Skip to content
  • Home
  • Aktuell
  • Tags
  • 0 Ungelesen 0
  • Kategorien
  • Unreplied
  • Beliebt
  • 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

  • Standard: (Kein Skin)
  • Kein Skin
Einklappen
ioBroker Logo

Community Forum

  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.2k

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

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

Huawei Sun2000 & ioBroker via JS script funktioniert

Geplant Angeheftet Gesperrt Verschoben ioBroker Allgemein
481 Beiträge 62 Kommentatoren 121.3k Aufrufe 63 Watching
  • Älteste zuerst
  • Neuste zuerst
  • Meiste Stimmen
Antworten
  • In einem neuen Thema antworten
Anmelden zum Antworten
Dieses Thema wurde gelöscht. Nur Nutzer mit entsprechenden Rechten können es sehen.
  • B badsnoopy667

    @oliwit82
    Die Werte kann man nicht direkt abfragen und müssen berechnet werden.

    Beispiel

    Oh, sehe gerade, mein Script ist gar nicht für die kWh Werte. Damit berechne ich erstmal Verbrauch, Bezug, etc. Aber diese Werte kann man dann ja aufsummieren über den Tag.

    O Offline
    O Offline
    OliWit82
    schrieb am zuletzt editiert von
    #102

    @badsnoopy667

    Danke.

    Gibt es da vielleicht schon ein fertiges blockly?

    B 1 Antwort Letzte Antwort
    0
    • O OliWit82

      @badsnoopy667

      Danke.

      Gibt es da vielleicht schon ein fertiges blockly?

      B Offline
      B Offline
      badsnoopy667
      schrieb am zuletzt editiert von
      #103

      @oliwit82
      Das sollte sich mit dem sourceanalytix Adapter am einfachsten realisieren lassen.

      1 Antwort Letzte Antwort
      0
      • J juggi1962

        @baumiliciousnessss
        Ja, ich habe das Skript von @Alex-Warkentin und das funktioniert jetzt.
        Er hat das Original Skript ein wenig abgespeckt und den Batterie Teil rausgenommen da er und ich keine Haben.

        
        
        // 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
        
        // @ts-ignore
        
        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)"
        
        ];
        
         
        
        // Enter your inverter modbus IP and port here:
        
        const modbusHost = "xxx.xxx.x.x";
        
        const modbusPort = 502;
        
        // Enter the Modbus-IDs of your Sun2000 inverters here:
        
        const modbusID = [1];
        
        // On which Modbus-ID can we reach the power meter? (via Sun2000!)
        
        const powerMeterID = 0;
        
         
        
        // Connect to modbus client
        
        ConnectModbus();
        
         
        
        // These register spaces need to be read:
        
        const registerSpacesToReadContinuously = [[37100, 114],[32000, 116]];
        
        var registerSpacesToReadContinuouslyPtr = 0;
        
         
        
        var globalDataBuffer = new Array(1);
        
        globalDataBuffer[0] = 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;
        
        }
        
         
        
        // Funktion zum Herstellen einer Modbus-Verbindung
        
        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);
        
                });
        
        }
        
         
        
        // Funktion zum Anlegen und Beschreiben eines Datenpunkts
        
        function ForceSetState(objectname, value, options) {
        
            if(!existsState("javascript.0." + objectname))      createState(objectname, value, options);
        
            else                                                setState(objectname, value);
        
        }  
        
        // ---------------------------------------------------------------
        
        // Functions to map registers into ioBreaker objects:
        
        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], 32002),          {name: "", unit: ""});
        
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".State3",                   GetU32(globalDataBuffer[id-1], 32003),          {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 + ".String.3_Voltage",         GetI16(globalDataBuffer[id-1], 32020) / 10,     {name: "", unit: "V"});
        
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.3_Current",         GetI16(globalDataBuffer[id-1], 32021) / 100,    {name: "", unit: "A"});
        
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.4_Voltage",         GetI16(globalDataBuffer[id-1], 32022) / 10,     {name: "", unit: "V"});
        
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.4_Current",         GetI16(globalDataBuffer[id-1], 32023) / 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",              String(new Date(GetU32(globalDataBuffer[id-1], 32091)*1000)),          {name: "", unit: ""});
        
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".ShutdownTime",             String(new Date(GetU32(globalDataBuffer[id-1], 32093)*1000)),          {name: "", unit: ""});
        
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".AccomulatedEnergyYield",   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 ReadRegisterSpace(id, address, length) {
        
            client.setID(modbusID[id-1]);
        
            client.readHoldingRegisters(address, length, function(err, data) {
        
                if (err) {
        
                    if (err.modbusCode == null) {
        
                        console.warn("Lost connection to client. Trying to reconnect...");
        
                        ConnectModbus();
        
                    } 
        
                    else console.warn("Error received reading address " + address + " from id: " + modbusID[id-1] + " with error: " + err.modbusCode); 
        
                }
        
                else
        
                {   
        
                    console.debug("Read data from id/address " + modbusID[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 <= modbusID.length; i++) {
        
                ProcessInverterStatus(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 > modbusID.length){
        
                    currentinverter = 1;  
        
                    triggerprocessing = 1;                    
        
                }
        
            }     
        
        }, 4000);
        
        

        Die Fehler die bei mir gekommen sind, sind jetzt fast weg, seit ich die Abfragezeit auf 4000 ms geändert habe.
        Ich hoffe ich konnte helfen, Gruß Jürgen

        AtifanA Offline
        AtifanA Offline
        Atifan
        schrieb am zuletzt editiert von
        #104

        @juggi1962 sagte in Huawei Sun2000 & ioBroker via JS script funktioniert:

        @baumiliciousnessss
        Ja, ich habe das Skript von @Alex-Warkentin und das funktioniert jetzt.
        Er hat das Original Skript ein wenig abgespeckt und den Batterie Teil rausgenommen da er und ich keine Haben.

        
        
        // 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
        
        // @ts-ignore
        
        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)"
        
        ];
        
         
        
        // Enter your inverter modbus IP and port here:
        
        const modbusHost = "xxx.xxx.x.x";
        
        const modbusPort = 502;
        
        // Enter the Modbus-IDs of your Sun2000 inverters here:
        
        const modbusID = [1];
        
        // On which Modbus-ID can we reach the power meter? (via Sun2000!)
        
        const powerMeterID = 0;
        
         
        
        // Connect to modbus client
        
        ConnectModbus();
        
         
        
        // These register spaces need to be read:
        
        const registerSpacesToReadContinuously = [[37100, 114],[32000, 116]];
        
        var registerSpacesToReadContinuouslyPtr = 0;
        
         
        
        var globalDataBuffer = new Array(1);
        
        globalDataBuffer[0] = 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;
        
        }
        
         
        
        // Funktion zum Herstellen einer Modbus-Verbindung
        
        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);
        
                });
        
        }
        
         
        
        // Funktion zum Anlegen und Beschreiben eines Datenpunkts
        
        function ForceSetState(objectname, value, options) {
        
            if(!existsState("javascript.0." + objectname))      createState(objectname, value, options);
        
            else                                                setState(objectname, value);
        
        }  
        
        // ---------------------------------------------------------------
        
        // Functions to map registers into ioBreaker objects:
        
        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], 32002),          {name: "", unit: ""});
        
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".State3",                   GetU32(globalDataBuffer[id-1], 32003),          {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 + ".String.3_Voltage",         GetI16(globalDataBuffer[id-1], 32020) / 10,     {name: "", unit: "V"});
        
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.3_Current",         GetI16(globalDataBuffer[id-1], 32021) / 100,    {name: "", unit: "A"});
        
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.4_Voltage",         GetI16(globalDataBuffer[id-1], 32022) / 10,     {name: "", unit: "V"});
        
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.4_Current",         GetI16(globalDataBuffer[id-1], 32023) / 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",              String(new Date(GetU32(globalDataBuffer[id-1], 32091)*1000)),          {name: "", unit: ""});
        
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".ShutdownTime",             String(new Date(GetU32(globalDataBuffer[id-1], 32093)*1000)),          {name: "", unit: ""});
        
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".AccomulatedEnergyYield",   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 ReadRegisterSpace(id, address, length) {
        
            client.setID(modbusID[id-1]);
        
            client.readHoldingRegisters(address, length, function(err, data) {
        
                if (err) {
        
                    if (err.modbusCode == null) {
        
                        console.warn("Lost connection to client. Trying to reconnect...");
        
                        ConnectModbus();
        
                    } 
        
                    else console.warn("Error received reading address " + address + " from id: " + modbusID[id-1] + " with error: " + err.modbusCode); 
        
                }
        
                else
        
                {   
        
                    console.debug("Read data from id/address " + modbusID[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 <= modbusID.length; i++) {
        
                ProcessInverterStatus(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 > modbusID.length){
        
                    currentinverter = 1;  
        
                    triggerprocessing = 1;                    
        
                }
        
            }     
        
        }, 4000);
        
        

        Die Fehler die bei mir gekommen sind, sind jetzt fast weg, seit ich die Abfragezeit auf 4000 ms geändert habe.
        Ich hoffe ich konnte helfen, Gruß Jürgen

        Hallo, habe auch diese Skript genommen und funktioniert bei mir auch.
        Nur habe ich noch eine LUNA2000 Batterie mit 10kWh und würde die gerne mit einbinden.
        Kann mir einer sagen was ich noch mit einfügen muss, damit der Speicher mit drin ist?
        Danke!

        1 Antwort Letzte Antwort
        0
        • Alex WarkentinA Offline
          Alex WarkentinA Offline
          Alex Warkentin
          schrieb am zuletzt editiert von
          #105

          Du solltest dann das Ursprungs-Script von Kachel aus dem ersten Post nehmen und beide ggf. kombinieren.

          X 1 Antwort Letzte Antwort
          0
          • G Offline
            G Offline
            g.polat
            schrieb am zuletzt editiert von g.polat
            #106

            Hallo zusammen,
            habe nun das Script ebenfalls zum laufen bekommen, habe jedoch einige Verständnisfragen.
            Was ist der Unterschied zwischen:
            javascript.0.Solarpower.Huawei.Meter.ActivePower und javascript.0.Solarpower.Huawei.Meter.ActivePower
            Welche Datenpunkte muss ich für den Energiefluss nehmen betreffend: Hausverbrauch; Netzeinspeisung; Netzausspeisung?
            Wäre für Hilfestellung dankbar, da die Werte aus der APP nicht mit den ausgelesenen Werten bis auf den Akku übereinstimmen.

            Laut AP aktuell:
            Produktion 4,79 KW
            Batterie wird mit 2,47 KW geladen
            Ins Netz gehen 1,96 KW
            Ins Haus 0,35KW

            Ausgelesen per Script:
            javascript.0.Solarpower.Huawei.Inverter.1.ActivePower 1.249 KW
            javascript.0.Solarpower.Huawei.Inverter.1.InputPower 4.42 KW
            javascript.0.Solarpower.Huawei.Meter.ActivePower 260 W
            javascript.0.Solarpower.Huawei.Meter.PositiveActiveEnergy 1.49 KW

            Hier mein Scrpt:

            // 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("192.168.0.45", { port: 502 });
            // Enter the Modbus-IDs of your Sun2000 inverters here:
            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], [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("javascript.0." + objectname)) {
                    createState(objectname, value, options); 
                    console.log("createstate " +  objectname + " to value " + value);            
                }
                    setState(objectname, value);
                }
            // ---------------------------------------------------------------
            // Functions to map registers into ioBreaker objects:
            function processOptimizers(id) {
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".OptimizerTotalNumber",     getU16(GlobalDataBuffer[id-1], 35200), {name: "", unit: ""});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".OptimizerOnlineNumber",    getU16(GlobalDataBuffer[id-1], 35201), {name: "", unit: ""});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".OptimizerFeatureData",     getU16(GlobalDataBuffer[id-1], 35202), {name: "", unit: ""});
            }
            
            function processInverterPowerAdjustments(id) {
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".ActiveAdjustement.ActiveAdjustementMode",     getU16(GlobalDataBuffer[id-1], 35300), {name: "", unit: ""});
                forcesetState("Solarpower2.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("Solarpower2.Huawei.Inverter." + id + ".ActiveAdjustement.ActiveAdjustementCommand",  getU16(GlobalDataBuffer[id-1], 35303), {name: "", unit: ""});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".ActiveAdjustement.ReactiveAdjustementMode",   getU16(GlobalDataBuffer[id-1], 35304), {name: "", unit: ""});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".ActiveAdjustement.ReactiveAdjustementValue",  getU32(GlobalDataBuffer[id-1], 35305), {name: "", unit: ""});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".ActiveAdjustement.ReactiveAdjustementCommand",getU16(GlobalDataBuffer[id-1], 35307), {name: "", unit: ""});
                forcesetState("Solarpower2.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("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.RunningStatus",          getU16(GlobalDataBuffer[id-1], 37000), {name: "", unit: ""});
                    forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.ChargeAndDischargePower",getI32(GlobalDataBuffer[id-1], 37001), {name: "Charge and Discharge Power", unit: "W"});
                    forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.BusVoltage",             getU16(GlobalDataBuffer[id-1], 37003) / 10, {name: "Busvoltage", unit: "V"});
                    forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.BatterySOC",             getU16(GlobalDataBuffer[id-1], 37004) / 10, {name: "Battery SOC", unit: "%"});
                    forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.WorkingMode",            getU16(GlobalDataBuffer[id-1], 37006), {name: "Working Mode", unit: ""});
                    forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.RatedChargePower",       getU32(GlobalDataBuffer[id-1], 37007), {name: "", unit: "W"});
                    forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.RatedDischargePower",    getU32(GlobalDataBuffer[id-1], 37009), {name: "", unit: "W"});
                    forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.FaultID",                getU16(GlobalDataBuffer[id-1], 37014), {name: "", unit: ""});
                    forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.CurrentDayChargeCapacity",    getU32(GlobalDataBuffer[id-1], 37015) / 100, {name: "", unit: "kWh"});
                    forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.CurrentDayDischargeCapacity", getU32(GlobalDataBuffer[id-1], 37017) / 100, {name: "", unit: "kWh"});
                    forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.BusCurrent",             getI16(GlobalDataBuffer[id-1], 37021) / 10, {name: "Buscurrent", unit: "A"});
                    forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.BatteryTemperature",     getI16(GlobalDataBuffer[id-1], 37022) / 10, {name: "Battery Temperatue", unit: "°C"});
                    forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.RemainingChargeDischargeTime", getU16(GlobalDataBuffer[id-1], 37025), {name: "", unit: "mins"});
                    forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.DCDCversion",            getZeroTerminatedString(GlobalDataBuffer[id-1], 37026, 10), {name: "", unit: ""});
                    forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.BMSversion",             getZeroTerminatedString(GlobalDataBuffer[id-1], 37036, 10), {name: "", unit: ""});
                }
                // Battery registers 16+17 (Storage-related)
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Battery.MaximumChargePower",                getU32(GlobalDataBuffer[id-1], 37046), {name: "", unit: "W"});
                forcesetState("Solarpower2.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("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.SN",                         getZeroTerminatedString(GlobalDataBuffer[id-1], 37052, 10), {name: "Serialnumber", unit: ""});       
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.TotalCharge",                getU32(GlobalDataBuffer[id-1], 37066) / 100, {name: "", unit: "kWh"});
                forcesetState("Solarpower2.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("Solarpower2.Huawei.Inverter." + id + ".Batterystack.2.SN",                     getZeroTerminatedString(GlobalDataBuffer[id-1], 37700, 10), {name: "Serialnumber", unit: ""});        
                    forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.2.BatterySOC",             getU16(GlobalDataBuffer[id-1], 37738) / 10, {name: "", unit: "%"});
                    forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.2.RunningStatus",          getU16(GlobalDataBuffer[id-1], 37741), {name: "", unit: ""});
                    forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.2.ChargeAndDischargePower",getI32(GlobalDataBuffer[id-1], 37743), {name: "", unit: "W"});
                    forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.2.CurrentDayChargeCapacity",    getU32(GlobalDataBuffer[id-1], 37746) / 100, {name: "", unit: "kWh"});
                    forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.2.CurrentDayDischargeCapacity", getU32(GlobalDataBuffer[id-1], 37748) / 100, {name: "", unit: "kWh"});
                    forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.2.BusVoltage",             getU16(GlobalDataBuffer[id-1], 37750) / 10, {name: "", unit: "V"});
                    forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.2.BusCurrent",             getI16(GlobalDataBuffer[id-1], 37751) / 10, {name: "", unit: "A"});
                    forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.2.BatteryTemperature",     getI16(GlobalDataBuffer[id-1], 37752) / 10, {name: "", unit: "°C"});
                    forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.2.TotalCharge",                 getU32(GlobalDataBuffer[id-1], 37753) / 100, {name: "", unit: "kWh"});
                    forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.2.TotalDischarge",              getU32(GlobalDataBuffer[id-1], 37755) / 100, {name: "", unit: "kWh"});
                }
                // Battery register 32-41 (Storage related)
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Battery.RatedCapacity", getU32(GlobalDataBuffer[id-1], 37758) / 1, {name: "", unit: "Wh"});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Battery.SOC", getU16(GlobalDataBuffer[id-1], 37760) / 10, {name: "", unit: "%"});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Battery.RunningStatus", getU16(GlobalDataBuffer[id-1], 37762) / 1, {name: "", unit: ""});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Battery.BusVoltage", getU16(GlobalDataBuffer[id-1], 37763) / 10, {name: "", unit: "V"});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Battery.BusCurrent", getI16(GlobalDataBuffer[id-1], 37764) / 10, {name: "", unit: "A"});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Battery.ChargeAndDischargePower", getI32(GlobalDataBuffer[id-1], 37765) / 1, {name: "", unit: "W"});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Battery.TotalCharge", getU32(GlobalDataBuffer[id-1], 37780) / 100, {name: "", unit: "kWh"});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Battery.TotalDischarge", getU32(GlobalDataBuffer[id-1], 37782) / 100, {name: "", unit: "kWh"});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Battery.CurrentDayChargeCapacity", getU32(GlobalDataBuffer[id-1], 37784) / 100, {name: "", unit: "kWh"});
                forcesetState("Solarpower2.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("Solarpower2.Huawei.Inverter." + id + ".Batterystack.2.SoftwareVersion",    getZeroTerminatedString(GlobalDataBuffer[id-1], 37814, 8), {name: "Softwareversion", unit: ""});
                }
                if(BatteryUnits[id-1][0] > 0) {
                    forcesetState("Solarpower2.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("Solarpower2.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".SN",                getZeroTerminatedString(GlobalDataBuffer[id-1], 38200+(i-1)*126+(j-1)*42, 6), {name: "", unit: ""});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".FirmwareVersion",   getZeroTerminatedString(GlobalDataBuffer[id-1], 38210+(i-1)*126+(j-1)*42, 8), {name: "", unit: ""});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".WorkingStatus",     getU16(GlobalDataBuffer[id-1], 38228+(i-1)*126+(j-1)*42), {name: "", unit: ""});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".BatterySOC",        getU16(GlobalDataBuffer[id-1], 38229+(i-1)*126+(j-1)*42) / 10, {name: "", unit: "%"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".ChargeAndDischargePower", getI32(GlobalDataBuffer[id-1], 38233+(i-1)*126+(j-1)*42) / 1000, {name: "", unit: "kW"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".Voltage",           getU16(GlobalDataBuffer[id-1], 38235+(i-1)*126+(j-1)*42) / 10, {name: "", unit: "V"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".Current",           getI16(GlobalDataBuffer[id-1], 38236+(i-1)*126+(j-1)*42) / 10, {name: "", unit: "A"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".TotalCharge",       getU32(GlobalDataBuffer[id-1], 38238+(i-1)*126+(j-1)*42) / 100, {name: "", unit: "kWh"});
                            forcesetState("Solarpower2.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("Solarpower2.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".MaxTemperature", getI16(GlobalDataBuffer[id-1], 38452+(i-1)*6+(j-1)*2) / 10, {name: "", unit: "°C"});
                            createState("Solarpower2.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("Solarpower2.Huawei.Meter.Status",          getU16(GlobalDataBuffer[PowerMeterID], 37100), {name: "", unit: ""});
                forcesetState("Solarpower2.Huawei.Meter.VoltageL1",        getI32(GlobalDataBuffer[PowerMeterID], 37101)  / 10, {name: "", unit: "V"});
                forcesetState("Solarpower2.Huawei.Meter.VoltageL2",        getI32(GlobalDataBuffer[PowerMeterID], 37103)  / 10, {name: "", unit: "V"});
                forcesetState("Solarpower2.Huawei.Meter.VoltageL3",        getI32(GlobalDataBuffer[PowerMeterID], 37105)  / 10, {name: "", unit: "V"});
                forcesetState("Solarpower2.Huawei.Meter.CurrentL1",        getI32(GlobalDataBuffer[PowerMeterID], 37107)  / 100, {name: "", unit: "A"});
                forcesetState("Solarpower2.Huawei.Meter.CurrentL2",        getI32(GlobalDataBuffer[PowerMeterID], 37109)  / 100, {name: "", unit: "A"});
                forcesetState("Solarpower2.Huawei.Meter.CurrentL3",        getI32(GlobalDataBuffer[PowerMeterID], 37111) / 100, {name: "", unit: "A"});
                forcesetState("Solarpower2.Huawei.Meter.ActivePower",     getI32(GlobalDataBuffer[PowerMeterID], 37113) / 1, {name: "", unit: "W"});
                forcesetState("Solarpower2.Huawei.Meter.ReactivePower",   getI32(GlobalDataBuffer[PowerMeterID], 37115) / 1, {name: "", unit: "Var"});
                forcesetState("Solarpower2.Huawei.Meter.PowerFactor",     getI16(GlobalDataBuffer[PowerMeterID], 37117) / 1000, {name: "", unit: ""});
                forcesetState("Solarpower2.Huawei.Meter.GridFrequency",   getI16(GlobalDataBuffer[PowerMeterID], 37118) / 100, {name: "", unit: "Hz"});
                forcesetState("Solarpower2.Huawei.Meter.PositiveActiveEnergy",     getI32(GlobalDataBuffer[PowerMeterID], 37119) / 100, {name: "", unit: "kWh"});
                forcesetState("Solarpower2.Huawei.Meter.ReverseActiveEnergy",      getI32(GlobalDataBuffer[PowerMeterID], 37121) / 100, {name: "", unit: "kWh"});
                forcesetState("Solarpower2.Huawei.Meter.AccumulatedReactivePower", getI32(GlobalDataBuffer[PowerMeterID], 37123) / 100, {name: "", unit: "kVarh"});
                forcesetState("Solarpower2.Huawei.Meter.MeterType",       getU16(GlobalDataBuffer[PowerMeterID], 37125), {name: "", unit: ""});
                forcesetState("Solarpower2.Huawei.Meter.VoltageL1-L2",       getI32(GlobalDataBuffer[PowerMeterID], 37126) / 10, {name: "", unit: "V"});
                forcesetState("Solarpower2.Huawei.Meter.VoltageL2-L3",       getI32(GlobalDataBuffer[PowerMeterID], 37128) / 10, {name: "", unit: "V"});
                forcesetState("Solarpower2.Huawei.Meter.VoltageL3-L1",       getI32(GlobalDataBuffer[PowerMeterID], 37130) / 10, {name: "", unit: "V"});
                forcesetState("Solarpower2.Huawei.Meter.ActivePowerL1",    getI32(GlobalDataBuffer[PowerMeterID], 37132) / 1, {name: "", unit: "W"});
                forcesetState("Solarpower2.Huawei.Meter.ActivePowerL2",    getI32(GlobalDataBuffer[PowerMeterID], 37134) / 1, {name: "", unit: "W"});
                forcesetState("Solarpower2.Huawei.Meter.ActivePowerL3",    getI32(GlobalDataBuffer[PowerMeterID], 37136) / 1, {name: "", unit: "W"});
                forcesetState("Solarpower2.Huawei.Meter.MeterModel",      getU16(GlobalDataBuffer[PowerMeterID], 37138), {name: "", unit: ""});
            }
            
            function processInverterStatus(id) {
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".State1", getU16(GlobalDataBuffer[id-1], 32000), {name: "", unit: ""});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".State2", getU16(GlobalDataBuffer[id-1], 32001), {name: "", unit: ""});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".State3", getU16(GlobalDataBuffer[id-1], 32002), {name: "", unit: ""});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Alarm1", getU16(GlobalDataBuffer[id-1], 32008), {name: "", unit: ""});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Alarm2", getU16(GlobalDataBuffer[id-1], 32009), {name: "", unit: ""});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Alarm3", getU16(GlobalDataBuffer[id-1], 32010), {name: "", unit: ""});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".String.1_Voltage",       getI16(GlobalDataBuffer[id-1], 32016) / 10  , {name: "", unit: "V"});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".String.1_Current",       getI16(GlobalDataBuffer[id-1], 32017) / 100 , {name: "", unit: "A"});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".String.2_Voltage",       getI16(GlobalDataBuffer[id-1], 32018) / 10  , {name: "", unit: "V"});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".String.2_Current",       getI16(GlobalDataBuffer[id-1], 32019) / 100 , {name: "", unit: "A"});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".InputPower",             getI32(GlobalDataBuffer[id-1], 32064) / 1000, {name: "", unit: "kW"});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Grid.L1-L2_Voltage",           getU16(GlobalDataBuffer[id-1], 32066) / 10  , {name: "", unit: "V"});      
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Grid.L2-L3_Voltage",           getU16(GlobalDataBuffer[id-1], 32067) / 10  , {name: "", unit: "V"});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Grid.L3-L1_Voltage",           getU16(GlobalDataBuffer[id-1], 32068) / 10  , {name: "", unit: "V"});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Grid.L1_Voltage",            getU16(GlobalDataBuffer[id-1], 32069) / 10  , {name: "", unit: "V"});                              
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Grid.L2_Voltage",            getU16(GlobalDataBuffer[id-1], 32070) / 10  , {name: "", unit: "V"});                                                  
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Grid.L3_Voltage",            getU16(GlobalDataBuffer[id-1], 32071) / 10  , {name: "", unit: "V"});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Grid.L1_Current",         getI32(GlobalDataBuffer[id-1], 32072) / 1000, {name: "", unit: "A"});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Grid.L2_Current",         getI32(GlobalDataBuffer[id-1], 32074) / 1000, {name: "", unit: "A"});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Grid.L3_Current",         getI32(GlobalDataBuffer[id-1], 32076) / 1000, {name: "", unit: "A"});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".PeakActivePowerDay",     getI32(GlobalDataBuffer[id-1], 32078) / 1000, {name: "", unit: "kW"});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".ActivePower",            getI32(GlobalDataBuffer[id-1], 32080) / 1000, {name: "", unit: "kW"});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".ReactivePower",          getI32(GlobalDataBuffer[id-1], 32082) / 1000, {name: "", unit: "kVar"});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".PowerFactor",            getI16(GlobalDataBuffer[id-1], 32084) / 1000, {name: "", unit: ""});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".GridFrequency",          getU16(GlobalDataBuffer[id-1], 32085) / 100 , {name: "", unit: "Hz"});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Efficiency",             getU16(GlobalDataBuffer[id-1], 32086) / 100 , {name: "", unit: "%"});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".InternalTemperature",    getI16(GlobalDataBuffer[id-1], 32087) / 10  , {name: "", unit: "°C"});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".InsulationResistance",   getU16(GlobalDataBuffer[id-1], 32088) / 1000, {name: "", unit: "MOhm"});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".DeviceStatus",              getU16(GlobalDataBuffer[id-1], 32089), {name: "", unit: ""});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".FaultCode",                 getU16(GlobalDataBuffer[id-1], 32090), {name: "", unit: ""});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".StartupTime",               getU16(GlobalDataBuffer[id-1], 32091), {name: "", unit: ""});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".ShutdownTime",              getU16(GlobalDataBuffer[id-1], 32093), {name: "", unit: ""});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".AccomulatedEnergyYield",   getU32(GlobalDataBuffer[id-1], 32106) / 100, {name: "", unit: "kWh"});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".DailyEnergyYield",         getU32(GlobalDataBuffer[id-1], 32114) / 100, {name: "", unit: "kWh"});
                
                //forcesetState("Solarpower2.Huawei.Inverter." + id + ".AccomulatedEnergyYield",    getU16(GlobalDataBuffer[id-1], 32106), {name: "", unit: "kWh"});
                //forcesetState("Solarpower2.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("Solarpower2.Huawei.Inverter." + id + ".Model",  getZeroTerminatedString(GlobalDataBuffer[id-1], 30000, 8), {name: "", unit: ""}); 
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".SN",     getZeroTerminatedString(GlobalDataBuffer[id-1], 30015, 6), {name: "", unit: ""});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".PN",     getZeroTerminatedString(GlobalDataBuffer[id-1], 30025, 6), {name: "", unit: ""});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".ModelID",           getU16(GlobalDataBuffer[id-1], 30070), {name: "", unit: ""});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".PVStrings",         getU16(GlobalDataBuffer[id-1], 30071), {name: "", unit: ""});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".MPPTrackers",       getU16(GlobalDataBuffer[id-1], 30072), {name: "", unit: ""});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".MaxRatedPower",     getU32(GlobalDataBuffer[id-1], 30073) / 1000, {name: "", unit: "kW"});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".MaxActivePower",    getU32(GlobalDataBuffer[id-1], 30075) / 1000, {name: "", unit: "kW"});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".MaxApparentPower",  getU32(GlobalDataBuffer[id-1], 30077) / 1000, {name: "", unit: "kVA"});
                forcesetState("Solarpower2.Huawei.Inverter." + id + ".MaxReactivePowerToGrid",        getI32(GlobalDataBuffer[id-1], 30079) / 1000, {name: "", unit: "kVAr"});
                forcesetState("Solarpower2.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;                    
                    }
                }     
            }, 4000);
            
            

            Gruß
            GP

            1 Antwort Letzte Antwort
            0
            • Alex WarkentinA Alex Warkentin

              Du solltest dann das Ursprungs-Script von Kachel aus dem ersten Post nehmen und beide ggf. kombinieren.

              X Offline
              X Offline
              Xanon
              schrieb am zuletzt editiert von Xanon
              #107

              @alex-warkentin
              Hallo, auch bei mir ist jetzt ein Speicher dazugekommen.
              Ich habe wie du empfohlen hast auch das AnfangsScript genommen, allerdings fehlen mir die Kenntnisse alle Optimierungen wie z.B. (den täglichen Ertrag (DailyEnergyYield)) oder (die Zeit für Wechselrichter Shutdown / Start als Uhrzeit / Datum) nachträglich mit einzubauen und ich bekomme immer wieder Fehlermeldungen ins Log und weiss nicht wie ich Sie behandeln kann.

              2023-05-20 11:34:33.284	warn	script.js.Solar.PV_mit_Speicher_Berechnung: Error received reading address 38300 from id: 1 with error: undefined
              
              javascript.0
              2023-05-20 11:33:29.251	warn	script.js.Solar.PV_mit_Speicher_Berechnung: Error received reading address 37800 from id: 1 with error: undefined
              
              javascript.0
              2023-05-20 11:32:27.244	warn	script.js.Solar.PV_mit_Speicher_Berechnung: Error received reading address 37700 from id: 1 with error: undefined
              
              javascript.0
              2023-05-20 11:31:23.234	warn	script.js.Solar.PV_mit_Speicher_Berechnung: Error received reading address 32000 from id: 1 with error: undefined
              
              javascript.0
              2023-05-20 11:31:13.244	warn	script.js.Solar.PV_mit_Speicher_Berechnung: Error received reading address 38300 from id: 1 with error: undefined
              
              javascript.0
              2023-05-20 11:30:19.236	warn	script.js.Solar.PV_mit_Speicher_Berechnung: Error received reading address 30000 from id: 1 with error: undefined
              
              javascript.0
              2023-05-20 11:30:03.237	warn	script.js.Solar.PV_mit_Speicher_Berechnung: Error received reading address 32000 from id: 1 with error: undefined
              
              javascript.0
              2023-05-20 11:29:15.196	warn	script.js.Solar.PV_mit_Speicher_Berechnung: Error received reading address 38400 from id: 1 with error: undefined
              
              javascript.0
              2023-05-20 11:28:13.192	warn	script.js.Solar.PV_mit_Speicher_Berechnung: Error received reading address 38300 from id: 1 with error: undefined
              
              javascript.0
              2023-05-20 11:27:09.180	warn	script.js.Solar.PV_mit_Speicher_Berechnung: Error received reading address 37800 from id: 1 with error: undefined
              
              javascript.0
              2023-05-20 11:26:05.178	warn	script.js.Solar.PV_mit_Speicher_Berechnung: Error received reading address 37000 from id: 1 with error: undefined
              

              Wärst du oder vielleicht jemand anderes so freundlich und würde mir sein Skript welches den Batterie Speicher beinhaltet und optimiert / verbessert ist zur Verfügung stellen?

              Vielen Dank

              1 Antwort Letzte Antwort
              0
              • C Offline
                C Offline
                Chris_B
                schrieb am zuletzt editiert von
                #108

                @Kachel
                Ich habe Deine Skript auch bei mir implementiert (5KWp, 15 kWh Speicher).
                Es läuft, ich hatte aber folgendes Problem bei meiner iobroker Installation: Die Funktion forcesetState() funktioniert bei mir nicht. Dadurch werden das erste Mal die Werte gelesen, danach aber nicht mehr, da nur createState() aufgerufen wird. Ich musste das folgendermassen abändern:

                if (!existsState("javascript.0." + objectname))
                

                D.h. ich muss beim Prüfen des State javascript.0 voranstellen.
                Danach läuft das Skript gut.
                Ich habe eine weitere Optimierung vorgenommen: Jetzt wird bei jedem Setzen der States geprüft ob der State existiert. Das ist ziemlich aufwendig. Ich mache das nun nur ein Mal pro 'Runde', und merke mir das in einer Variable. Dadurch wird nicht dauernd geprüft; spart etwas Processing Power...

                X 1 Antwort Letzte Antwort
                0
                • C Chris_B

                  @Kachel
                  Ich habe Deine Skript auch bei mir implementiert (5KWp, 15 kWh Speicher).
                  Es läuft, ich hatte aber folgendes Problem bei meiner iobroker Installation: Die Funktion forcesetState() funktioniert bei mir nicht. Dadurch werden das erste Mal die Werte gelesen, danach aber nicht mehr, da nur createState() aufgerufen wird. Ich musste das folgendermassen abändern:

                  if (!existsState("javascript.0." + objectname))
                  

                  D.h. ich muss beim Prüfen des State javascript.0 voranstellen.
                  Danach läuft das Skript gut.
                  Ich habe eine weitere Optimierung vorgenommen: Jetzt wird bei jedem Setzen der States geprüft ob der State existiert. Das ist ziemlich aufwendig. Ich mache das nun nur ein Mal pro 'Runde', und merke mir das in einer Variable. Dadurch wird nicht dauernd geprüft; spart etwas Processing Power...

                  X Offline
                  X Offline
                  Xanon
                  schrieb am zuletzt editiert von
                  #109

                  @chris_b
                  Würdest du dein Skript hier zur Verfügung stellen?

                  G C 2 Antworten Letzte Antwort
                  0
                  • X Xanon

                    @chris_b
                    Würdest du dein Skript hier zur Verfügung stellen?

                    G Offline
                    G Offline
                    g.polat
                    schrieb am zuletzt editiert von
                    #110

                    @xanon sagte in Huawei Sun2000 & ioBroker via JS script funktioniert:

                    @chris_b
                    Würdest du dein Skript hier zur Verfügung stellen?

                    Funktioniert bei mir mir 10kw Akku perfekt.

                    // 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("192.168.0.45", { port: 502 });
                    // Enter the Modbus-IDs of your Sun2000 inverters here:
                    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], [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("javascript.0." + objectname)) {
                            createState(objectname, value, options); 
                            console.log("createstate " +  objectname + " to value " + value);            
                        }
                            setState(objectname, value);
                        }
                    // ---------------------------------------------------------------
                    // Functions to map registers into ioBreaker objects:
                    function processOptimizers(id) {
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".OptimizerTotalNumber",     getU16(GlobalDataBuffer[id-1], 35200), {name: "", unit: ""});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".OptimizerOnlineNumber",    getU16(GlobalDataBuffer[id-1], 35201), {name: "", unit: ""});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".OptimizerFeatureData",     getU16(GlobalDataBuffer[id-1], 35202), {name: "", unit: ""});
                    }
                    
                    function processInverterPowerAdjustments(id) {
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".ActiveAdjustement.ActiveAdjustementMode",     getU16(GlobalDataBuffer[id-1], 35300), {name: "", unit: ""});
                        forcesetState("Solarpower2.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("Solarpower2.Huawei.Inverter." + id + ".ActiveAdjustement.ActiveAdjustementCommand",  getU16(GlobalDataBuffer[id-1], 35303), {name: "", unit: ""});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".ActiveAdjustement.ReactiveAdjustementMode",   getU16(GlobalDataBuffer[id-1], 35304), {name: "", unit: ""});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".ActiveAdjustement.ReactiveAdjustementValue",  getU32(GlobalDataBuffer[id-1], 35305), {name: "", unit: ""});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".ActiveAdjustement.ReactiveAdjustementCommand",getU16(GlobalDataBuffer[id-1], 35307), {name: "", unit: ""});
                        forcesetState("Solarpower2.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("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.RunningStatus",          getU16(GlobalDataBuffer[id-1], 37000), {name: "", unit: ""});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.ChargeAndDischargePower",getI32(GlobalDataBuffer[id-1], 37001), {name: "Charge and Discharge Power", unit: "W"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.BusVoltage",             getU16(GlobalDataBuffer[id-1], 37003) / 10, {name: "Busvoltage", unit: "V"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.BatterySOC",             getU16(GlobalDataBuffer[id-1], 37004) / 10, {name: "Battery SOC", unit: "%"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.WorkingMode",            getU16(GlobalDataBuffer[id-1], 37006), {name: "Working Mode", unit: ""});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.RatedChargePower",       getU32(GlobalDataBuffer[id-1], 37007), {name: "", unit: "W"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.RatedDischargePower",    getU32(GlobalDataBuffer[id-1], 37009), {name: "", unit: "W"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.FaultID",                getU16(GlobalDataBuffer[id-1], 37014), {name: "", unit: ""});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.CurrentDayChargeCapacity",    getU32(GlobalDataBuffer[id-1], 37015) / 100, {name: "", unit: "kWh"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.CurrentDayDischargeCapacity", getU32(GlobalDataBuffer[id-1], 37017) / 100, {name: "", unit: "kWh"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.BusCurrent",             getI16(GlobalDataBuffer[id-1], 37021) / 10, {name: "Buscurrent", unit: "A"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.BatteryTemperature",     getI16(GlobalDataBuffer[id-1], 37022) / 10, {name: "Battery Temperatue", unit: "°C"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.RemainingChargeDischargeTime", getU16(GlobalDataBuffer[id-1], 37025), {name: "", unit: "mins"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.DCDCversion",            getZeroTerminatedString(GlobalDataBuffer[id-1], 37026, 10), {name: "", unit: ""});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.BMSversion",             getZeroTerminatedString(GlobalDataBuffer[id-1], 37036, 10), {name: "", unit: ""});
                        }
                        // Battery registers 16+17 (Storage-related)
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".Battery.MaximumChargePower",                getU32(GlobalDataBuffer[id-1], 37046), {name: "", unit: "W"});
                        forcesetState("Solarpower2.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("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.SN",                         getZeroTerminatedString(GlobalDataBuffer[id-1], 37052, 10), {name: "Serialnumber", unit: ""});       
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.TotalCharge",                getU32(GlobalDataBuffer[id-1], 37066) / 100, {name: "", unit: "kWh"});
                        forcesetState("Solarpower2.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("Solarpower2.Huawei.Inverter." + id + ".Batterystack.2.SN",                     getZeroTerminatedString(GlobalDataBuffer[id-1], 37700, 10), {name: "Serialnumber", unit: ""});        
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.2.BatterySOC",             getU16(GlobalDataBuffer[id-1], 37738) / 10, {name: "", unit: "%"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.2.RunningStatus",          getU16(GlobalDataBuffer[id-1], 37741), {name: "", unit: ""});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.2.ChargeAndDischargePower",getI32(GlobalDataBuffer[id-1], 37743), {name: "", unit: "W"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.2.CurrentDayChargeCapacity",    getU32(GlobalDataBuffer[id-1], 37746) / 100, {name: "", unit: "kWh"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.2.CurrentDayDischargeCapacity", getU32(GlobalDataBuffer[id-1], 37748) / 100, {name: "", unit: "kWh"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.2.BusVoltage",             getU16(GlobalDataBuffer[id-1], 37750) / 10, {name: "", unit: "V"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.2.BusCurrent",             getI16(GlobalDataBuffer[id-1], 37751) / 10, {name: "", unit: "A"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.2.BatteryTemperature",     getU16(GlobalDataBuffer[id-1], 37752) / 10, {name: "", unit: "°C"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.2.TotalCharge",                 getU32(GlobalDataBuffer[id-1], 37753) / 100, {name: "", unit: "kWh"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.2.TotalDischarge",              getU32(GlobalDataBuffer[id-1], 37755) / 100, {name: "", unit: "kWh"});
                        }
                        // Battery register 32-41 (Storage related)
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".Battery.RatedCapacity", getU32(GlobalDataBuffer[id-1], 37758) / 1, {name: "", unit: "Wh"});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".Battery.SOC", getU16(GlobalDataBuffer[id-1], 37760) / 10, {name: "", unit: "%"});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".Battery.RunningStatus", getU16(GlobalDataBuffer[id-1], 37762) / 1, {name: "", unit: ""});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".Battery.BusVoltage", getU16(GlobalDataBuffer[id-1], 37763) / 10, {name: "", unit: "V"});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".Battery.BusCurrent", getI16(GlobalDataBuffer[id-1], 37764) / 10, {name: "", unit: "A"});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".Battery.ChargeAndDischargePower", getI32(GlobalDataBuffer[id-1], 37765) / 1, {name: "", unit: "W"});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".Battery.TotalCharge", getU32(GlobalDataBuffer[id-1], 37780) / 100, {name: "", unit: "kWh"});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".Battery.TotalDischarge", getU32(GlobalDataBuffer[id-1], 37782) / 100, {name: "", unit: "kWh"});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".Battery.CurrentDayChargeCapacity", getU32(GlobalDataBuffer[id-1], 37784) / 100, {name: "", unit: "kWh"});
                        forcesetState("Solarpower2.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("Solarpower2.Huawei.Inverter." + id + ".Batterystack.2.SoftwareVersion",    getZeroTerminatedString(GlobalDataBuffer[id-1], 37814, 8), {name: "Softwareversion", unit: ""});
                        }
                        if(BatteryUnits[id-1][0] > 0) {
                            forcesetState("Solarpower2.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("Solarpower2.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".SN",                getZeroTerminatedString(GlobalDataBuffer[id-1], 38200+(i-1)*126+(j-1)*42, 6), {name: "", unit: ""});
                                    forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".FirmwareVersion",   getZeroTerminatedString(GlobalDataBuffer[id-1], 38210+(i-1)*126+(j-1)*42, 8), {name: "", unit: ""});
                                    forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".WorkingStatus",     getU16(GlobalDataBuffer[id-1], 38228+(i-1)*126+(j-1)*42), {name: "", unit: ""});
                                    forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".BatterySOC",        getU16(GlobalDataBuffer[id-1], 38229+(i-1)*126+(j-1)*42) / 10, {name: "", unit: "%"});
                                    forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".ChargeAndDischargePower", getI32(GlobalDataBuffer[id-1], 38233+(i-1)*126+(j-1)*42) / 1000, {name: "", unit: "kW"});
                                    forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".Voltage",           getU16(GlobalDataBuffer[id-1], 38235+(i-1)*126+(j-1)*42) / 10, {name: "", unit: "V"});
                                    forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".Current",           getI16(GlobalDataBuffer[id-1], 38236+(i-1)*126+(j-1)*42) / 10, {name: "", unit: "A"});
                                    forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".TotalCharge",       getU32(GlobalDataBuffer[id-1], 38238+(i-1)*126+(j-1)*42) / 100, {name: "", unit: "kWh"});
                                    forcesetState("Solarpower2.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("Solarpower2.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".MaxTemperature", getI16(GlobalDataBuffer[id-1], 38452+(i-1)*6+(j-1)*2) / 10, {name: "", unit: "°C"});
                                    createState("Solarpower2.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("Solarpower2.Huawei.Meter.Status",          getU16(GlobalDataBuffer[PowerMeterID], 37100), {name: "", unit: ""});
                        forcesetState("Solarpower2.Huawei.Meter.VoltageL1",        getI32(GlobalDataBuffer[PowerMeterID], 37101)  / 10, {name: "", unit: "V"});
                        forcesetState("Solarpower2.Huawei.Meter.VoltageL2",        getI32(GlobalDataBuffer[PowerMeterID], 37103)  / 10, {name: "", unit: "V"});
                        forcesetState("Solarpower2.Huawei.Meter.VoltageL3",        getI32(GlobalDataBuffer[PowerMeterID], 37105)  / 10, {name: "", unit: "V"});
                        forcesetState("Solarpower2.Huawei.Meter.CurrentL1",        getI32(GlobalDataBuffer[PowerMeterID], 37107)  / 100, {name: "", unit: "A"});
                        forcesetState("Solarpower2.Huawei.Meter.CurrentL2",        getI32(GlobalDataBuffer[PowerMeterID], 37109)  / 100, {name: "", unit: "A"});
                        forcesetState("Solarpower2.Huawei.Meter.CurrentL3",        getI32(GlobalDataBuffer[PowerMeterID], 37111) / 100, {name: "", unit: "A"});
                        forcesetState("Solarpower2.Huawei.Meter.ActivePower",     getI32(GlobalDataBuffer[PowerMeterID], 37113) / 1, {name: "", unit: "W"});
                        forcesetState("Solarpower2.Huawei.Meter.ReactivePower",   getI32(GlobalDataBuffer[PowerMeterID], 37115) / 1, {name: "", unit: "Var"});
                        forcesetState("Solarpower2.Huawei.Meter.PowerFactor",     getI16(GlobalDataBuffer[PowerMeterID], 37117) / 1000, {name: "", unit: ""});
                        forcesetState("Solarpower2.Huawei.Meter.GridFrequency",   getI16(GlobalDataBuffer[PowerMeterID], 37118) / 100, {name: "", unit: "Hz"});
                        forcesetState("Solarpower2.Huawei.Meter.PositiveActiveEnergy",     getI32(GlobalDataBuffer[PowerMeterID], 37119) / 100, {name: "", unit: "kWh"});
                        forcesetState("Solarpower2.Huawei.Meter.ReverseActiveEnergy",      getI32(GlobalDataBuffer[PowerMeterID], 37121) / 100, {name: "", unit: "kWh"});
                        forcesetState("Solarpower2.Huawei.Meter.AccumulatedReactivePower", getI32(GlobalDataBuffer[PowerMeterID], 37123) / 100, {name: "", unit: "kVarh"});
                        forcesetState("Solarpower2.Huawei.Meter.MeterType",       getU16(GlobalDataBuffer[PowerMeterID], 37125), {name: "", unit: ""});
                        forcesetState("Solarpower2.Huawei.Meter.VoltageL1-L2",       getI32(GlobalDataBuffer[PowerMeterID], 37126) / 10, {name: "", unit: "V"});
                        forcesetState("Solarpower2.Huawei.Meter.VoltageL2-L3",       getI32(GlobalDataBuffer[PowerMeterID], 37128) / 10, {name: "", unit: "V"});
                        forcesetState("Solarpower2.Huawei.Meter.VoltageL3-L1",       getI32(GlobalDataBuffer[PowerMeterID], 37130) / 10, {name: "", unit: "V"});
                        forcesetState("Solarpower2.Huawei.Meter.ActivePowerL1",    getI32(GlobalDataBuffer[PowerMeterID], 37132) / 1, {name: "", unit: "W"});
                        forcesetState("Solarpower2.Huawei.Meter.ActivePowerL2",    getI32(GlobalDataBuffer[PowerMeterID], 37134) / 1, {name: "", unit: "W"});
                        forcesetState("Solarpower2.Huawei.Meter.ActivePowerL3",    getI32(GlobalDataBuffer[PowerMeterID], 37136) / 1, {name: "", unit: "W"});
                        forcesetState("Solarpower2.Huawei.Meter.MeterModel",      getU16(GlobalDataBuffer[PowerMeterID], 37138), {name: "", unit: ""});
                    }
                    
                    function processInverterStatus(id) {
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".State1", getU16(GlobalDataBuffer[id-1], 32000), {name: "", unit: ""});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".State2", getU16(GlobalDataBuffer[id-1], 32001), {name: "", unit: ""});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".State3", getU16(GlobalDataBuffer[id-1], 32002), {name: "", unit: ""});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".Alarm1", getU16(GlobalDataBuffer[id-1], 32008), {name: "", unit: ""});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".Alarm2", getU16(GlobalDataBuffer[id-1], 32009), {name: "", unit: ""});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".Alarm3", getU16(GlobalDataBuffer[id-1], 32010), {name: "", unit: ""});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".String.1_Voltage",       getI16(GlobalDataBuffer[id-1], 32016) / 10  , {name: "", unit: "V"});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".String.1_Current",       getI16(GlobalDataBuffer[id-1], 32017) / 100 , {name: "", unit: "A"});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".String.2_Voltage",       getI16(GlobalDataBuffer[id-1], 32018) / 10  , {name: "", unit: "V"});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".String.2_Current",       getI16(GlobalDataBuffer[id-1], 32019) / 100 , {name: "", unit: "A"});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".InputPower",             getI32(GlobalDataBuffer[id-1], 32064) / 1000, {name: "", unit: "kW"});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".Grid.L1-L2_Voltage",           getU16(GlobalDataBuffer[id-1], 32066) / 10  , {name: "", unit: "V"});      
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".Grid.L2-L3_Voltage",           getU16(GlobalDataBuffer[id-1], 32067) / 10  , {name: "", unit: "V"});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".Grid.L3-L1_Voltage",           getU16(GlobalDataBuffer[id-1], 32068) / 10  , {name: "", unit: "V"});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".Grid.L1_Voltage",            getU16(GlobalDataBuffer[id-1], 32069) / 10  , {name: "", unit: "V"});                              
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".Grid.L2_Voltage",            getU16(GlobalDataBuffer[id-1], 32070) / 10  , {name: "", unit: "V"});                                                  
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".Grid.L3_Voltage",            getU16(GlobalDataBuffer[id-1], 32071) / 10  , {name: "", unit: "V"});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".Grid.L1_Current",         getI32(GlobalDataBuffer[id-1], 32072) / 1000, {name: "", unit: "A"});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".Grid.L2_Current",         getI32(GlobalDataBuffer[id-1], 32074) / 1000, {name: "", unit: "A"});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".Grid.L3_Current",         getI32(GlobalDataBuffer[id-1], 32076) / 1000, {name: "", unit: "A"});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".PeakActivePowerDay",     getI32(GlobalDataBuffer[id-1], 32078) / 1000, {name: "", unit: "kW"});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".ActivePower",            getI32(GlobalDataBuffer[id-1], 32080) / 1000, {name: "", unit: "kW"});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".ReactivePower",          getI32(GlobalDataBuffer[id-1], 32082) / 1000, {name: "", unit: "kVar"});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".PowerFactor",            getI16(GlobalDataBuffer[id-1], 32084) / 1000, {name: "", unit: ""});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".GridFrequency",          getU16(GlobalDataBuffer[id-1], 32085) / 100 , {name: "", unit: "Hz"});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".Efficiency",             getU16(GlobalDataBuffer[id-1], 32086) / 100 , {name: "", unit: "%"});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".InternalTemperature",    getI16(GlobalDataBuffer[id-1], 32087) / 10  , {name: "", unit: "°C"});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".InsulationResistance",   getU16(GlobalDataBuffer[id-1], 32088) / 1000, {name: "", unit: "MOhm"});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".DeviceStatus",              getU16(GlobalDataBuffer[id-1], 32089), {name: "", unit: ""});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".FaultCode",                 getU16(GlobalDataBuffer[id-1], 32090), {name: "", unit: ""});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".StartupTime",               getU16(GlobalDataBuffer[id-1], 32091), {name: "", unit: ""});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".ShutdownTime",              getU16(GlobalDataBuffer[id-1], 32093), {name: "", unit: ""});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".AccomulatedEnergyYield",   getU32(GlobalDataBuffer[id-1], 32106) / 100, {name: "", unit: "kWh"});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".DailyEnergyYield",         getU32(GlobalDataBuffer[id-1], 32114) / 100, {name: "", unit: "kWh"});
                        
                        //forcesetState("Solarpower.Huawei.Inverter." + id + ".AccomulatedEnergyYield",    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("Solarpower2.Huawei.Inverter." + id + ".Model",  getZeroTerminatedString(GlobalDataBuffer[id-1], 30000, 8), {name: "", unit: ""}); 
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".SN",     getZeroTerminatedString(GlobalDataBuffer[id-1], 30015, 6), {name: "", unit: ""});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".PN",     getZeroTerminatedString(GlobalDataBuffer[id-1], 30025, 6), {name: "", unit: ""});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".ModelID",           getU16(GlobalDataBuffer[id-1], 30070), {name: "", unit: ""});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".PVStrings",         getU16(GlobalDataBuffer[id-1], 30071), {name: "", unit: ""});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".MPPTrackers",       getU16(GlobalDataBuffer[id-1], 30072), {name: "", unit: ""});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".MaxRatedPower",     getU32(GlobalDataBuffer[id-1], 30073) / 1000, {name: "", unit: "kW"});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".MaxActivePower",    getU32(GlobalDataBuffer[id-1], 30075) / 1000, {name: "", unit: "kW"});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".MaxApparentPower",  getU32(GlobalDataBuffer[id-1], 30077) / 1000, {name: "", unit: "kVA"});
                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".MaxReactivePowerToGrid",        getI32(GlobalDataBuffer[id-1], 30079) / 1000, {name: "", unit: "kVAr"});
                        forcesetState("Solarpower2.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;                    
                            }
                        }     
                    }, 4000);
                    
                    
                    X 1 Antwort Letzte Antwort
                    0
                    • X Xanon

                      @chris_b
                      Würdest du dein Skript hier zur Verfügung stellen?

                      C Offline
                      C Offline
                      Chris_B
                      schrieb am zuletzt editiert von
                      #111

                      @xanon Mach' ich in den nächsten 1-2 Tagen. Ich möchte noch ein paar weitere Verbesserungen vornehmen, dann stelle ich das Skript zur Verfügung.

                      X 1 Antwort Letzte Antwort
                      0
                      • G g.polat

                        @xanon sagte in Huawei Sun2000 & ioBroker via JS script funktioniert:

                        @chris_b
                        Würdest du dein Skript hier zur Verfügung stellen?

                        Funktioniert bei mir mir 10kw Akku perfekt.

                        // 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("192.168.0.45", { port: 502 });
                        // Enter the Modbus-IDs of your Sun2000 inverters here:
                        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], [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("javascript.0." + objectname)) {
                                createState(objectname, value, options); 
                                console.log("createstate " +  objectname + " to value " + value);            
                            }
                                setState(objectname, value);
                            }
                        // ---------------------------------------------------------------
                        // Functions to map registers into ioBreaker objects:
                        function processOptimizers(id) {
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".OptimizerTotalNumber",     getU16(GlobalDataBuffer[id-1], 35200), {name: "", unit: ""});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".OptimizerOnlineNumber",    getU16(GlobalDataBuffer[id-1], 35201), {name: "", unit: ""});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".OptimizerFeatureData",     getU16(GlobalDataBuffer[id-1], 35202), {name: "", unit: ""});
                        }
                        
                        function processInverterPowerAdjustments(id) {
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".ActiveAdjustement.ActiveAdjustementMode",     getU16(GlobalDataBuffer[id-1], 35300), {name: "", unit: ""});
                            forcesetState("Solarpower2.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("Solarpower2.Huawei.Inverter." + id + ".ActiveAdjustement.ActiveAdjustementCommand",  getU16(GlobalDataBuffer[id-1], 35303), {name: "", unit: ""});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".ActiveAdjustement.ReactiveAdjustementMode",   getU16(GlobalDataBuffer[id-1], 35304), {name: "", unit: ""});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".ActiveAdjustement.ReactiveAdjustementValue",  getU32(GlobalDataBuffer[id-1], 35305), {name: "", unit: ""});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".ActiveAdjustement.ReactiveAdjustementCommand",getU16(GlobalDataBuffer[id-1], 35307), {name: "", unit: ""});
                            forcesetState("Solarpower2.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("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.RunningStatus",          getU16(GlobalDataBuffer[id-1], 37000), {name: "", unit: ""});
                                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.ChargeAndDischargePower",getI32(GlobalDataBuffer[id-1], 37001), {name: "Charge and Discharge Power", unit: "W"});
                                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.BusVoltage",             getU16(GlobalDataBuffer[id-1], 37003) / 10, {name: "Busvoltage", unit: "V"});
                                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.BatterySOC",             getU16(GlobalDataBuffer[id-1], 37004) / 10, {name: "Battery SOC", unit: "%"});
                                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.WorkingMode",            getU16(GlobalDataBuffer[id-1], 37006), {name: "Working Mode", unit: ""});
                                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.RatedChargePower",       getU32(GlobalDataBuffer[id-1], 37007), {name: "", unit: "W"});
                                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.RatedDischargePower",    getU32(GlobalDataBuffer[id-1], 37009), {name: "", unit: "W"});
                                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.FaultID",                getU16(GlobalDataBuffer[id-1], 37014), {name: "", unit: ""});
                                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.CurrentDayChargeCapacity",    getU32(GlobalDataBuffer[id-1], 37015) / 100, {name: "", unit: "kWh"});
                                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.CurrentDayDischargeCapacity", getU32(GlobalDataBuffer[id-1], 37017) / 100, {name: "", unit: "kWh"});
                                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.BusCurrent",             getI16(GlobalDataBuffer[id-1], 37021) / 10, {name: "Buscurrent", unit: "A"});
                                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.BatteryTemperature",     getI16(GlobalDataBuffer[id-1], 37022) / 10, {name: "Battery Temperatue", unit: "°C"});
                                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.RemainingChargeDischargeTime", getU16(GlobalDataBuffer[id-1], 37025), {name: "", unit: "mins"});
                                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.DCDCversion",            getZeroTerminatedString(GlobalDataBuffer[id-1], 37026, 10), {name: "", unit: ""});
                                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.BMSversion",             getZeroTerminatedString(GlobalDataBuffer[id-1], 37036, 10), {name: "", unit: ""});
                            }
                            // Battery registers 16+17 (Storage-related)
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Battery.MaximumChargePower",                getU32(GlobalDataBuffer[id-1], 37046), {name: "", unit: "W"});
                            forcesetState("Solarpower2.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("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.SN",                         getZeroTerminatedString(GlobalDataBuffer[id-1], 37052, 10), {name: "Serialnumber", unit: ""});       
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.1.TotalCharge",                getU32(GlobalDataBuffer[id-1], 37066) / 100, {name: "", unit: "kWh"});
                            forcesetState("Solarpower2.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("Solarpower2.Huawei.Inverter." + id + ".Batterystack.2.SN",                     getZeroTerminatedString(GlobalDataBuffer[id-1], 37700, 10), {name: "Serialnumber", unit: ""});        
                                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.2.BatterySOC",             getU16(GlobalDataBuffer[id-1], 37738) / 10, {name: "", unit: "%"});
                                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.2.RunningStatus",          getU16(GlobalDataBuffer[id-1], 37741), {name: "", unit: ""});
                                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.2.ChargeAndDischargePower",getI32(GlobalDataBuffer[id-1], 37743), {name: "", unit: "W"});
                                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.2.CurrentDayChargeCapacity",    getU32(GlobalDataBuffer[id-1], 37746) / 100, {name: "", unit: "kWh"});
                                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.2.CurrentDayDischargeCapacity", getU32(GlobalDataBuffer[id-1], 37748) / 100, {name: "", unit: "kWh"});
                                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.2.BusVoltage",             getU16(GlobalDataBuffer[id-1], 37750) / 10, {name: "", unit: "V"});
                                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.2.BusCurrent",             getI16(GlobalDataBuffer[id-1], 37751) / 10, {name: "", unit: "A"});
                                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.2.BatteryTemperature",     getU16(GlobalDataBuffer[id-1], 37752) / 10, {name: "", unit: "°C"});
                                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.2.TotalCharge",                 getU32(GlobalDataBuffer[id-1], 37753) / 100, {name: "", unit: "kWh"});
                                forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack.2.TotalDischarge",              getU32(GlobalDataBuffer[id-1], 37755) / 100, {name: "", unit: "kWh"});
                            }
                            // Battery register 32-41 (Storage related)
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Battery.RatedCapacity", getU32(GlobalDataBuffer[id-1], 37758) / 1, {name: "", unit: "Wh"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Battery.SOC", getU16(GlobalDataBuffer[id-1], 37760) / 10, {name: "", unit: "%"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Battery.RunningStatus", getU16(GlobalDataBuffer[id-1], 37762) / 1, {name: "", unit: ""});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Battery.BusVoltage", getU16(GlobalDataBuffer[id-1], 37763) / 10, {name: "", unit: "V"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Battery.BusCurrent", getI16(GlobalDataBuffer[id-1], 37764) / 10, {name: "", unit: "A"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Battery.ChargeAndDischargePower", getI32(GlobalDataBuffer[id-1], 37765) / 1, {name: "", unit: "W"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Battery.TotalCharge", getU32(GlobalDataBuffer[id-1], 37780) / 100, {name: "", unit: "kWh"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Battery.TotalDischarge", getU32(GlobalDataBuffer[id-1], 37782) / 100, {name: "", unit: "kWh"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Battery.CurrentDayChargeCapacity", getU32(GlobalDataBuffer[id-1], 37784) / 100, {name: "", unit: "kWh"});
                            forcesetState("Solarpower2.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("Solarpower2.Huawei.Inverter." + id + ".Batterystack.2.SoftwareVersion",    getZeroTerminatedString(GlobalDataBuffer[id-1], 37814, 8), {name: "Softwareversion", unit: ""});
                            }
                            if(BatteryUnits[id-1][0] > 0) {
                                forcesetState("Solarpower2.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("Solarpower2.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".SN",                getZeroTerminatedString(GlobalDataBuffer[id-1], 38200+(i-1)*126+(j-1)*42, 6), {name: "", unit: ""});
                                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".FirmwareVersion",   getZeroTerminatedString(GlobalDataBuffer[id-1], 38210+(i-1)*126+(j-1)*42, 8), {name: "", unit: ""});
                                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".WorkingStatus",     getU16(GlobalDataBuffer[id-1], 38228+(i-1)*126+(j-1)*42), {name: "", unit: ""});
                                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".BatterySOC",        getU16(GlobalDataBuffer[id-1], 38229+(i-1)*126+(j-1)*42) / 10, {name: "", unit: "%"});
                                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".ChargeAndDischargePower", getI32(GlobalDataBuffer[id-1], 38233+(i-1)*126+(j-1)*42) / 1000, {name: "", unit: "kW"});
                                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".Voltage",           getU16(GlobalDataBuffer[id-1], 38235+(i-1)*126+(j-1)*42) / 10, {name: "", unit: "V"});
                                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".Current",           getI16(GlobalDataBuffer[id-1], 38236+(i-1)*126+(j-1)*42) / 10, {name: "", unit: "A"});
                                        forcesetState("Solarpower2.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".TotalCharge",       getU32(GlobalDataBuffer[id-1], 38238+(i-1)*126+(j-1)*42) / 100, {name: "", unit: "kWh"});
                                        forcesetState("Solarpower2.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("Solarpower2.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".MaxTemperature", getI16(GlobalDataBuffer[id-1], 38452+(i-1)*6+(j-1)*2) / 10, {name: "", unit: "°C"});
                                        createState("Solarpower2.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("Solarpower2.Huawei.Meter.Status",          getU16(GlobalDataBuffer[PowerMeterID], 37100), {name: "", unit: ""});
                            forcesetState("Solarpower2.Huawei.Meter.VoltageL1",        getI32(GlobalDataBuffer[PowerMeterID], 37101)  / 10, {name: "", unit: "V"});
                            forcesetState("Solarpower2.Huawei.Meter.VoltageL2",        getI32(GlobalDataBuffer[PowerMeterID], 37103)  / 10, {name: "", unit: "V"});
                            forcesetState("Solarpower2.Huawei.Meter.VoltageL3",        getI32(GlobalDataBuffer[PowerMeterID], 37105)  / 10, {name: "", unit: "V"});
                            forcesetState("Solarpower2.Huawei.Meter.CurrentL1",        getI32(GlobalDataBuffer[PowerMeterID], 37107)  / 100, {name: "", unit: "A"});
                            forcesetState("Solarpower2.Huawei.Meter.CurrentL2",        getI32(GlobalDataBuffer[PowerMeterID], 37109)  / 100, {name: "", unit: "A"});
                            forcesetState("Solarpower2.Huawei.Meter.CurrentL3",        getI32(GlobalDataBuffer[PowerMeterID], 37111) / 100, {name: "", unit: "A"});
                            forcesetState("Solarpower2.Huawei.Meter.ActivePower",     getI32(GlobalDataBuffer[PowerMeterID], 37113) / 1, {name: "", unit: "W"});
                            forcesetState("Solarpower2.Huawei.Meter.ReactivePower",   getI32(GlobalDataBuffer[PowerMeterID], 37115) / 1, {name: "", unit: "Var"});
                            forcesetState("Solarpower2.Huawei.Meter.PowerFactor",     getI16(GlobalDataBuffer[PowerMeterID], 37117) / 1000, {name: "", unit: ""});
                            forcesetState("Solarpower2.Huawei.Meter.GridFrequency",   getI16(GlobalDataBuffer[PowerMeterID], 37118) / 100, {name: "", unit: "Hz"});
                            forcesetState("Solarpower2.Huawei.Meter.PositiveActiveEnergy",     getI32(GlobalDataBuffer[PowerMeterID], 37119) / 100, {name: "", unit: "kWh"});
                            forcesetState("Solarpower2.Huawei.Meter.ReverseActiveEnergy",      getI32(GlobalDataBuffer[PowerMeterID], 37121) / 100, {name: "", unit: "kWh"});
                            forcesetState("Solarpower2.Huawei.Meter.AccumulatedReactivePower", getI32(GlobalDataBuffer[PowerMeterID], 37123) / 100, {name: "", unit: "kVarh"});
                            forcesetState("Solarpower2.Huawei.Meter.MeterType",       getU16(GlobalDataBuffer[PowerMeterID], 37125), {name: "", unit: ""});
                            forcesetState("Solarpower2.Huawei.Meter.VoltageL1-L2",       getI32(GlobalDataBuffer[PowerMeterID], 37126) / 10, {name: "", unit: "V"});
                            forcesetState("Solarpower2.Huawei.Meter.VoltageL2-L3",       getI32(GlobalDataBuffer[PowerMeterID], 37128) / 10, {name: "", unit: "V"});
                            forcesetState("Solarpower2.Huawei.Meter.VoltageL3-L1",       getI32(GlobalDataBuffer[PowerMeterID], 37130) / 10, {name: "", unit: "V"});
                            forcesetState("Solarpower2.Huawei.Meter.ActivePowerL1",    getI32(GlobalDataBuffer[PowerMeterID], 37132) / 1, {name: "", unit: "W"});
                            forcesetState("Solarpower2.Huawei.Meter.ActivePowerL2",    getI32(GlobalDataBuffer[PowerMeterID], 37134) / 1, {name: "", unit: "W"});
                            forcesetState("Solarpower2.Huawei.Meter.ActivePowerL3",    getI32(GlobalDataBuffer[PowerMeterID], 37136) / 1, {name: "", unit: "W"});
                            forcesetState("Solarpower2.Huawei.Meter.MeterModel",      getU16(GlobalDataBuffer[PowerMeterID], 37138), {name: "", unit: ""});
                        }
                        
                        function processInverterStatus(id) {
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".State1", getU16(GlobalDataBuffer[id-1], 32000), {name: "", unit: ""});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".State2", getU16(GlobalDataBuffer[id-1], 32001), {name: "", unit: ""});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".State3", getU16(GlobalDataBuffer[id-1], 32002), {name: "", unit: ""});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Alarm1", getU16(GlobalDataBuffer[id-1], 32008), {name: "", unit: ""});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Alarm2", getU16(GlobalDataBuffer[id-1], 32009), {name: "", unit: ""});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Alarm3", getU16(GlobalDataBuffer[id-1], 32010), {name: "", unit: ""});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".String.1_Voltage",       getI16(GlobalDataBuffer[id-1], 32016) / 10  , {name: "", unit: "V"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".String.1_Current",       getI16(GlobalDataBuffer[id-1], 32017) / 100 , {name: "", unit: "A"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".String.2_Voltage",       getI16(GlobalDataBuffer[id-1], 32018) / 10  , {name: "", unit: "V"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".String.2_Current",       getI16(GlobalDataBuffer[id-1], 32019) / 100 , {name: "", unit: "A"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".InputPower",             getI32(GlobalDataBuffer[id-1], 32064) / 1000, {name: "", unit: "kW"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Grid.L1-L2_Voltage",           getU16(GlobalDataBuffer[id-1], 32066) / 10  , {name: "", unit: "V"});      
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Grid.L2-L3_Voltage",           getU16(GlobalDataBuffer[id-1], 32067) / 10  , {name: "", unit: "V"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Grid.L3-L1_Voltage",           getU16(GlobalDataBuffer[id-1], 32068) / 10  , {name: "", unit: "V"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Grid.L1_Voltage",            getU16(GlobalDataBuffer[id-1], 32069) / 10  , {name: "", unit: "V"});                              
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Grid.L2_Voltage",            getU16(GlobalDataBuffer[id-1], 32070) / 10  , {name: "", unit: "V"});                                                  
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Grid.L3_Voltage",            getU16(GlobalDataBuffer[id-1], 32071) / 10  , {name: "", unit: "V"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Grid.L1_Current",         getI32(GlobalDataBuffer[id-1], 32072) / 1000, {name: "", unit: "A"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Grid.L2_Current",         getI32(GlobalDataBuffer[id-1], 32074) / 1000, {name: "", unit: "A"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Grid.L3_Current",         getI32(GlobalDataBuffer[id-1], 32076) / 1000, {name: "", unit: "A"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".PeakActivePowerDay",     getI32(GlobalDataBuffer[id-1], 32078) / 1000, {name: "", unit: "kW"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".ActivePower",            getI32(GlobalDataBuffer[id-1], 32080) / 1000, {name: "", unit: "kW"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".ReactivePower",          getI32(GlobalDataBuffer[id-1], 32082) / 1000, {name: "", unit: "kVar"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".PowerFactor",            getI16(GlobalDataBuffer[id-1], 32084) / 1000, {name: "", unit: ""});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".GridFrequency",          getU16(GlobalDataBuffer[id-1], 32085) / 100 , {name: "", unit: "Hz"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".Efficiency",             getU16(GlobalDataBuffer[id-1], 32086) / 100 , {name: "", unit: "%"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".InternalTemperature",    getI16(GlobalDataBuffer[id-1], 32087) / 10  , {name: "", unit: "°C"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".InsulationResistance",   getU16(GlobalDataBuffer[id-1], 32088) / 1000, {name: "", unit: "MOhm"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".DeviceStatus",              getU16(GlobalDataBuffer[id-1], 32089), {name: "", unit: ""});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".FaultCode",                 getU16(GlobalDataBuffer[id-1], 32090), {name: "", unit: ""});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".StartupTime",               getU16(GlobalDataBuffer[id-1], 32091), {name: "", unit: ""});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".ShutdownTime",              getU16(GlobalDataBuffer[id-1], 32093), {name: "", unit: ""});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".AccomulatedEnergyYield",   getU32(GlobalDataBuffer[id-1], 32106) / 100, {name: "", unit: "kWh"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".DailyEnergyYield",         getU32(GlobalDataBuffer[id-1], 32114) / 100, {name: "", unit: "kWh"});
                            
                            //forcesetState("Solarpower.Huawei.Inverter." + id + ".AccomulatedEnergyYield",    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("Solarpower2.Huawei.Inverter." + id + ".Model",  getZeroTerminatedString(GlobalDataBuffer[id-1], 30000, 8), {name: "", unit: ""}); 
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".SN",     getZeroTerminatedString(GlobalDataBuffer[id-1], 30015, 6), {name: "", unit: ""});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".PN",     getZeroTerminatedString(GlobalDataBuffer[id-1], 30025, 6), {name: "", unit: ""});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".ModelID",           getU16(GlobalDataBuffer[id-1], 30070), {name: "", unit: ""});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".PVStrings",         getU16(GlobalDataBuffer[id-1], 30071), {name: "", unit: ""});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".MPPTrackers",       getU16(GlobalDataBuffer[id-1], 30072), {name: "", unit: ""});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".MaxRatedPower",     getU32(GlobalDataBuffer[id-1], 30073) / 1000, {name: "", unit: "kW"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".MaxActivePower",    getU32(GlobalDataBuffer[id-1], 30075) / 1000, {name: "", unit: "kW"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".MaxApparentPower",  getU32(GlobalDataBuffer[id-1], 30077) / 1000, {name: "", unit: "kVA"});
                            forcesetState("Solarpower2.Huawei.Inverter." + id + ".MaxReactivePowerToGrid",        getI32(GlobalDataBuffer[id-1], 30079) / 1000, {name: "", unit: "kVAr"});
                            forcesetState("Solarpower2.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;                    
                                }
                            }     
                        }, 4000);
                        
                        
                        X Offline
                        X Offline
                        Xanon
                        schrieb am zuletzt editiert von
                        #112

                        @g-polat Super Vielen Dank
                        Werde ich mal testen 👍

                        1 Antwort Letzte Antwort
                        0
                        • C Chris_B

                          @xanon Mach' ich in den nächsten 1-2 Tagen. Ich möchte noch ein paar weitere Verbesserungen vornehmen, dann stelle ich das Skript zur Verfügung.

                          X Offline
                          X Offline
                          Xanon
                          schrieb am zuletzt editiert von
                          #113

                          @chris_b
                          Ok, bin gespannt, was du noch aus dem Skript heraus zauberst.😊
                          Danke für deine Mühe.👍

                          C 1 Antwort Letzte Antwort
                          0
                          • X Xanon

                            @chris_b
                            Ok, bin gespannt, was du noch aus dem Skript heraus zauberst.😊
                            Danke für deine Mühe.👍

                            C Offline
                            C Offline
                            Chris_B
                            schrieb am zuletzt editiert von
                            #114

                            @xanon
                            Hier schon einmal vorab mein aktueller Stand des Skripts. Dazu folgende Bemerkungen:

                            • Das Skript ist noch nicht wirklich fertig. Ich komme aber erst am Wochenende dazu noch mehr Funktionalität einzubauen. Ich werde dann ein Update posten.
                            • Die Sache mit createState() ist jetzt optimiert.
                            • Neuer State: javascript.0.Solarpower.Dervied.PeakPower --> Zeigt den Max Wert der Panels an einem Tag an.
                            • Neuer State: javascript.0.Solarpower.Dervied.BatteryOverview --> hier werden die % Werte jedes Battery Packs angezeigt, momentan fix für 3, sollte ich allgemeiner schreiben.

                            Ich werde am Wochenende weiter am Skript arbeiten und weitere Funktionen einfügen. Habe aber bis dann keine Zeit.

                            // 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.Dervied.PeakPower", 0,  {read: true, write: true, name: "Peak Solar Panel Power today"});
                            createState("javascript.0.Solarpower.Dervied.BatteryOverview", "",  {read: true, write: true, name: "Battery Overview SOC"});
                            
                            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.1.127", { 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], 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.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.Dervied.BatteryOverview", BatOverview);
                            
                                // determine maximum power delivery of today (this is reset at midnight)
                                var PeakPV = parseFloat(getState("javascript.0.Solarpower.Huawei.Inverter.1.InputPower").val);
                                PeakPV = max(PeakPV, getState("javascript.0.Solarpower.Dervied.PeakPower").val);
                                setState("javascript.0.Solarpower.Dervied.PeakPower", PeakPV);
                            
                                console.debug("Processing done!");  // this was originally .log
                            }
                            
                            
                            var triggerprocessing = 0; 
                            var currentinverter = 1;
                            
                            // one minute before midnight: reset min/max variables
                            schedule("59 23 * * *", function ()
                            {   
                                setState("javascript.0.Solarpower.Dervied.PeakPower", 0);
                            });
                            
                            
                            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);
                            

                            Hier noch ein Screenshot meiner Vis. Auch diese ist erst im Aufbau, möchte ich noch stark verbessern...
                            8df625ee-4603-4aae-9927-06cc52a445fa-grafik.png

                            S C 2 Antworten Letzte Antwort
                            0
                            • C Chris_B

                              @xanon
                              Hier schon einmal vorab mein aktueller Stand des Skripts. Dazu folgende Bemerkungen:

                              • Das Skript ist noch nicht wirklich fertig. Ich komme aber erst am Wochenende dazu noch mehr Funktionalität einzubauen. Ich werde dann ein Update posten.
                              • Die Sache mit createState() ist jetzt optimiert.
                              • Neuer State: javascript.0.Solarpower.Dervied.PeakPower --> Zeigt den Max Wert der Panels an einem Tag an.
                              • Neuer State: javascript.0.Solarpower.Dervied.BatteryOverview --> hier werden die % Werte jedes Battery Packs angezeigt, momentan fix für 3, sollte ich allgemeiner schreiben.

                              Ich werde am Wochenende weiter am Skript arbeiten und weitere Funktionen einfügen. Habe aber bis dann keine Zeit.

                              // 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.Dervied.PeakPower", 0,  {read: true, write: true, name: "Peak Solar Panel Power today"});
                              createState("javascript.0.Solarpower.Dervied.BatteryOverview", "",  {read: true, write: true, name: "Battery Overview SOC"});
                              
                              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.1.127", { 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], 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.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.Dervied.BatteryOverview", BatOverview);
                              
                                  // determine maximum power delivery of today (this is reset at midnight)
                                  var PeakPV = parseFloat(getState("javascript.0.Solarpower.Huawei.Inverter.1.InputPower").val);
                                  PeakPV = max(PeakPV, getState("javascript.0.Solarpower.Dervied.PeakPower").val);
                                  setState("javascript.0.Solarpower.Dervied.PeakPower", PeakPV);
                              
                                  console.debug("Processing done!");  // this was originally .log
                              }
                              
                              
                              var triggerprocessing = 0; 
                              var currentinverter = 1;
                              
                              // one minute before midnight: reset min/max variables
                              schedule("59 23 * * *", function ()
                              {   
                                  setState("javascript.0.Solarpower.Dervied.PeakPower", 0);
                              });
                              
                              
                              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);
                              

                              Hier noch ein Screenshot meiner Vis. Auch diese ist erst im Aufbau, möchte ich noch stark verbessern...
                              8df625ee-4603-4aae-9927-06cc52a445fa-grafik.png

                              S Offline
                              S Offline
                              spooky82
                              schrieb am zuletzt editiert von
                              #115

                              @chris_b

                              Hallo,

                              ich habe wohl ein Verständnisproblem.
                              Ich habe das Skript und den easee Adapter eingerichtet und alle Datenpunkte mMn korrekt gesetzt.
                              Das Laden geht jedoch nicht los.
                              Habt ihr Ideen?

                              6303f803-4b05-4fd2-8452-9aa7380f3608-image.png

                              ce878160-6e5c-47f3-b039-d6b2bf026b6f-image.png

                              3c553291-ba34-461a-8ab6-484a46857849-image.png 050572b2-4e9d-48b9-aa2c-9f57c6a49de9-image.png

                              e0acf878-0445-478d-9c5f-e7590337a550-image.png

                              Dankeschön

                              C 1 Antwort Letzte Antwort
                              0
                              • S spooky82

                                @chris_b

                                Hallo,

                                ich habe wohl ein Verständnisproblem.
                                Ich habe das Skript und den easee Adapter eingerichtet und alle Datenpunkte mMn korrekt gesetzt.
                                Das Laden geht jedoch nicht los.
                                Habt ihr Ideen?

                                6303f803-4b05-4fd2-8452-9aa7380f3608-image.png

                                ce878160-6e5c-47f3-b039-d6b2bf026b6f-image.png

                                3c553291-ba34-461a-8ab6-484a46857849-image.png 050572b2-4e9d-48b9-aa2c-9f57c6a49de9-image.png

                                e0acf878-0445-478d-9c5f-e7590337a550-image.png

                                Dankeschön

                                C Offline
                                C Offline
                                Chris_B
                                schrieb am zuletzt editiert von
                                #116

                                @spooky82 Sorry, aber da muss eine Verwechslung voliegen. Das von mir abgeänderte Skript oben ist für Huawei Sun2000 / Luna2000 Anlagen. Für das Auslesen der Anlagen via TCP / Modbus braucht man ausschliesslich das Skript, wie oben in diversen Beiträgen beschrieben.
                                Die Datenpunkte dafür befinden sich dann unter javascript.0.Solarpower....
                                Gruss

                                S 1 Antwort Letzte Antwort
                                0
                                • C Chris_B

                                  @xanon
                                  Hier schon einmal vorab mein aktueller Stand des Skripts. Dazu folgende Bemerkungen:

                                  • Das Skript ist noch nicht wirklich fertig. Ich komme aber erst am Wochenende dazu noch mehr Funktionalität einzubauen. Ich werde dann ein Update posten.
                                  • Die Sache mit createState() ist jetzt optimiert.
                                  • Neuer State: javascript.0.Solarpower.Dervied.PeakPower --> Zeigt den Max Wert der Panels an einem Tag an.
                                  • Neuer State: javascript.0.Solarpower.Dervied.BatteryOverview --> hier werden die % Werte jedes Battery Packs angezeigt, momentan fix für 3, sollte ich allgemeiner schreiben.

                                  Ich werde am Wochenende weiter am Skript arbeiten und weitere Funktionen einfügen. Habe aber bis dann keine Zeit.

                                  // 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.Dervied.PeakPower", 0,  {read: true, write: true, name: "Peak Solar Panel Power today"});
                                  createState("javascript.0.Solarpower.Dervied.BatteryOverview", "",  {read: true, write: true, name: "Battery Overview SOC"});
                                  
                                  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.1.127", { 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], 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.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.Dervied.BatteryOverview", BatOverview);
                                  
                                      // determine maximum power delivery of today (this is reset at midnight)
                                      var PeakPV = parseFloat(getState("javascript.0.Solarpower.Huawei.Inverter.1.InputPower").val);
                                      PeakPV = max(PeakPV, getState("javascript.0.Solarpower.Dervied.PeakPower").val);
                                      setState("javascript.0.Solarpower.Dervied.PeakPower", PeakPV);
                                  
                                      console.debug("Processing done!");  // this was originally .log
                                  }
                                  
                                  
                                  var triggerprocessing = 0; 
                                  var currentinverter = 1;
                                  
                                  // one minute before midnight: reset min/max variables
                                  schedule("59 23 * * *", function ()
                                  {   
                                      setState("javascript.0.Solarpower.Dervied.PeakPower", 0);
                                  });
                                  
                                  
                                  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);
                                  

                                  Hier noch ein Screenshot meiner Vis. Auch diese ist erst im Aufbau, möchte ich noch stark verbessern...
                                  8df625ee-4603-4aae-9927-06cc52a445fa-grafik.png

                                  C Offline
                                  C Offline
                                  Chris_B
                                  schrieb am zuletzt editiert von
                                  #117

                                  @chris_b Ich bin immer noch an der Anänderung des Skripts. Habe noch ein paar Fehler darin gefunden (falsche Skalierung der Werte). Ich brauche noch etwas mehr Zeit. Hier mein aktueller Stand für das UI (im Wesentlichen eine Nachbildung der Huawei App, aber, wenn ich dann fertig bin, so, wie es mir passt, und mit zusätzlicher Information.
                                  (Dies ist ein noch fehlerhafter Zwischenstand)
                                  28775814-8e3f-48ad-a981-6710a7f6a438-grafik.png

                                  S 1 Antwort Letzte Antwort
                                  0
                                  • C Chris_B

                                    @spooky82 Sorry, aber da muss eine Verwechslung voliegen. Das von mir abgeänderte Skript oben ist für Huawei Sun2000 / Luna2000 Anlagen. Für das Auslesen der Anlagen via TCP / Modbus braucht man ausschliesslich das Skript, wie oben in diversen Beiträgen beschrieben.
                                    Die Datenpunkte dafür befinden sich dann unter javascript.0.Solarpower....
                                    Gruss

                                    S Offline
                                    S Offline
                                    spooky82
                                    schrieb am zuletzt editiert von
                                    #118

                                    @chris_b

                                    Sorry, hast absolut Recht. Falsches Forum.
                                    Danke dir!

                                    1 Antwort Letzte Antwort
                                    0
                                    • C Chris_B

                                      @chris_b Ich bin immer noch an der Anänderung des Skripts. Habe noch ein paar Fehler darin gefunden (falsche Skalierung der Werte). Ich brauche noch etwas mehr Zeit. Hier mein aktueller Stand für das UI (im Wesentlichen eine Nachbildung der Huawei App, aber, wenn ich dann fertig bin, so, wie es mir passt, und mit zusätzlicher Information.
                                      (Dies ist ein noch fehlerhafter Zwischenstand)
                                      28775814-8e3f-48ad-a981-6710a7f6a438-grafik.png

                                      S Offline
                                      S Offline
                                      Sweatchuck
                                      schrieb am zuletzt editiert von
                                      #119

                                      @chris_b

                                      Hallo Chris,

                                      ich hätte starkes Interesse an deinem Script. Node-red ist leider nichts für mich ;-)

                                      Meine PV-Konfiguration ist sehr ähnlich.

                                      2 Strings (Ost/West), Powermeter, Optimierer und 1x Akkuturm mit 3x 5kwh Packs.

                                      Würde mich freuen wenn du deine Arbeit mit uns/mir teilen würdest.

                                      Grüße

                                      C 1 Antwort Letzte Antwort
                                      0
                                      • S Sweatchuck

                                        @chris_b

                                        Hallo Chris,

                                        ich hätte starkes Interesse an deinem Script. Node-red ist leider nichts für mich ;-)

                                        Meine PV-Konfiguration ist sehr ähnlich.

                                        2 Strings (Ost/West), Powermeter, Optimierer und 1x Akkuturm mit 3x 5kwh Packs.

                                        Würde mich freuen wenn du deine Arbeit mit uns/mir teilen würdest.

                                        Grüße

                                        C Offline
                                        C Offline
                                        Chris_B
                                        schrieb am zuletzt editiert von
                                        #120

                                        @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);
                                        });
                                        
                                        
                                        S S 2 Antworten Letzte Antwort
                                        1
                                        • C Chris_B

                                          @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);
                                          });
                                          
                                          
                                          S Offline
                                          S Offline
                                          Sweatchuck
                                          schrieb am zuletzt editiert von
                                          #121

                                          @chris_b

                                          Vielen herzlichen Dank.

                                          Deine Updates/Verbesserungen würde ich natürlich gerne auch bei mir integrieren.

                                          Wenn ich bei der Entwicklung/Weiterentwicklung unterstützen kann (Tester etc.), lass es mich wissen!

                                          Gruß

                                          C 1 Antwort Letzte Antwort
                                          0
                                          Antworten
                                          • In einem neuen Thema antworten
                                          Anmelden zum Antworten
                                          • Älteste zuerst
                                          • Neuste zuerst
                                          • Meiste Stimmen


                                          Support us

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

                                          497

                                          Online

                                          32.4k

                                          Benutzer

                                          81.4k

                                          Themen

                                          1.3m

                                          Beiträge
                                          Community
                                          Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen | Einwilligungseinstellungen
                                          ioBroker Community 2014-2025
                                          logo
                                          • Anmelden

                                          • Du hast noch kein Konto? Registrieren

                                          • Anmelden oder registrieren, um zu suchen
                                          • Erster Beitrag
                                            Letzter Beitrag
                                          0
                                          • Home
                                          • Aktuell
                                          • Tags
                                          • Ungelesen 0
                                          • Kategorien
                                          • Unreplied
                                          • Beliebt
                                          • GitHub
                                          • Docu
                                          • Hilfe