Skip to content
  • Recent
  • Tags
  • 0 Unread 0
  • Categories
  • Unreplied
  • Popular
  • GitHub
  • Docu
  • Hilfe
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Logo
  1. ioBroker Community Home
  2. Deutsch
  3. ioBroker Allgemein
  4. Huawei Sun2000 & ioBroker via JS script funktioniert

NEWS

  • UPDATE 31.10.: Amazon Alexa - ioBroker Skill läuft aus ?
    apollon77A
    apollon77
    48
    3
    8.0k

  • Monatsrückblick – September 2025
    BluefoxB
    Bluefox
    13
    1
    1.7k

  • Neues Video "KI im Smart Home" - ioBroker plus n8n
    BluefoxB
    Bluefox
    15
    1
    2.0k

Huawei Sun2000 & ioBroker via JS script funktioniert

Huawei Sun2000 & ioBroker via JS script funktioniert

Scheduled Pinned Locked Moved ioBroker Allgemein
481 Posts 62 Posters 120.6k Views 63 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • JohGreJ JohGre

    @KornSW Schaue ich mir gerne an, hab eben den API Zugang angefordert.
    Danke schon mal für deine Mühe

    JohGreJ Offline
    JohGreJ Offline
    JohGre
    wrote on last edited by
    #20

    @KornSW Huawei hat mir zurückgeschrieben, dass den Open-API Account nur ein Installateur beantragen kann. Wie hat das bei dir funktioniert?

    nuc i5: RaspberryMatic, ioBroker, pi-hole, SQL-Server, OMV-NAS, Influx-DB & Grafana, OpenHab, tasmoadmin

    1 Reply Last reply
    0
    • M Offline
      M Offline
      majawe
      wrote on last edited by majawe
      #21

      EDIT: Fehler gefunden...geht...

      Funktioniert das script noch? Bekomme folgenden fehler:
      Verwende einen Huawei Sun2000-8ktl-M1

      Als FW habe ich die versionen:
      Inverter: V100R001C00SPC148
      Dongle: V100R001C00SPC130
      MBUS: V100R001C00SPC330

      Screenshot 2022-12-11 120754.png

      M 1 Reply Last reply
      0
      • M majawe

        EDIT: Fehler gefunden...geht...

        Funktioniert das script noch? Bekomme folgenden fehler:
        Verwende einen Huawei Sun2000-8ktl-M1

        Als FW habe ich die versionen:
        Inverter: V100R001C00SPC148
        Dongle: V100R001C00SPC130
        MBUS: V100R001C00SPC330

        Screenshot 2022-12-11 120754.png

        M Offline
        M Offline
        majawe
        wrote on last edited by
        #22

        Es hat leider nur 1 mal funktioniert (als die Ordner angelegt wurden), er liesst zwar die Daten aktuallisiert Sie aber nicht unter Objekte, jemand eine Idee?

        Screenshot 2022-12-11 133427.png

        S 1 Reply Last reply
        0
        • M majawe

          Es hat leider nur 1 mal funktioniert (als die Ordner angelegt wurden), er liesst zwar die Daten aktuallisiert Sie aber nicht unter Objekte, jemand eine Idee?

          Screenshot 2022-12-11 133427.png

          S Offline
          S Offline
          Skoltrinker
          wrote on last edited by
          #23

          @majawe
          Ich hatte das gleiche Problem. Hat anfangs problemlos funktioniert und dann mit einem Versionsupgrade (ich glaube vom js-adapter) ging es plötzlich nicht mehr. Ich habe dann den folgenden Code Teil auskommentiert und dann hat es wieder funktioniert. Warum und wieso erschließt sich mir aber nicht ganz.

          function forcesetState(objectname, value, options) {
              **//Problem mit existsState -> aus irgendeinem Grund funktioniert es nicht mehr. 
              //if(!existsState(objectname)) {
              //    createState(objectname, value, options);        
              //}
              //else {**
                  setState(objectname, value);
              **//}**
          }  
          

          Ich habe auch den Verbindungsaufbau in eine function ausgelagert:

          function connectModBus() {
              console.log("Init connection to: " + ModBusHost +":" + ModBusPort);
              // set requests parameters
              client.setTimeout (10000);
              // try to connect
              client.connectTCP (ModBusHost, { port: ModBusPort })
                  .then(function()
                  {
                      console.log("Connected, wait for reading...");
                  })
                  .catch(function(e)
                  {
                      console.log(e);
                  });
          }
          

          Und dann eine provisorisch eine Prüfung hinzugefügt ob das Lesen der Daten erfolgreich war und ob die MODBUS Verbindung noch offen ist. Da ich immer wieder das Problem hatte, wenn die Verbindung verloren gegangen ist, dass dann keine Daten mehr gelesen werden konnten (da kein Wiederaufbau der Verbindung stattgefunden hat).

          setInterval(function() {
              if (!getDataSuccessful){
                  if (!client.isOpen){
                      connectModBus();
                  }
              } ...
          

          @majawe said in Huawei Sun2000 & ioBroker via JS script funktioniert:

          Es hat leider nur 1 mal funktioniert (als die Ordner angelegt wurden), er liesst zwar die Daten aktuallisiert Sie aber nicht unter Objekte, jemand eine Idee?

          Screenshot 2022-12-11 133427.png

          und n

          1 Reply Last reply
          0
          • K Kachel

            Die Modbus-Ansteuerung vom Huawei Sun2000 Wechselrichter ist über TCP etwas speziell, da nach öffnen des TCP-Ports noch eine Pause eingehalten werden muss, da sonst keine Daten zurück geliefert werden. Auch wird nicht jede Modbus-TCP-Anfrage mit den angeforderten Registern beantwortet. Daher funktioniert die Kommunikation über den normalen Modbus-Adapter im ioBroker nicht.

            Um die verfügbaren Register in den ioBroker zu bekommen hab ich ein js-script geschrieben, dass die Abfrage der Register über TCP macht und die Daten entsprechend parsed. Man braucht dafür im IOBroker nur die ScriptEngine und muss in deren Settings noch die modbus-serial hinzufügen. Danach legt das Script einen großen Satz an Objekten an und aktualisiert die regelmäßig (ca. 2x die Minute). Es werden nur Register gelesen - das Schreiben von Registern ist nicht eingebaut (und bei mir gerade auch nicht nötig). Damit die Netzwerkpakete möglichst groß sind werden die Registern in Blöcken abgefragt.

            Wer möchte kann das Script gerne nutzen. . Einfach IP, Batteriekonfiguration und die Modbus-IDs eintragen und ausführen. Wer es ändern möchte darf dies auch gerne tun - es freut aber sicher alle ioBroker-Nutzer wenn ihr Änderungen auch wieder veröffentlicht.

            Falls jemand noch eine Idee hat, wie man den Huawei File-transfer über Modbus implementieren kann (mit deren speziellem function-code 0x41), würde ich mich freuen. Der fehlt leider damit die Optimierer ihre Echtzeit-Daten in den IOBroker liefern können...

            der Kachel

            // License: Beerware! Do what ever you like with this, but I'm not liable for anything that you do with it.
            // If you like this code, feel free to buy me a beer ...
            // Have fun with it! der Kachel
            var ModbusRTU = require("modbus-serial");
            var client = new ModbusRTU();
            
            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("$$$ADD.YOUR.IP.HERE$$$", { port: 502 });
            // Enter the Modbus-IDs of your Sun2000 inverters here:
            const ModBusIDs = [16, 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], [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) {
                var value = array[0];    
                return value;
            }
            
            function readUnsignedInt32(array) {
                var value = array[0] * 256 * 256 + array[1];    
                return value;
            }
            
            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) {
                var value = readUnsignedInt16(dataarray.slice(index, index+1));
                return value;
            }
            
            function getU32(dataarray, index) {
                var value = readUnsignedInt32(dataarray.slice(index, index+2));
                return value;
            }
            
            function getI16(dataarray, index) {
                var value = readSignedInt16(dataarray.slice(index, index+1));
                return value;
            }
            
            function getI32(dataarray, index) {
                var value = readSignedInt32(dataarray.slice(index, index+2));
                return value;
            }
            
            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) {
                if(!existsState(objectname)) {
                    createState(objectname, value, options);        
                }
                else {
                    setState(objectname, value);
                }
            }  
            // ---------------------------------------------------------------
            // Functions to map registers into ioBreaker objects:
            function processOptimizers(id) {
                forcesetState("Solarpower.Huawei.Inverter." + id + ".OptimizerTotalNumber",     getU16(GlobalDataBuffer[id-1], 35200), {name: "", unit: ""});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".OptimizerOnlineNumber",    getU16(GlobalDataBuffer[id-1], 35201), {name: "", unit: ""});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".OptimizerFeatureData",     getU16(GlobalDataBuffer[id-1], 35202), {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 + ".AccomulatedEnergyYield",    getU16(GlobalDataBuffer[id-1], 32106), {name: "", unit: "kWh"});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".DailyEnergyYield",          getU16(GlobalDataBuffer[id-1], 32114), {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.log("Processing new data...");
                for(var i = 1; i <= ModBusIDs.length; i++) {
                    ProcessDeviceInfo(i);
                    processInverterStatus(i);
                    processBattery(i);
                    processInverterPowerAdjustments(i);
                    processOptimizers(i); 
                }    
                ProcessPowerMeterStatus();
                console.log("Processing done!");
            }
            
            
            // -------------------------------------------------------------------
            // This is the main function triggering a  read via modbus-tcp every two seconds.
            // Processing of data is triggered as soon as one complete set of registers is copied.
            var triggerprocessing = 0; 
            var currentinverter = 1;
            
            
            setInterval(function() {
                if(triggerprocessing == 1) {
                    triggerprocessing = 0;
                    processData();        
                }      
               
                console.log("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;                    
                    }
                }     
            }, 2000);
            
            ? Offline
            ? Offline
            A Former User
            wrote on last edited by A Former User
            #24

            @kachel

            Danke für die Mühe, aber ich bekomme immer die Fehlermeldungen Cannot find module 'modbus-serial' und ModbusRTU is not a constructor

            Mit npm install modbus-serial hab ich vorher das Modus NPM Modul installiert.

            Könnt ihr mir hier kurz auf die Sprünge helfen bitte ?

            M 1 Reply Last reply
            0
            • ? A Former User

              @kachel

              Danke für die Mühe, aber ich bekomme immer die Fehlermeldungen Cannot find module 'modbus-serial' und ModbusRTU is not a constructor

              Mit npm install modbus-serial hab ich vorher das Modus NPM Modul installiert.

              Könnt ihr mir hier kurz auf die Sprünge helfen bitte ?

              M Offline
              M Offline
              majawe
              wrote on last edited by
              #25

              @zoid1988 hast du es im Adapter hinzugefügt?
              Screenshot 2022-12-29 135310.png

              ? 1 Reply Last reply
              0
              • M majawe

                @zoid1988 hast du es im Adapter hinzugefügt?
                Screenshot 2022-12-29 135310.png

                ? Offline
                ? Offline
                A Former User
                wrote on last edited by
                #26

                @majawe

                Vielen Dank, wusste garnicht das man das machen kann ... Wieder etwas gelernt ...

                Das Script startet jetzt, aber ich bekomme leider keine Daten ausgelesen.

                Habe die Werte bei mir jetzt so angepasst (ich habe leider - noch - keinen Akku):

                client.connectTCP("10.168.1.111", { port: 502 });
                const ModBusIDs = [1];
                const PowerMeterID = 0;
                const BatteryUnits = [[0, 0]];

                Folgende Infos find ich im Log:

                30.12.2022, 11:33:51.829 [info ]: javascript.0 (1120689) script.js.PV: Triggering read of inverter 1 at address 35300 with length 40
                30.12.2022, 11:33:51.830 [warn ]: javascript.0 (1120689) script.js.PV: Error received reading address 35300 from id: 1 with error: undefined
                30.12.2022, 11:33:53.829 [info ]: javascript.0 (1120689) script.js.PV: Processing new data...
                30.12.2022, 11:33:53.832 [info ]: javascript.0 (1120689) script.js.PV: Processing done!
                30.12.2022, 11:33:53.833 [info ]: javascript.0 (1120689) script.js.PV: Triggering read of inverter 1 at address 30000 with length 81
                30.12.2022, 11:33:53.833 [warn ]: javascript.0 (1120689) script.js.PV: Error received reading address 30000 from id: 1 with error: undefined
                30.12.2022, 11:33:55.830 [info ]: javascript.0 (1120689) script.js.PV: Triggering read of inverter 1 at address 37100 with length 114
                30.12.2022, 11:33:55.830 [warn ]: javascript.0 (1120689) script.js.PV: Error received reading address 37100 from id: 1 with error: undefined
                30.12.2022, 11:33:57.830 [info ]: javascript.0 (1120689) script.js.PV: Triggering read of inverter 1 at address 32000 with length 116
                30.12.2022, 11:33:57.830 [warn ]: javascript.0 (1120689) script.js.PV: Error received reading address 32000 from id: 1 with error: undefined
                30.12.2022, 11:33:59.830 [info ]: javascript.0 (1120689) script.js.PV: Triggering read of inverter 1 at address 37000 with length 68
                30.12.2022, 11:33:59.831 [warn ]: javascript.0 (1120689) script.js.PV: Error received reading address 37000 from id: 1 with error: undefined
                30.12.2022, 11:34:01.830 [info ]: javascript.0 (1120689) script.js.PV: Triggering read of inverter 1 at address 37700 with length 100
                30.12.2022, 11:34:01.831 [warn ]: javascript.0 (1120689) script.js.PV: Error received reading address 37700 from id: 1 with error: undefined
                30.12.2022, 11:34:03.831 [info ]: javascript.0 (1120689) script.js.PV: Triggering read of inverter 1 at address 37800 with length 100
                30.12.2022, 11:34:03.831 [warn ]: javascript.0 (1120689) script.js.PV: Error received reading address 37800 from id: 1 with error: undefined
                30.12.2022, 11:34:05.831 [info ]: javascript.0 (1120689) script.js.PV: Triggering read of inverter 1 at address 38200 with length 100
                30.12.2022, 11:34:05.832 [warn ]: javascript.0 (1120689) script.js.PV: Error received reading address 38200 from id: 1 with error: undefined
                30.12.2022, 11:34:07.832 [info ]: javascript.0 (1120689) script.js.PV: Triggering read of inverter 1 at address 38300 with length 100
                30.12.2022, 11:34:07.833 [warn ]: javascript.0 (1120689) script.js.PV: Error received reading address 38300 from id: 1 with error: undefined
                30.12.2022, 11:34:08.028 [info ]: javascript.0 (1120689) Stop script script.js.PV

                ? oswibzO 2 Replies Last reply
                0
                • ? A Former User

                  @majawe

                  Vielen Dank, wusste garnicht das man das machen kann ... Wieder etwas gelernt ...

                  Das Script startet jetzt, aber ich bekomme leider keine Daten ausgelesen.

                  Habe die Werte bei mir jetzt so angepasst (ich habe leider - noch - keinen Akku):

                  client.connectTCP("10.168.1.111", { port: 502 });
                  const ModBusIDs = [1];
                  const PowerMeterID = 0;
                  const BatteryUnits = [[0, 0]];

                  Folgende Infos find ich im Log:

                  30.12.2022, 11:33:51.829 [info ]: javascript.0 (1120689) script.js.PV: Triggering read of inverter 1 at address 35300 with length 40
                  30.12.2022, 11:33:51.830 [warn ]: javascript.0 (1120689) script.js.PV: Error received reading address 35300 from id: 1 with error: undefined
                  30.12.2022, 11:33:53.829 [info ]: javascript.0 (1120689) script.js.PV: Processing new data...
                  30.12.2022, 11:33:53.832 [info ]: javascript.0 (1120689) script.js.PV: Processing done!
                  30.12.2022, 11:33:53.833 [info ]: javascript.0 (1120689) script.js.PV: Triggering read of inverter 1 at address 30000 with length 81
                  30.12.2022, 11:33:53.833 [warn ]: javascript.0 (1120689) script.js.PV: Error received reading address 30000 from id: 1 with error: undefined
                  30.12.2022, 11:33:55.830 [info ]: javascript.0 (1120689) script.js.PV: Triggering read of inverter 1 at address 37100 with length 114
                  30.12.2022, 11:33:55.830 [warn ]: javascript.0 (1120689) script.js.PV: Error received reading address 37100 from id: 1 with error: undefined
                  30.12.2022, 11:33:57.830 [info ]: javascript.0 (1120689) script.js.PV: Triggering read of inverter 1 at address 32000 with length 116
                  30.12.2022, 11:33:57.830 [warn ]: javascript.0 (1120689) script.js.PV: Error received reading address 32000 from id: 1 with error: undefined
                  30.12.2022, 11:33:59.830 [info ]: javascript.0 (1120689) script.js.PV: Triggering read of inverter 1 at address 37000 with length 68
                  30.12.2022, 11:33:59.831 [warn ]: javascript.0 (1120689) script.js.PV: Error received reading address 37000 from id: 1 with error: undefined
                  30.12.2022, 11:34:01.830 [info ]: javascript.0 (1120689) script.js.PV: Triggering read of inverter 1 at address 37700 with length 100
                  30.12.2022, 11:34:01.831 [warn ]: javascript.0 (1120689) script.js.PV: Error received reading address 37700 from id: 1 with error: undefined
                  30.12.2022, 11:34:03.831 [info ]: javascript.0 (1120689) script.js.PV: Triggering read of inverter 1 at address 37800 with length 100
                  30.12.2022, 11:34:03.831 [warn ]: javascript.0 (1120689) script.js.PV: Error received reading address 37800 from id: 1 with error: undefined
                  30.12.2022, 11:34:05.831 [info ]: javascript.0 (1120689) script.js.PV: Triggering read of inverter 1 at address 38200 with length 100
                  30.12.2022, 11:34:05.832 [warn ]: javascript.0 (1120689) script.js.PV: Error received reading address 38200 from id: 1 with error: undefined
                  30.12.2022, 11:34:07.832 [info ]: javascript.0 (1120689) script.js.PV: Triggering read of inverter 1 at address 38300 with length 100
                  30.12.2022, 11:34:07.833 [warn ]: javascript.0 (1120689) script.js.PV: Error received reading address 38300 from id: 1 with error: undefined
                  30.12.2022, 11:34:08.028 [info ]: javascript.0 (1120689) Stop script script.js.PV

                  ? Offline
                  ? Offline
                  A Former User
                  wrote on last edited by
                  #27

                  @zoid1988
                  So, ich muss mich kurz selbst korrigieren.
                  Ich habe bereits die Lösung mit Node-red im Einsatz und hab jetzt mal den Node-red Adapter gestoppt und nun haben sich die Einträge im Log verändert.

                  Bildschirmfoto 2022-12-30 um 11.45.31.png

                  Scheinbar kann er jetzt erfolgreich was abfragen, aber in den Objekten stehen immer noch alle Werte auf 0.

                  1 Reply Last reply
                  0
                  • B badsnoopy667

                    Ich hab ein bisschen mit Modbus rumgespielt:

                    modbus_write.png

                    Mit dem rot markierten Teil in meinem Modbus-TCP Flow versuche ich den Wert der ID "JSON_Test" in das Register 47082 zu schreiben. Das ist die %-Zahl ab der er aufhören soll die Batterie zu entladen. "JSON_Test" ist nur ein ungenutztes Objekt das ich gerade "übrig" hatte, also nicht am Namen stören.

                    Aktuell bin ich soweit, dass ich keine Fehlermeldung bekomme, wenn ich den Wert von "JSON_Test" ändere. Und ich glaube er wird auch geschrieben. Denn: Ich lese dieses Modbus Register auch 1x pro Minute aus. Und da ließt er dann meinen in "JSON_Test" eingetragenen Wert aus!
                    Aber: Die Batterie entlädt trotzdem weiter, obwohl der SOC kleiner ist als der eingegebene Wert. Es hat also keinen Effekt...
                    Vielleicht hilft das ja schon jemandem weiter als Gedankenanstoß wie man es hinbekommen kann?

                    Edit: Ich glaube das nichts passiert liegt daran, dass ich den "Gain" von 10 vergessen habe. D.h. wenn ich 30 (%) eingebe glaube ich das der Wechselrichter das al 3% interpretiert. Habe nämlich mal Register 47076 gelesen, das ist "Maximum Charging Power". Und da meldet er 1000 zurück für 100%.
                    Wenn ich jetzt aber nicht 30 sondern 300 sende bekomme ich folgende Fehlermeldung zurück:

                    node-red.0
                    2022-04-06 23:17:20.985	error	6 Apr 23:17:20 - [error] [modbus-write:47082 (Bat Discharge cutof capacity SET)] Error: Modbus exception 4: Slave device failure (device reports internal error) at ModbusRTU._onReceive (/opt/iobroker/iobroker-data/node-red/node_modules/modbus-serial/index.js:371:21) at TcpPort.emit (events.js:400:28) at Socket.<anonymous> (/opt/iobroker/iobroker-data/node-red/node_modules/modbus-serial/ports/tcpport.js:92:20) at Socket.emit (events.js:400:28) at addChunk (internal/streams/readable.js:293:12) at readableAddChunk (internal/streams/readable.js:267:9) at Socket.Readable.push (internal/streams/readable.js:206:10) at TCP.onStreamRead (internal/stream_base_commons.js:188:23)
                    

                    Nochmal Edit:
                    Ich habe rausgefunden, dass der Fehler nur kommt, wenn der geschriebene Wert größer ist als der aktuelle SOC der Batterie. Wenn ich 300 schreibe und die Batterie hat nur 22% kommt der Fehler. Schreibe ich z.B. 100 kommt kein Fehler und die 100 werden beim nächsten Register auslesen auch wieder angezeigt. Hab das Ding jetzt auf 10% gestellt und gehe jetzt schlafen... mal gucken ob er heute Nacht bei 10% aufhört die Batterie zu entladen. Ich werde berichten.
                    Over and Out, Gute Nacht!

                    Korrektur: Ich kann nur Werte zwischen 0 und 20 schreiben, denn das ist der Bereich der für die Batterie-Minimum-Ladung. Mehr als 20% geht nicht.

                    Ich möchte gerne Register 47077 schreiben, denn das enhält den maximalen Entladestrom. Idee: Wenn eAuto lädt, dann max. Ladestrom auf 0 damit das Auto nicht die Batterie entlädt.
                    Problem: Das ist ein Register mit der Länge 2, also 2x 16Bit Integer (U32). Ich habe rausgefunden, dass man daher das "dahingeschickte" formatieren muss, denn die iobroker Datenpunkte sind INT16. Ich muss das also in 2x INT16 aufteilen. Aber wie geht das? Hat da jemand eine Idee?

                    Hier ist das beschrieben, aber ich werde da nicht schlau draus:
                    https://stevesnoderedguide.com/modbus-writing-data

                    Und hier noch der Auszug aus der Huawei Modbus Dokumentation:

                    modbus_47077.png

                    M Offline
                    M Offline
                    majawe
                    wrote on last edited by
                    #28

                    @badsnoopy667 Klappt super den Wert zu ändern, hast du evtl eine Idee wie ich den Akku laden lassen kann? habe es mit 47100 (1) probiert aber es funktioniert nicht......9c46b519-9196-42f1-ae9b-17da6d60c51b-image.png

                    B 2 Replies Last reply
                    0
                    • M majawe

                      @badsnoopy667 Klappt super den Wert zu ändern, hast du evtl eine Idee wie ich den Akku laden lassen kann? habe es mit 47100 (1) probiert aber es funktioniert nicht......9c46b519-9196-42f1-ae9b-17da6d60c51b-image.png

                      B Offline
                      B Offline
                      badsnoopy667
                      wrote on last edited by
                      #29

                      @majawe
                      Nein, das habe ich noch nicht probiert, da ich keinen variablen Stromtarif habe... aber darüber nachgedacht, ob es geht, habe ich auch schon. Falls Du also etwas rausbekommen solltest, sag gerne Bescheid! 🙂

                      1 Reply Last reply
                      0
                      • M majawe

                        @badsnoopy667 Klappt super den Wert zu ändern, hast du evtl eine Idee wie ich den Akku laden lassen kann? habe es mit 47100 (1) probiert aber es funktioniert nicht......9c46b519-9196-42f1-ae9b-17da6d60c51b-image.png

                        B Offline
                        B Offline
                        badsnoopy667
                        wrote on last edited by badsnoopy667
                        #30

                        @majawe
                        Kurzes Update: Über Modbus habe ich es noch nicht geschafft den Akku laden zu lassen. Ich vermute übrigens, Du hast nicht die letzte Version (V3) Der "modbus-interface-definitions"
                        Link: solar-inverter-modbus-interface-definitions-v3.0.pdf .
                        Das Register was Du da zeigst gibt es da nicht mehr. Es gibt aber ein Register [Energy storage unit] Time-of-use electricity price periods - 47200. Da kann man wohl die Lade- und Entladezeiten eintragen für den Akku. Da das Ding aber 41 Zeichen lang ist, habe ich keinen Plan, wie das korrekte Format aussehen muss. Ich habe mal den Huawei Support angeschrieben.
                        Aber: Was ich gerade mal getestet habe: Mit der SUN2000 App (Nicht FusionSolar, geht aber vll auch, k.a.) habe ich mich auf den Wechselrichter als Installateur verbunden (über das SDongle WLan im Keller) und habe die Betriebsweise das Akkus auf "TOU" gestellt. Also zeitgesteuertes Laden. Wenn man da dann eine Ladezeit einträgt, fängt das Ding auch an aus dem Netz zu laden.
                        Daher meine fixe Idee als Workaround: In der App eine Ladezeit einstelle (z.B. von 23:00 - 6:00 Uhr Nachts, in der Annahme das Nachts die günstigesten Preise vorliegen). Und dann das Register [Energy storage unit] Maximum charging power - 47075 entsprechend auf 0 setzen, zu Zeiten wenn man nicht laden will und auf 5000 (für 5000W, bei mind. 10kWh Akku, sonst weniger), wenn man laden möchte in dieser Zeit. Morgens natürlich dann wieder hochsetzen. Habe ich aber noch nicht ausprobiert. Könnte mir aber vorstellen, dass es klappt. Bin mir nur nicht sicher, ob er dann noch entlädt (in der Zeit wo die Ladeleistung 0 ist, aber die Ladezeit gesetzt ist).

                        M 2 Replies Last reply
                        0
                        • B badsnoopy667

                          @majawe
                          Kurzes Update: Über Modbus habe ich es noch nicht geschafft den Akku laden zu lassen. Ich vermute übrigens, Du hast nicht die letzte Version (V3) Der "modbus-interface-definitions"
                          Link: solar-inverter-modbus-interface-definitions-v3.0.pdf .
                          Das Register was Du da zeigst gibt es da nicht mehr. Es gibt aber ein Register [Energy storage unit] Time-of-use electricity price periods - 47200. Da kann man wohl die Lade- und Entladezeiten eintragen für den Akku. Da das Ding aber 41 Zeichen lang ist, habe ich keinen Plan, wie das korrekte Format aussehen muss. Ich habe mal den Huawei Support angeschrieben.
                          Aber: Was ich gerade mal getestet habe: Mit der SUN2000 App (Nicht FusionSolar, geht aber vll auch, k.a.) habe ich mich auf den Wechselrichter als Installateur verbunden (über das SDongle WLan im Keller) und habe die Betriebsweise das Akkus auf "TOU" gestellt. Also zeitgesteuertes Laden. Wenn man da dann eine Ladezeit einträgt, fängt das Ding auch an aus dem Netz zu laden.
                          Daher meine fixe Idee als Workaround: In der App eine Ladezeit einstelle (z.B. von 23:00 - 6:00 Uhr Nachts, in der Annahme das Nachts die günstigesten Preise vorliegen). Und dann das Register [Energy storage unit] Maximum charging power - 47075 entsprechend auf 0 setzen, zu Zeiten wenn man nicht laden will und auf 5000 (für 5000W, bei mind. 10kWh Akku, sonst weniger), wenn man laden möchte in dieser Zeit. Morgens natürlich dann wieder hochsetzen. Habe ich aber noch nicht ausprobiert. Könnte mir aber vorstellen, dass es klappt. Bin mir nur nicht sicher, ob er dann noch entlädt (in der Zeit wo die Ladeleistung 0 ist, aber die Ladezeit gesetzt ist).

                          M Offline
                          M Offline
                          majawe
                          wrote on last edited by
                          #31

                          @badsnoopy667 said in Huawei Sun2000 & ioBroker via JS script funktioniert:

                          [Energy storage unit] Maximum charging power - 47075

                          Die Idee hatte ich auch schon, leider bekomme ich es nicht hin das er die 0 annimmt bzw überträgt

                          B 1 Reply Last reply
                          0
                          • M majawe

                            @badsnoopy667 said in Huawei Sun2000 & ioBroker via JS script funktioniert:

                            [Energy storage unit] Maximum charging power - 47075

                            Die Idee hatte ich auch schon, leider bekomme ich es nicht hin das er die 0 annimmt bzw überträgt

                            B Offline
                            B Offline
                            badsnoopy667
                            wrote on last edited by
                            #32

                            @majawe
                            Das sollte ja das kleinste Problem sein. Der Wert wird genauso geschrieben wie das Register 47077 (Max. Entladeleistung). Hab's gerade probiert. Wenn ich im Flow die Adresse von 47077 auf 47075 ändere (und sonst alles gleich lasse), kann ich die Ladeleistung einstellen. "0" habe ich nicht probiert, aber 4999 und 5000W hat geklappt.

                            M 1 Reply Last reply
                            0
                            • B badsnoopy667

                              @majawe
                              Das sollte ja das kleinste Problem sein. Der Wert wird genauso geschrieben wie das Register 47077 (Max. Entladeleistung). Hab's gerade probiert. Wenn ich im Flow die Adresse von 47077 auf 47075 ändere (und sonst alles gleich lasse), kann ich die Ladeleistung einstellen. "0" habe ich nicht probiert, aber 4999 und 5000W hat geklappt.

                              M Offline
                              M Offline
                              majawe
                              wrote on last edited by
                              #33

                              @badsnoopy667 könntest du mir den flow mal exportieren oder ein scrennshot der karte bitte machen?🙏

                              B 1 Reply Last reply
                              0
                              • M majawe

                                @badsnoopy667 könntest du mir den flow mal exportieren oder ein scrennshot der karte bitte machen?🙏

                                B Offline
                                B Offline
                                badsnoopy667
                                wrote on last edited by badsnoopy667
                                #34

                                @majawe
                                Hier der Flow für beide Zustände (Charge und Discharge)
                                flows_read_write_charge_discharge.json
                                Sobald du eines der beiden Objekte "_SET" änderst (vorher anlegen!), wird das entsprechende Register geschrieben.
                                Und wie immer bei meinem Flow: Achte auf die Unit-ID. Bei mir ist die 2, bei dir vermutlich nicht! Mein WR war mal defekt.

                                Hast Du darauf geachtet beim Ändern nicht nur den Namen, sondern wirklich die Adresse zu ändern? Das hab ich schon ein paar mal durcheinander gebracht. Der Name allein hilft nicht, der ist sowieso völlig beliebig.

                                karte_modbus.png

                                M B 2 Replies Last reply
                                0
                                • B badsnoopy667

                                  @majawe
                                  Hier der Flow für beide Zustände (Charge und Discharge)
                                  flows_read_write_charge_discharge.json
                                  Sobald du eines der beiden Objekte "_SET" änderst (vorher anlegen!), wird das entsprechende Register geschrieben.
                                  Und wie immer bei meinem Flow: Achte auf die Unit-ID. Bei mir ist die 2, bei dir vermutlich nicht! Mein WR war mal defekt.

                                  Hast Du darauf geachtet beim Ändern nicht nur den Namen, sondern wirklich die Adresse zu ändern? Das hab ich schon ein paar mal durcheinander gebracht. Der Name allein hilft nicht, der ist sowieso völlig beliebig.

                                  karte_modbus.png

                                  M Offline
                                  M Offline
                                  majawe
                                  wrote on last edited by
                                  #35

                                  @badsnoopy667 Funktioniert heute auf Anhieb komischer weise 🙂 ich denke es lag am Dongle update

                                  Tou kannst du auch online umstellen unter, https://region02eu5.fusionsolar.huawei.com, Dongle, EMS Control oder direkt am Handy unter Dongel, Parametereinstellung, Arbeitsmodus Tou.

                                  Also brauchst dich nicht direkt am Wechselrichter einloggen

                                  tou.png
                                  tou handy.png

                                  B 1 Reply Last reply
                                  0
                                  • B badsnoopy667

                                    @majawe
                                    Kurzes Update: Über Modbus habe ich es noch nicht geschafft den Akku laden zu lassen. Ich vermute übrigens, Du hast nicht die letzte Version (V3) Der "modbus-interface-definitions"
                                    Link: solar-inverter-modbus-interface-definitions-v3.0.pdf .
                                    Das Register was Du da zeigst gibt es da nicht mehr. Es gibt aber ein Register [Energy storage unit] Time-of-use electricity price periods - 47200. Da kann man wohl die Lade- und Entladezeiten eintragen für den Akku. Da das Ding aber 41 Zeichen lang ist, habe ich keinen Plan, wie das korrekte Format aussehen muss. Ich habe mal den Huawei Support angeschrieben.
                                    Aber: Was ich gerade mal getestet habe: Mit der SUN2000 App (Nicht FusionSolar, geht aber vll auch, k.a.) habe ich mich auf den Wechselrichter als Installateur verbunden (über das SDongle WLan im Keller) und habe die Betriebsweise das Akkus auf "TOU" gestellt. Also zeitgesteuertes Laden. Wenn man da dann eine Ladezeit einträgt, fängt das Ding auch an aus dem Netz zu laden.
                                    Daher meine fixe Idee als Workaround: In der App eine Ladezeit einstelle (z.B. von 23:00 - 6:00 Uhr Nachts, in der Annahme das Nachts die günstigesten Preise vorliegen). Und dann das Register [Energy storage unit] Maximum charging power - 47075 entsprechend auf 0 setzen, zu Zeiten wenn man nicht laden will und auf 5000 (für 5000W, bei mind. 10kWh Akku, sonst weniger), wenn man laden möchte in dieser Zeit. Morgens natürlich dann wieder hochsetzen. Habe ich aber noch nicht ausprobiert. Könnte mir aber vorstellen, dass es klappt. Bin mir nur nicht sicher, ob er dann noch entlädt (in der Zeit wo die Ladeleistung 0 ist, aber die Ladezeit gesetzt ist).

                                    M Offline
                                    M Offline
                                    majawe
                                    wrote on last edited by
                                    #36

                                    @badsnoopy667 Super 👍 👍 👍 👍 👍 so wird es gemacht
                                    Danke🙏

                                    1 Reply Last reply
                                    0
                                    • M majawe

                                      @badsnoopy667 Funktioniert heute auf Anhieb komischer weise 🙂 ich denke es lag am Dongle update

                                      Tou kannst du auch online umstellen unter, https://region02eu5.fusionsolar.huawei.com, Dongle, EMS Control oder direkt am Handy unter Dongel, Parametereinstellung, Arbeitsmodus Tou.

                                      Also brauchst dich nicht direkt am Wechselrichter einloggen

                                      tou.png
                                      tou handy.png

                                      B Offline
                                      B Offline
                                      badsnoopy667
                                      wrote on last edited by
                                      #37

                                      @majawe
                                      Schön, dass es klappt! Aber ENT-laden im Ladezeitraum tut er nicht, oder? Das ist nämlich vermutlich noch der Haken. Den Zeitraum würde ich ja immer (in der Nacht) stehen lassen und über die Ladeleistung dann quasi aktivieren und deaktivieren.
                                      Wobei man streiten kann, ob das ein Problem ist, im Winter ist der Akku Nachts sowieso fast immer leer. Dann spielt es keine Rolle. Und im Sommer brauche ich ihn ihn nicht extern laden.

                                      Zu der FusionSolar Seite: Wo geht das denn? Bei mir kann ich da gar nix einstellen. Welche Dongle Firmware ist das? Oder hast Du da Installateur Zugriff auf FusionSolar?

                                      M 2 Replies Last reply
                                      0
                                      • B badsnoopy667

                                        @majawe
                                        Schön, dass es klappt! Aber ENT-laden im Ladezeitraum tut er nicht, oder? Das ist nämlich vermutlich noch der Haken. Den Zeitraum würde ich ja immer (in der Nacht) stehen lassen und über die Ladeleistung dann quasi aktivieren und deaktivieren.
                                        Wobei man streiten kann, ob das ein Problem ist, im Winter ist der Akku Nachts sowieso fast immer leer. Dann spielt es keine Rolle. Und im Sommer brauche ich ihn ihn nicht extern laden.

                                        Zu der FusionSolar Seite: Wo geht das denn? Bei mir kann ich da gar nix einstellen. Welche Dongle Firmware ist das? Oder hast Du da Installateur Zugriff auf FusionSolar?

                                        M Offline
                                        M Offline
                                        majawe
                                        wrote on last edited by
                                        #38

                                        @badsnoopy667 Ich denke bei sonnenuntergang setze ich den auf 0watt, und dann wenn kleiner als 5cent = 5000Watt. Den Rest erledigt Tou zwischen 0 - 5 Uhr.

                                        1 Reply Last reply
                                        0
                                        • B badsnoopy667

                                          @majawe
                                          Schön, dass es klappt! Aber ENT-laden im Ladezeitraum tut er nicht, oder? Das ist nämlich vermutlich noch der Haken. Den Zeitraum würde ich ja immer (in der Nacht) stehen lassen und über die Ladeleistung dann quasi aktivieren und deaktivieren.
                                          Wobei man streiten kann, ob das ein Problem ist, im Winter ist der Akku Nachts sowieso fast immer leer. Dann spielt es keine Rolle. Und im Sommer brauche ich ihn ihn nicht extern laden.

                                          Zu der FusionSolar Seite: Wo geht das denn? Bei mir kann ich da gar nix einstellen. Welche Dongle Firmware ist das? Oder hast Du da Installateur Zugriff auf FusionSolar?

                                          M Offline
                                          M Offline
                                          majawe
                                          wrote on last edited by majawe
                                          #39

                                          @badsnoopy667 Ich habe den Installateur zugang, da ist der Punkt sichtbar. Der Dongle hat die FW PC133 am ende aber gesehen habe ich den Punkt bereits mit der PC130

                                          1 Reply Last reply
                                          0
                                          Reply
                                          • Reply as topic
                                          Log in to reply
                                          • Oldest to Newest
                                          • Newest to Oldest
                                          • Most Votes


                                          Support us

                                          ioBroker
                                          Community Adapters
                                          Donate
                                          FAQ Cloud / IOT
                                          HowTo: Node.js-Update
                                          HowTo: Backup/Restore
                                          Downloads
                                          BLOG

                                          247

                                          Online

                                          32.4k

                                          Users

                                          81.3k

                                          Topics

                                          1.3m

                                          Posts
                                          Community
                                          Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
                                          ioBroker Community 2014-2025
                                          logo
                                          • Login

                                          • Don't have an account? Register

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Recent
                                          • Tags
                                          • Unread 0
                                          • Categories
                                          • Unreplied
                                          • Popular
                                          • GitHub
                                          • Docu
                                          • Hilfe