Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Chris_B

    NEWS

    • ioBroker@Smart Living Forum Solingen, 14.06. - Agenda added

    • ioBroker goes Matter ... Matter Adapter in Stable

    • Monatsrückblick - April 2025

    C
    • Profile
    • Following 1
    • Followers 0
    • Topics 9
    • Posts 133
    • Best 8
    • Groups 2

    Chris_B

    @Chris_B

    11
    Reputation
    46
    Profile views
    133
    Posts
    0
    Followers
    1
    Following
    Joined Last Online
    Location Horgen, Switzerland

    Chris_B Follow
    Pro Starter

    Best posts made by Chris_B

    • RE: Huawei Sun2000 & ioBroker via JS script funktioniert

      @bishop Hallo zusammen. Nach längerer Abwesenheit endlich eine neue Version des Skripts. Das beinhaltet (endlich) einen Übersetzung von vielen Zuständen in lesbaren Text. So ist bspw. der Inverterzustand jetz nicht mehr eine Zahl, sondern ein lesbarer Text, bspw. "On-grid" oder "Standby: no irradiation". Das gleiche ist für die Batterie- und die Batterystack Zustände umgesetzt.

      Der Kommentar von @bolliy habe ich noch nicht umgesetzt, schaue ich mir noch an.

      Das Ganze findet sich, inklusive erweiterter Beschreibung auf Github:
      Github Sun2000
      Gruss, Christian

      posted in ioBroker Allgemein
      C
      Chris_B
    • RE: Huawei Sun2000 & ioBroker via JS script funktioniert

      @hussi Am besten einmal meine (neue) Github Seite anschauen. Dort sollte alles im Readme File erklärt sein. Ich werde das Readme in nächster Zeit noch erweitern und verbessern. Gruss

      https://github.com/ChrisBCH/SunLuna2000_iobroker

      posted in ioBroker Allgemein
      C
      Chris_B
    • RE: Huawei Sun2000 & ioBroker via JS script funktioniert

      @sweatchuck
      Hallo
      Hier mein aktueller Stand des Skripts. Bitte beachten:

      • Das Skript ist noch NICHT fertig. Ich werde in den nächsten Tagen noch weitere Verbesserungen vornehmen.
      • Unter client.connectTCP("192.168.0.0", { port: 502 }); die eigene TCP-IP Adresse des INverters angeben
      • Verwendung des Skripts auf eigene Verantwortung.
        Das Skript erzeugt neu noch zusätzliche Variable unter Solarpower.Derived.XXX. Die Beschreibung der Variable ist meist selbsterklärend.
        Ich werde in den nächsten Tagen und Wochen noch folgendes erweitern:
      1. Am Ende jedes Tages die aktuellen Werte in ein File schreiben, zur Analyse in bspw. Excel.
      2. Den Tagesverbrauch ausgeben (wie im Huawei Portal)
      3. Den Modbus-Trafic verringern (bspw. Nachts)
      4. Mein UI verbessern
        Hier mein aktuelles UI und das Skript.

      c6e56fff-e6e6-4cbd-b19b-017c56317b72-grafik.png

      // From iobroker Forum: "Huawei Sun2000 & ioBroker via JS script funktioniert"
      // https://forum.iobroker.net/topic/53005/huawei-sun2000-iobroker-via-js-script-funktioniert
      //
      
      createState("javascript.0.Solarpower.Derived.BatteryOverview", "",  {read: true, write: true, name: "Battery Overview SOC"});
      createState("javascript.0.Solarpower.Derived.HouseConsumption", "",  {read: true, write: true, name: "Consumption of House", unit: "W"});
      createState("javascript.0.Solarpower.Derived.YieldToday", "",  {read: true, write: true, name: "Yield Today", unit: "kW"});
      createState("javascript.0.Solarpower.Derived.IsBatteryLoading", 0,  {read: true, write: true, name: "Luna 2000 Battery is loading", type: "number"});
      createState("javascript.0.Solarpower.Derived.IsGridExporting", 0,  {read: true, write: true, name: "Exporting Power to Grid", type: "number"});
      createState("javascript.0.Solarpower.Derived.PeakPanelPower", 0,  {read: true, write: true, name: "Peak panel power today"});
      createState("javascript.0.Solarpower.Derived.GridExportSum", 0,  {read: true, write: true, name: "Total export to grid", unit: "kWh"});
      createState("javascript.0.Solarpower.Derived.GridImportSum", 0,  {read: true, write: true, name: "Total import from grid", unit: "kWh"});
      createState("javascript.0.Solarpower.Derived.GridExportToday", 0,  {read: true, write: true, name: "Export to grid today", unit: "kWh"});
      createState("javascript.0.Solarpower.Derived.GridImportToday", 0,  {read: true, write: true, name: "Import from grid today", unit: "kWh"});
      
      
      var ModbusRTU = require("modbus-serial");
      var client = new ModbusRTU();
      var testCreateState = 0;
      
      var modbusErrorMessages =
      [   "Unknown error",
          "Illegal function (device does not support this read/write function)",
          "Illegal data address (register not supported by device)",
          "Illegal data value (value cannot be written to this register)",
          "Slave device failure (device reports internal error)",
          "Acknowledge (requested data will be available later)",
          "Slave device busy (retry request again later)"
      ];
      
      // open connection to a tcp line
      client.setTimeout(10000);
      
      // Enter your inverter modbus IP and port here:
      client.connectTCP("192.168.0.0", { port: 502 });
      // Enter the Modbus-IDs of your Sun2000 inverters here (example for two inverters): const ModBusIDs = [16, 1];
      const ModBusIDs = [1];
      // On which Modbus-ID can we reach the power meter? (via Sun2000!)
      const PowerMeterID = 0;
      // Enter your battery stack setup. 2 dimensional array, e.g. [[3, 2], [3, 0]] means:
      // First inverter has two battery stacks with 3 + 2 battery modules
      // while second inverter has only one battery stack with 3 battery modules
      const BatteryUnits = [[3, 0]];
      
      // These register spaces need to be read:
      const RegisterSpacesToReadContinuously = [[30000, 81], [37100, 114], [32000, 116], [37000, 68],  [37700, 100], [37800, 100], [38200, 100], [38300, 100], [38400, 100], [35300, 40]];
      var RegisterSpacesToReadContinuouslyPtr = 0;
      
      var GlobalDataBuffer = new Array(2);
      for ( var i=0; i < ModBusIDs.length; i++)
      {
          GlobalDataBuffer[i] = new Array(50000); // not optimized....
      }
      
      
      // Some helper functions:
      
      function readUnsignedInt16(array)
      {   return array[0];
      }
      
      function readUnsignedInt32(array)
      {   return array[0] * 256 * 256 + array[1];
      }
      
      function readSignedInt16(array)
      {   var value = 0;
          if (array[0] > 32767)   value = array[0] - 65535; 
              else                value = array[0];
          return value;
      }
      
      function readSignedInt32(array)
      {   var value = 0;
          for (var i = 0; i < 2; i++) { value = (value << 16) | array[i]; }
          return value;
      }
      
      function getU16(dataarray, index)
      {   return readUnsignedInt16(dataarray.slice(index, index+1));
      }
      
      function getU32(dataarray, index)
      {   return readUnsignedInt32(dataarray.slice(index, index+2));
      }
      
      function getI16(dataarray, index)
      {   return readSignedInt16(dataarray.slice(index, index+1));
      }
      
      function getI32(dataarray, index)
      {   return readSignedInt32(dataarray.slice(index, index+2));
      }
      
      function getString(dataarray, index, length)
      {   var shortarray = dataarray.slice(index, index+length);
          var bytearray = [];
          for (var i = 0; i < length; i++)
          {   bytearray.push(dataarray[index+i] >> 8);
              bytearray.push(dataarray[index+i] & 0xff);
          }       
          var value =  String.fromCharCode.apply(null, bytearray);    
          return value;
      }
      
      function getZeroTerminatedString(dataarray, index, length)
      {   var shortarray = dataarray.slice(index, index+length);
          var bytearray = [];
          for(var i = 0; i < length; i++)
          {   bytearray.push(dataarray[index+i] >> 8);
              bytearray.push(dataarray[index+i] & 0xff);
          }       
          var value =  String.fromCharCode.apply(null, bytearray);    
          var value2 = new String(value).trim();
          return value2;
      }
      
      function forcesetState(objectname, value, options)
      //------------------------------------------------
      // perform createState() only if variable does not yet exist, and perform the check via existsState() only once for each processing round
      {   if (testCreateState == 0)
          {   if (!existsState("javascript.0." + objectname)) { createState(objectname, value, options); }
              else                                            { setState(objectname, value); testCreateState = 1; }
          } else
          {   setState(objectname, value);
          }
      }  
      
      
      // Functions to map registers into ioBreaker objects
      
      function ProcessOptimizers(id)
      //----------------------------
      {
          forcesetState("Solarpower.Huawei.Inverter." + id + ".OptimizerTotalNumber",     getU16(GlobalDataBuffer[id-1], 37200), {name: "", unit: ""});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".OptimizerOnlineNumber",    getU16(GlobalDataBuffer[id-1], 37201), {name: "", unit: ""});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".OptimizerFeatureData",     getU16(GlobalDataBuffer[id-1], 37202), {name: "", unit: ""});
      }
      
      function ProcessInverterPowerAdjustments(id)
      //------------------------------------------
      {
          forcesetState("Solarpower.Huawei.Inverter." + id + ".ActiveAdjustement.ActiveAdjustementMode",     getU16(GlobalDataBuffer[id-1], 35300), {name: "", unit: ""});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".ActiveAdjustement.ActiveAdjustementValue",    getU32(GlobalDataBuffer[id-1], 35301), {name: "", unit: ""}); // Note: This might be an error in the manual. It says register 35302 with quantity 2, but on 35303 is already the next value.
          forcesetState("Solarpower.Huawei.Inverter." + id + ".ActiveAdjustement.ActiveAdjustementCommand",  getU16(GlobalDataBuffer[id-1], 35303), {name: "", unit: ""});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".ActiveAdjustement.ReactiveAdjustementMode",   getU16(GlobalDataBuffer[id-1], 35304), {name: "", unit: ""});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".ActiveAdjustement.ReactiveAdjustementValue",  getU32(GlobalDataBuffer[id-1], 35305), {name: "", unit: ""});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".ActiveAdjustement.ReactiveAdjustementCommand",getU16(GlobalDataBuffer[id-1], 35307), {name: "", unit: ""});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".ActiveAdjustement.PowerMeterActivePower",     getI32(GlobalDataBuffer[id-1], 35313), {name: "", unit: ""});
      }
      
      function ProcessBattery(id)
      //-------------------------
      {
          // Battery registers 1-15 (Stack 1 related)
          if ( BatteryUnits[id-1][0] > 0)
          {
              forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.RunningStatus",               getU16(GlobalDataBuffer[id-1], 37000), {name: "", unit: ""});
              forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.ChargeAndDischargePower",     getI32(GlobalDataBuffer[id-1], 37001), {name: "Charge and Discharge Power", unit: "W"});
              forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.BusVoltage",                  getU16(GlobalDataBuffer[id-1], 37003) / 10, {name: "Busvoltage", unit: "V"});
              forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.BatterySOC",                  getU16(GlobalDataBuffer[id-1], 37004) / 10, {name: "Battery SOC", unit: "%"});
              forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.WorkingMode",                 getU16(GlobalDataBuffer[id-1], 37006), {name: "Working Mode", unit: ""});
              forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.RatedChargePower",            getU32(GlobalDataBuffer[id-1], 37007), {name: "", unit: "W"});
              forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.RatedDischargePower",         getU32(GlobalDataBuffer[id-1], 37009), {name: "", unit: "W"});
              forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.FaultID",                     getU16(GlobalDataBuffer[id-1], 37014), {name: "", unit: ""});
              forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.CurrentDayChargeCapacity",    getU32(GlobalDataBuffer[id-1], 37015) / 100, {name: "", unit: "kWh"});
              forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.CurrentDayDischargeCapacity", getU32(GlobalDataBuffer[id-1], 37017) / 100, {name: "", unit: "kWh"});
              forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.BusCurrent",                  getI16(GlobalDataBuffer[id-1], 37021) / 10, {name: "Buscurrent", unit: "A"});
              forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.BatteryTemperature",          getI16(GlobalDataBuffer[id-1], 37022) / 10, {name: "Battery Temperatue", unit: "°C"});
              forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.RemainingChargeDischargeTime",getU16(GlobalDataBuffer[id-1], 37025), {name: "", unit: "mins"});
              //forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.DCDCversion",                 getZeroTerminatedString(GlobalDataBuffer[id-1], 37026, 10), {name: "", unit: ""});
              //forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.BMSversion",                  getZeroTerminatedString(GlobalDataBuffer[id-1], 37036, 10), {name: "", unit: ""});
          }
          // Battery registers 16+17 (Storage-related)
          forcesetState("Solarpower.Huawei.Inverter." + id + ".Battery.MaximumChargePower",                     getU32(GlobalDataBuffer[id-1], 37046), {name: "", unit: "W"});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".Battery.MaximumDischargePower",                  getU32(GlobalDataBuffer[id-1], 37048), {name: "", unit: "W"});
      
          // Battery register 18-20 (Stack 1 related)
          if (BatteryUnits[id-1][0] > 0)
          {
              forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.SN",                          getZeroTerminatedString(GlobalDataBuffer[id-1], 37052, 10), {name: "Serialnumber", unit: ""});       
              forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.TotalCharge",                 getU32(GlobalDataBuffer[id-1], 37066) / 100, {name: "", unit: "kWh"});
              forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.TotalDischarge",              getU32(GlobalDataBuffer[id-1], 37068) / 100, {name: "", unit: "kWh"});
          }
          // Battery register 21-31 (Stack 2 related)
          if ( BatteryUnits[id-1][1] > 0)
          {
              forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.2.SN",                          getZeroTerminatedString(GlobalDataBuffer[id-1], 37700, 10), {name: "Serialnumber", unit: ""});        
              forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.2.BatterySOC",                  getU16(GlobalDataBuffer[id-1], 37738) / 10, {name: "", unit: "%"});
              forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.2.RunningStatus",               getU16(GlobalDataBuffer[id-1], 37741), {name: "", unit: ""});
              forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.2.ChargeAndDischargePower",     getI32(GlobalDataBuffer[id-1], 37743), {name: "", unit: "W"});
              forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.2.CurrentDayChargeCapacity",    getU32(GlobalDataBuffer[id-1], 37746) / 100, {name: "", unit: "kWh"});
              forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.2.CurrentDayDischargeCapacity", getU32(GlobalDataBuffer[id-1], 37748) / 100, {name: "", unit: "kWh"});
              forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.2.BusVoltage",                  getU16(GlobalDataBuffer[id-1], 37750) / 10, {name: "", unit: "V"});
              forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.2.BusCurrent",                  getI16(GlobalDataBuffer[id-1], 37751) / 10, {name: "", unit: "A"});
              forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.2.BatteryTemperature",          getI16(GlobalDataBuffer[id-1], 37752) / 10, {name: "", unit: "°C"});
              forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.2.TotalCharge",                 getU32(GlobalDataBuffer[id-1], 37753) / 100, {name: "", unit: "kWh"});
              forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.2.TotalDischarge",              getU32(GlobalDataBuffer[id-1], 37755) / 100, {name: "", unit: "kWh"});
          }
          // Battery register 32-41 (Storage related)
          forcesetState("Solarpower.Huawei.Inverter." + id + ".Battery.RatedCapacity", getU32(GlobalDataBuffer[id-1], 37758) / 1, {name: "", unit: "Wh"});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".Battery.SOC", getU16(GlobalDataBuffer[id-1], 37760) / 10, {name: "", unit: "%"});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".Battery.RunningStatus", getU16(GlobalDataBuffer[id-1], 37762) / 1, {name: "", unit: ""});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".Battery.BusVoltage", getU16(GlobalDataBuffer[id-1], 37763) / 10, {name: "", unit: "V"});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".Battery.BusCurrent", getI16(GlobalDataBuffer[id-1], 37764) / 10, {name: "", unit: "A"});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".Battery.ChargeAndDischargePower", getI32(GlobalDataBuffer[id-1], 37765) / 1, {name: "", unit: "W"});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".Battery.TotalCharge", getU32(GlobalDataBuffer[id-1], 37780) / 100, {name: "", unit: "kWh"});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".Battery.TotalDischarge", getU32(GlobalDataBuffer[id-1], 37782) / 100, {name: "", unit: "kWh"});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".Battery.CurrentDayChargeCapacity", getU32(GlobalDataBuffer[id-1], 37784) / 100, {name: "", unit: "kWh"});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".Battery.CurrentDayDischargeCapacity", getU32(GlobalDataBuffer[id-1], 37786) / 100, {name: "Current DayDiscarge ", unit: "kWh"});
      
          // Battery registers 42+43 (Battery stack related)   
          if ( BatteryUnits[id-1][1] > 0)
          {
              forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.2.SoftwareVersion",    getZeroTerminatedString(GlobalDataBuffer[id-1], 37814, 8), {name: "Softwareversion", unit: ""});
          }
          
          if ( BatteryUnits[id-1][0] > 0)
          {
              forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.SoftwareVersion",    getZeroTerminatedString(GlobalDataBuffer[id-1], 37799, 8), {name: "Softwareversion", unit: ""});
          }
      
          // Registers 44 to 98: (Battery pack related)
          for(var i = 1; i <= 2; i++)
          {        
              if(BatteryUnits[id-1][i-1] >= 0)
              {            
                  for(var j = 1; j <= BatteryUnits[id-1][i-1]; j++)
                  {
                      //[[38200, 38242, 38284] [38326, 38368, 38410]]; (+42 for each battery pack, +126 for each stack)
                      forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".SN",                getZeroTerminatedString(GlobalDataBuffer[id-1], 38200+(i-1)*126+(j-1)*42, 6), {name: "", unit: ""});
                      forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".FirmwareVersion",   getZeroTerminatedString(GlobalDataBuffer[id-1], 38210+(i-1)*126+(j-1)*42, 8), {name: "", unit: ""});
                      forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".WorkingStatus",     getU16(GlobalDataBuffer[id-1], 38228+(i-1)*126+(j-1)*42), {name: "", unit: ""});
                      forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".BatterySOC",        getU16(GlobalDataBuffer[id-1], 38229+(i-1)*126+(j-1)*42) / 10, {name: "", unit: "%"});
                      forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".ChargeAndDischargePower", getI32(GlobalDataBuffer[id-1], 38233+(i-1)*126+(j-1)*42) / 1000, {name: "", unit: "kW"});
                      forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".Voltage",           getU16(GlobalDataBuffer[id-1], 38235+(i-1)*126+(j-1)*42) / 10, {name: "", unit: "V"});
                      forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".Current",           getI16(GlobalDataBuffer[id-1], 38236+(i-1)*126+(j-1)*42) / 10, {name: "", unit: "A"});
                      forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".TotalCharge",       getU32(GlobalDataBuffer[id-1], 38238+(i-1)*126+(j-1)*42) / 100, {name: "", unit: "kWh"});
                      forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".TotalDischarge",    getU32(GlobalDataBuffer[id-1], 38240+(i-1)*126+(j-1)*42) / 100, {name: "", unit: "kWh"});
      
                      // [[38452, 38454, 38456][38458, 38460, 38462]] ( +2 for each pack, +6 for each stack)
                      createState("Solarpower.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".MaxTemperature", getI16(GlobalDataBuffer[id-1], 38452+(i-1)*6+(j-1)*2) / 10, {name: "", unit: "°C"});
                      createState("Solarpower.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".MinTemperature", getI16(GlobalDataBuffer[id-1], 38453+(i-1)*6+(j-1)*2) / 10, {name: "", unit: "°C"});
                  }
              }        
          }
      
          // Battery registers 110-141 are not supported by this script yet!
      }
      
      
      function ProcessPowerMeterStatus()
      //--------------------------------
      {       
          forcesetState("Solarpower.Huawei.Meter.Status",                   getU16(GlobalDataBuffer[PowerMeterID], 37100), {name: "", unit: ""});
          forcesetState("Solarpower.Huawei.Meter.VoltageL1",                getI32(GlobalDataBuffer[PowerMeterID], 37101)  / 10, {name: "", unit: "V"});
          forcesetState("Solarpower.Huawei.Meter.VoltageL2",                getI32(GlobalDataBuffer[PowerMeterID], 37103)  / 10, {name: "", unit: "V"});
          forcesetState("Solarpower.Huawei.Meter.VoltageL3",                getI32(GlobalDataBuffer[PowerMeterID], 37105)  / 10, {name: "", unit: "V"});
          forcesetState("Solarpower.Huawei.Meter.CurrentL1",                getI32(GlobalDataBuffer[PowerMeterID], 37107)  / 100, {name: "", unit: "A"});
          forcesetState("Solarpower.Huawei.Meter.CurrentL2",                getI32(GlobalDataBuffer[PowerMeterID], 37109)  / 100, {name: "", unit: "A"});
          forcesetState("Solarpower.Huawei.Meter.CurrentL3",                getI32(GlobalDataBuffer[PowerMeterID], 37111) / 100, {name: "", unit: "A"});
          forcesetState("Solarpower.Huawei.Meter.ActivePower",              getI32(GlobalDataBuffer[PowerMeterID], 37113) / 1, {name: "", unit: "W"});
          forcesetState("Solarpower.Huawei.Meter.ReactivePower",            getI32(GlobalDataBuffer[PowerMeterID], 37115) / 1, {name: "", unit: "Var"});
          forcesetState("Solarpower.Huawei.Meter.PowerFactor",              getI16(GlobalDataBuffer[PowerMeterID], 37117) / 1000, {name: "", unit: ""});
          forcesetState("Solarpower.Huawei.Meter.GridFrequency",            getI16(GlobalDataBuffer[PowerMeterID], 37118) / 100, {name: "", unit: "Hz"});
          forcesetState("Solarpower.Huawei.Meter.PositiveActiveEnergy",     getI32(GlobalDataBuffer[PowerMeterID], 37119) / 100, {name: "", unit: "kWh"});
          forcesetState("Solarpower.Huawei.Meter.ReverseActiveEnergy",      getI32(GlobalDataBuffer[PowerMeterID], 37121) / 100, {name: "", unit: "kWh"});
          forcesetState("Solarpower.Huawei.Meter.AccumulatedReactivePower", getI32(GlobalDataBuffer[PowerMeterID], 37123) / 100, {name: "", unit: "kVarh"});
          //forcesetState("Solarpower.Huawei.Meter.MeterType",                getU16(GlobalDataBuffer[PowerMeterID], 37125), {name: "", unit: ""});
          forcesetState("Solarpower.Huawei.Meter.VoltageL1-L2",             getI32(GlobalDataBuffer[PowerMeterID], 37126) / 10, {name: "", unit: "V"});
          forcesetState("Solarpower.Huawei.Meter.VoltageL2-L3",             getI32(GlobalDataBuffer[PowerMeterID], 37128) / 10, {name: "", unit: "V"});
          forcesetState("Solarpower.Huawei.Meter.VoltageL3-L1",             getI32(GlobalDataBuffer[PowerMeterID], 37130) / 10, {name: "", unit: "V"});
          forcesetState("Solarpower.Huawei.Meter.ActivePowerL1",            getI32(GlobalDataBuffer[PowerMeterID], 37132) / 1, {name: "", unit: "W"});
          forcesetState("Solarpower.Huawei.Meter.ActivePowerL2",            getI32(GlobalDataBuffer[PowerMeterID], 37134) / 1, {name: "", unit: "W"});
          forcesetState("Solarpower.Huawei.Meter.ActivePowerL3",            getI32(GlobalDataBuffer[PowerMeterID], 37136) / 1, {name: "", unit: "W"});
          //forcesetState("Solarpower.Huawei.Meter.MeterModel",               getU16(GlobalDataBuffer[PowerMeterID], 37138), {name: "", unit: ""});
      }
      
      function ProcessInverterStatus(id)
      //--------------------------------
      {
          forcesetState("Solarpower.Huawei.Inverter." + id + ".State1", getU16(GlobalDataBuffer[id-1], 32000), {name: "", unit: ""});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".State2", getU16(GlobalDataBuffer[id-1], 32001), {name: "", unit: ""});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".State3", getU16(GlobalDataBuffer[id-1], 32002), {name: "", unit: ""});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".Alarm1", getU16(GlobalDataBuffer[id-1], 32008), {name: "", unit: ""});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".Alarm2", getU16(GlobalDataBuffer[id-1], 32009), {name: "", unit: ""});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".Alarm3", getU16(GlobalDataBuffer[id-1], 32010), {name: "", unit: ""});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".String.1_Voltage",       getI16(GlobalDataBuffer[id-1], 32016) / 10  , {name: "", unit: "V"});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".String.1_Current",       getI16(GlobalDataBuffer[id-1], 32017) / 100 , {name: "", unit: "A"});
          //forcesetState("Solarpower.Huawei.Inverter." + id + ".String.2_Voltage",       getI16(GlobalDataBuffer[id-1], 32018) / 10  , {name: "", unit: "V"});
          //forcesetState("Solarpower.Huawei.Inverter." + id + ".String.2_Current",       getI16(GlobalDataBuffer[id-1], 32019) / 100 , {name: "", unit: "A"});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".InputPower",             getI32(GlobalDataBuffer[id-1], 32064) / 1000, {name: "", unit: "kW"});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1-L2_Voltage",           getU16(GlobalDataBuffer[id-1], 32066) / 10  , {name: "", unit: "V"});      
          forcesetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2-L3_Voltage",           getU16(GlobalDataBuffer[id-1], 32067) / 10  , {name: "", unit: "V"});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3-L1_Voltage",           getU16(GlobalDataBuffer[id-1], 32068) / 10  , {name: "", unit: "V"});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1_Voltage",            getU16(GlobalDataBuffer[id-1], 32069) / 10  , {name: "", unit: "V"});                              
          forcesetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2_Voltage",            getU16(GlobalDataBuffer[id-1], 32070) / 10  , {name: "", unit: "V"});                                                  
          forcesetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3_Voltage",            getU16(GlobalDataBuffer[id-1], 32071) / 10  , {name: "", unit: "V"});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1_Current",         getI32(GlobalDataBuffer[id-1], 32072) / 1000, {name: "", unit: "A"});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2_Current",         getI32(GlobalDataBuffer[id-1], 32074) / 1000, {name: "", unit: "A"});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3_Current",         getI32(GlobalDataBuffer[id-1], 32076) / 1000, {name: "", unit: "A"});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".PeakActivePowerDay",     getI32(GlobalDataBuffer[id-1], 32078) / 1000, {name: "", unit: "kW"});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".ActivePower",            getI32(GlobalDataBuffer[id-1], 32080) / 1000, {name: "", unit: "kW"});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".ReactivePower",          getI32(GlobalDataBuffer[id-1], 32082) / 1000, {name: "", unit: "kVar"});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".PowerFactor",            getI16(GlobalDataBuffer[id-1], 32084) / 1000, {name: "", unit: ""});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".GridFrequency",          getU16(GlobalDataBuffer[id-1], 32085) / 100 , {name: "", unit: "Hz"});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".Efficiency",             getU16(GlobalDataBuffer[id-1], 32086) / 100 , {name: "", unit: "%"});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".InternalTemperature",    getI16(GlobalDataBuffer[id-1], 32087) / 10  , {name: "", unit: "°C"});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".InsulationResistance",   getU16(GlobalDataBuffer[id-1], 32088) / 1000, {name: "", unit: "MOhm"});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".DeviceStatus",              getU16(GlobalDataBuffer[id-1], 32089), {name: "", unit: ""});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".FaultCode",                 getU16(GlobalDataBuffer[id-1], 32090), {name: "", unit: ""});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".StartupTime",               getU16(GlobalDataBuffer[id-1], 32091), {name: "", unit: ""});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".ShutdownTime",              getU16(GlobalDataBuffer[id-1], 32093), {name: "", unit: ""});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".AccumulatedEnergyYield",    getU32(GlobalDataBuffer[id-1], 32106) / 100, {name: "", unit: "kWh"});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".DailyEnergyYield",          getU32(GlobalDataBuffer[id-1], 32114) / 100, {name: "", unit: "kWh"});
      }
      
      
      function ProcessDeviceInfo(id)
      //----------------------------
      {      
          // Note: Manual says its quantitiy is 15, but that is the number (+1) of 8bit characters
          forcesetState("Solarpower.Huawei.Inverter." + id + ".Model",  getZeroTerminatedString(GlobalDataBuffer[id-1], 30000, 8), {name: "", unit: ""}); 
          forcesetState("Solarpower.Huawei.Inverter." + id + ".SN",     getZeroTerminatedString(GlobalDataBuffer[id-1], 30015, 6), {name: "", unit: ""});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".PN",     getZeroTerminatedString(GlobalDataBuffer[id-1], 30025, 6), {name: "", unit: ""});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".ModelID",           getU16(GlobalDataBuffer[id-1], 30070), {name: "", unit: ""});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".PVStrings",         getU16(GlobalDataBuffer[id-1], 30071), {name: "", unit: ""});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".MPPTrackers",       getU16(GlobalDataBuffer[id-1], 30072), {name: "", unit: ""});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".MaxRatedPower",     getU32(GlobalDataBuffer[id-1], 30073) / 1000, {name: "", unit: "kW"});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".MaxActivePower",    getU32(GlobalDataBuffer[id-1], 30075) / 1000, {name: "", unit: "kW"});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".MaxApparentPower",  getU32(GlobalDataBuffer[id-1], 30077) / 1000, {name: "", unit: "kVA"});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".MaxReactivePowerToGrid",        getI32(GlobalDataBuffer[id-1], 30079) / 1000, {name: "", unit: "kVAr"});
          forcesetState("Solarpower.Huawei.Inverter." + id + ".MaxReactivePowerFromGrid",      getI32(GlobalDataBuffer[id-1], 30081) / 1000, {name: "", unit: "kVAr"});
      }
      
      
      function readRegisterSpace(id, address, length)
      //---------------------------------------------
      {
          client.setID(ModBusIDs[id-1]);
          client.readHoldingRegisters(address, length, function(err, data)
          {   
              if (err)
              {   console.warn("Error received reading address " + address + " from id: " + ModBusIDs[id-1] + " with error: " + modbusErrorMessages[err.modbusCode]);            
              }
              else
              {   console.debug("Read data from id/address " + ModBusIDs[id-1] + "/" + address + "\nData is: " + data.data);
                  for (var i = 0; i < length; i++) GlobalDataBuffer[id-1][address+i] = data.data[i];
              }
          });
      }
      
      
      function ProcessData()
      //--------------------
      {
          console.debug("Processing new data...");   // this was originally .log
          for ( var i = 1; i <= ModBusIDs.length; i++)
          {
              ProcessDeviceInfo(i);
              ProcessInverterStatus(i);
              ProcessBattery(i);
              //ProcessInverterPowerAdjustments(i);
              ProcessOptimizers(i); 
          }    
          ProcessPowerMeterStatus();
      
          // get SOC of all batteries and combine to one string
          var BatOverview = getState("javascript.0.Solarpower.Huawei.Inverter.1.Batterystack.1.Battery1.BatterySOC").val + "%, " +
              getState("javascript.0.Solarpower.Huawei.Inverter.1.Batterystack.1.Battery2.BatterySOC").val + "%, " +
              getState("javascript.0.Solarpower.Huawei.Inverter.1.Batterystack.1.Battery3.BatterySOC").val + "%";
          setState("javascript.0.Solarpower.Derived.BatteryOverview", BatOverview);
      
          // determine peak panel power
          var PanelPower = getState("javascript.0.Solarpower.Huawei.Inverter.1.InputPower").val;
          var PanelMax = getState("javascript.0.Solarpower.Derived.PeakPanelPower").val;
          if (PanelPower > PanelMax) setState("javascript.0.Solarpower.Derived.PeakPanelPower", PanelPower);
          
          // determine power used by house
          setState("javascript.0.Solarpower.Derived.HouseConsumption", getState("javascript.0.Solarpower.Huawei.Inverter.1.ActivePower").val * 1000 -
              getState("javascript.0.Solarpower.Huawei.Meter.ActivePower").val);
      
          // determine yield today
          setState("javascript.0.Solarpower.Derived.YieldToday", getState("javascript.0.Solarpower.Huawei.Inverter.1.DailyEnergyYield").val +
              getState("javascript.0.Solarpower.Huawei.Inverter.1.Batterystack.1.CurrentDayChargeCapacity").val -
              getState("javascript.0.Solarpower.Huawei.Inverter.1.Batterystack.1.CurrentDayDischargeCapacity").val)
      
          // determine if battery is loading
          setState("javascript.0.Solarpower.Derived.IsBatteryLoading", getState("javascript.0.Solarpower.Huawei.Inverter.1.Batterystack.1.ChargeAndDischargePower").val > 0 ? 0 : 1);
      
          // determine if power is imported or exported
          setState("javascript.0.Solarpower.Derived.IsGridExporting", getState("javascript.0.Solarpower.Huawei.Meter.ActivePower").val > 0 ? 1 : 0);
      
          // compute export and import today
          setState("javascript.0.Solarpower.Derived.GridExportToday", getState("javascript.0.Solarpower.Huawei.Meter.PositiveActiveEnergy").val - getState("javascript.0.Solarpower.Derived.GridExportSum").val);
          setState("javascript.0.Solarpower.Derived.GridImportToday", getState("javascript.0.Solarpower.Huawei.Meter.ReverseActiveEnergy").val - getState("javascript.0.Solarpower.Derived.GridImportSum").val);
          
          console.debug("Processing done!");  // this was originally .log
      }
      
      
      var triggerprocessing = 0; 
      var currentinverter = 1;
      
      setInterval(function()
      // -------------------
      // This is the main function triggering a  read via modbus-tcp every 2 seconds - changed to 5 seconds
      // Processing of data is triggered as soon as one complete set of registers is copied
      // with 5 seconds, new values are displyed every 50 seconds
      {
          if (triggerprocessing == 1)
          {
              triggerprocessing = 0;
              ProcessData();
              testCreateState = 0;       
          }      
         
          // this was originally also a .log
          console.debug("Triggering read of inverter " + currentinverter + " at address " +
              RegisterSpacesToReadContinuously[RegisterSpacesToReadContinuouslyPtr][0] +
              " with length " +  RegisterSpacesToReadContinuously[RegisterSpacesToReadContinuouslyPtr][1]);
          
          readRegisterSpace(currentinverter, RegisterSpacesToReadContinuously[RegisterSpacesToReadContinuouslyPtr][0], RegisterSpacesToReadContinuously[RegisterSpacesToReadContinuouslyPtr][1]); 
          RegisterSpacesToReadContinuouslyPtr++;               
          if (RegisterSpacesToReadContinuouslyPtr >= RegisterSpacesToReadContinuously.length)
          {
              RegisterSpacesToReadContinuouslyPtr = 0;
              currentinverter++
              if (currentinverter > ModBusIDs.length)
              {
                  currentinverter = 1;  
                  triggerprocessing = 1;                    
              }
          }     
      }, 5000);
      
      
      // one minute before midnight - perform housekeeping actions
      schedule("59 23 * * *", function ()
      {   
          // reset peak power for next day
          setState("javascript.0.Solarpower.Derived.PeakPanelPower", 0);
          // copy current export/import kWh - used to compute daily import/export in kWh
          setState("javascript.0.Solarpower.Derived.GridExportSum", getState("javascript.0.Solarpower.Huawei.Meter.PositiveActiveEnergy").val);
          setState("javascript.0.Solarpower.Derived.GridImportSum", getState("javascript.0.Solarpower.Huawei.Meter.ReverseActiveEnergy").val);
      });
      
      
      posted in ioBroker Allgemein
      C
      Chris_B
    • RE: Huawei Sun2000 & ioBroker via JS script funktioniert

      @hussi Dieser Typo und andere kleinere Fehler, sollten eigentlich in meinem Skript oben korrigiert worden sein...
      Gruss

      posted in ioBroker Allgemein
      C
      Chris_B
    • RE: Huawei Sun2000 & ioBroker via JS script funktioniert

      @r4 und an alle die es interessiert:
      Ich habe die Anregung der schnell und langsam zu lesenden Registersätze nun auch in 'mein' Skript implementiert - die Idee gefällt mir. Ich habe es allerdings etwas anders umgesetzt:
      Mein Skript liest total 9 Registersätze; die ersten n = RegFast (in meinem Fall 5) werden schnell gelesen, die restlichen langsam. Über die Variable RegFastMod wird bestimmt, was langsam bedeutet. RegFastMod = 10 bedeutet, dass nur jedes zehnte Mal alle Register gelesen werden.
      Ich habe im Skript noch einige Detailverbesserungen vorgenommen.
      In einer nächste Variante möchte ich mich noch dem GlobalDataBuffer[] annehmen. Dieser ist ja (und das steht auch im Skript) nicht optimiert, und benützt eine monströse (sorry) Grösse. Das kommt dann noch.
      Hier ein Link zu 'meinem' Skript (diesmal als Link, da es mit 'Code' Probleme gab bei 'grossen' Dateien)
      Sun2000.js
      Gruss

      posted in ioBroker Allgemein
      C
      Chris_B
    • RE: Huawei Sun2000 & ioBroker via JS script funktioniert

      @R4 und alle, die es interessiert.
      Ich habe jetzt mein Skript (früher Version 3 genannt) nun auf Github.
      Das macht es einfacher die aktuelle Version zu finden. Das ist der erste Versuch.
      Das Readme File ist noch minimal, das werde ich stark ausbauen um Fragen zum Skript zu klären. Im Wesentlichen Dinge, die hier irgendwann einmal erwähnt wurden.
      Hier der Link:

      https://github.com/ChrisBCH/SunLuna2000_iobroker

      posted in ioBroker Allgemein
      C
      Chris_B
    • RE: Huawei Sun2000 & ioBroker via JS script funktioniert

      @badsnoopy667 Hallo Jan. Momentan ist eine Schreibfunktion noch nicht implementiert. Es gibt aber einen Vorschlag von @R4 , der relativ leicht zu implementieren sein sollte. Ich möchte das in einer nächsten Version auch noch implementieren. Weiss aber noch nicht, wann cih dazu komme, da ich beruflich gerade ziemlich engagiert und unterwegs sein werde. Einfach etwas Geduld noch... Gruss

      posted in ioBroker Allgemein
      C
      Chris_B
    • RE: Huawei Sun2000 & ioBroker via JS script funktioniert

      Neues Skript auf Github. Folgende Änderungen:

      1. Das Skript liest mehr Batteriedaten, vor allem auch betreffen laden der Batterie aus dem Netz.
      2. Dokumentation ergänzt, vor allem auch das Issue zum Daily Yield ist jetzt beschrieben.

      Hier nchmals der Link:
      Github-Sun2000

      posted in ioBroker Allgemein
      C
      Chris_B

    Latest posts made by Chris_B

    • RE: Adapter zur Steuerung von Projektoren (PJLink / PJLinkV2)

      @jozu
      Ich weiss nicht, ob das Problem bei Dir weiterhin besteht. Hast Du eine Lösung gefunden?
      Ich habe heute den Adapter installiert und das gleiche Problem gehabt. Men Projektor: Epson LS12000.
      Meine 'Hack'-Lösung: Adapter nach dem Einschalten des Projektors via Javascript stoppen, danach bei Bedarf wieder starten. Was meinst Du?

      posted in ioBroker Allgemein
      C
      Chris_B
    • RE: Huawei Sun2000 & ioBroker via JS script funktioniert

      @psykokev Danke für den Hinweis, und ja, meine Anlage hat nur einen String. Die Berechnung kann man natürlich auch, wie Du es nennst 'dynamisch', so machen, dass ein oder zwei Strings für die Berechnung verwendet werden. Die Frage ist dann aber: Will ich diese separat oder zusammen ausgeben? Beides kann sinnvoll sein.
      Mir ist bewusst, dass das Skript auf meine Verhältnisse zugeschnitten ist. Ich mache in diesem Skript auch mehrheitlich nur das, was für mich sinnvoll ist. Sorry, das ist vielleicht egoistisch, ich habe habe (leider?) genug Anderes zu tun.
      @bolliy Aus genau dem Grund implementiere ich momentan das 'Schreiben' von Werten nicht. Ich brauche und möchte das momentan (noch?) nicht. Sorry. Die Async Methode interessiert mich allerdings...
      Ihr könnt gerne von Github einen Fork auf das Projekt machen und diese Dinge realisieren, oder das Skript für Euch selbst abändern...
      Gruss

      posted in ioBroker Allgemein
      C
      Chris_B
    • RE: Huawei Sun2000 & ioBroker via JS script funktioniert

      @bolliy Hallo Stephan.
      Ich habe versucht Deinen Vorschlag zu verstehen, ist mir leider nicht vollständig gelungen - bis jetzt. Also: readRegisterSpace wird durch ReadRegisterSpaceAsync ersetzt. Aber wie / wo wird ReadRegister(reg) im Skript verwendet, sorry ich steh auf dem Schlauch. Ich würde gerne das Skript entsprechend anpassen, aber ohne zu verstehen geht das nicht...
      Gruss

      posted in ioBroker Allgemein
      C
      Chris_B
    • RE: Huawei Sun2000 & ioBroker via JS script funktioniert

      @bishop Sorry, aber ich verstehe die Frage nicht. Ich bin kein Javascript Experte, aber im Skript selbst brauche ich das nicht. Für was brauchst Du das? Die Werte (Du nennst sie Datenpunkte) kann man Problemlos in Vis verwenden...
      Gruss

      posted in ioBroker Allgemein
      C
      Chris_B
    • RE: Huawei Sun2000 & ioBroker via JS script funktioniert

      @bishop Hallo zusammen. Nach längerer Abwesenheit endlich eine neue Version des Skripts. Das beinhaltet (endlich) einen Übersetzung von vielen Zuständen in lesbaren Text. So ist bspw. der Inverterzustand jetz nicht mehr eine Zahl, sondern ein lesbarer Text, bspw. "On-grid" oder "Standby: no irradiation". Das gleiche ist für die Batterie- und die Batterystack Zustände umgesetzt.

      Der Kommentar von @bolliy habe ich noch nicht umgesetzt, schaue ich mir noch an.

      Das Ganze findet sich, inklusive erweiterter Beschreibung auf Github:
      Github Sun2000
      Gruss, Christian

      posted in ioBroker Allgemein
      C
      Chris_B
    • RE: Huawei Sun2000 & ioBroker via JS script funktioniert

      @bolliy INteressanter Input. Muss ich mir anschauen. Ich veröffentliche gleich eine neue Version des Skripts (endlich, nach längerer Abwesenheit). Diese Version übersetzt nun Meldungen in verständliche Strings (bspw. den Zustand des Inverters). Deine Überlegungen sind allerdings da noch nicht eingebaut. Schau ich mir noch an und baue das ein - sofern ich es verstehe...
      Gruss

      posted in ioBroker Allgemein
      C
      Chris_B
    • RE: Huawei Sun2000 & ioBroker via JS script funktioniert

      @bishop Danke für die Frage.
      ich habe mich sehr lange nicht gemeldet. Ich habe genau das, und noch etwas mehr umgesetzt. Die Status von Inverter und Battery werden als Text ausgegeben. Zusätzlich werden gewisse Variable, welche im Standby der Battery nicht mehr zur Verfügung stehen entsprechend gesetzt, sodass diese dann in den Status 'standby' wechseln. Ich konnte das erst jetzt gut testen, da meine Anlage erst jetzt regelmässig in diesen Modus wechselt.
      Ich werde das so erweiterte Skript am Wochenende zur Verfügung stellen. Ich aknn nicht früher, zu viel zu tun...

      posted in ioBroker Allgemein
      C
      Chris_B
    • RE: Huawei Sun2000 & ioBroker via JS script funktioniert

      @baerengraben Ja, das ist auch noch ein Ausbau den ich machen wollte. Ich schau mir das an. Danke und Gruss

      posted in ioBroker Allgemein
      C
      Chris_B
    • RE: Huawei Sun2000 & ioBroker via JS script funktioniert

      @bahnuhr OK, sorry, habe nicht gesehen, dass du 2 Inverter hast. Also, ausmeiner Sicht, müsste das dann so aussehen:

      var currentinverter = 2;
      // Enter the Modbus-IDs of your Sun2000 inverters here (example for two inverters): const ModBusIDs = [16, 1];
      const ModBusIDs = [1, 2];
      // On which Modbus-ID can we reach the power meter? (via Sun2000!)
      const PowerMeterID = 0;
      // Enter your battery stack setup. 2 dimensional array, e.g. [[3, 2], [3, 0]] means:
      // First inverter has two battery stacks with 3 + 2 battery modules
      // while second inverter has only one battery stack with 3 battery modules
      const BatteryUnits = [[3, 0], [0, 0]];
      

      Der von @baerengraben angegebene Array für die BatteryUnits ist nicht korrekt. Es kann laufen, aber das Programm greift potentiell auf nicht definierte Daten zu. Es muss für jeden WR angegeben werden, wie der potentiell vorhandene Batterystack aufgebaut ist. In diesem Fall: Am ersten WR hängt ein einfacher Battery Stack mit 3 Modulen, am zweiten hängt nichts (und auch das sollte spezifiziert werden).
      Wichtig: PowerMeterID sagt, an welchem WR das PowerMeter hängt. In diesem Fall am erste WR.
      Was mir nicht ganz klar ist sind die ModBusIDs. Bei nur einem WR ist das [1], bei zwei würde ich es einmal wie von @baerengraben vorgeschlagen ausprobieren, oder sonst mit der zweiten Zahl spielen...
      Gruss

      Gruss

      posted in ioBroker Allgemein
      C
      Chris_B
    • RE: Huawei Sun2000 & ioBroker via JS script funktioniert

      @bahnuhr Hallo - ich glaube der einzige wirkliche Fehler ist, dass Du zwar zwei Strings, aber 'nur' einen Inverter hast. In diesem Sinne müsste folgendes gesetzt sein:

      var currentinverter = 1;
      
      // Enter the Modbus-IDs of your Sun2000 inverters here (example for two inverters): const ModBusIDs = [16, 1];
      const ModBusIDs = [1];
      // On which Modbus-ID can we reach the power meter? (via Sun2000!)
      const PowerMeterID = 0;
      // Enter your battery stack setup. 2 dimensional array, e.g. [[3, 2], [3, 0]] means:
      // First inverter has two battery stacks with 3 + 2 battery modules
      // while second inverter has only one battery stack with 3 battery modules
      const BatteryUnits = [[3, 0]];
      

      Das Setup entspricht eigentlich fast meinem Setup, einzig, dass ich nur einen String habe.
      Jetzt müsste man schauen was an Fehlermeldungen kommen. Und beachte: Gewisse Werte sind erst nach einmal Durchlaufen von Mitternacht wirklich sinnvoll.
      Gruss

      posted in ioBroker Allgemein
      C
      Chris_B
    Community
    Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
    The ioBroker Community 2014-2023
    logo