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

Huawei Sun2000 & ioBroker via JS script funktioniert

Geplant Angeheftet Gesperrt Verschoben ioBroker Allgemein
481 Beiträge 62 Kommentatoren 121.4k 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.
  • 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
                      • A Offline
                        A Offline
                        anno171986
                        schrieb am zuletzt editiert von anno171986
                        #122

                        @Chris_B Vielen Dank für dein Skript. Ich habe die vorletzte Vdersion und mit der Ausnahme der Datenpunkterzeugung läuft es auch gut.

                        Was mich ein bisschen ärgert ist, das Huawei anscheinend nicht alle Werte hier per API bereitstellt die man über die App sieht. Mich interessiert z.B. der Gesamtstromverbrauch am Tag. Kann man den aus den vorliegenden Werten berechnen, bin da noch nicht fündig geworden.

                        VG

                        C 1 Antwort Letzte Antwort
                        0
                        • S Sweatchuck

                          @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 Offline
                          C Offline
                          Chris_B
                          schrieb am zuletzt editiert von
                          #123

                          @sweatchuck
                          Mach ich gerne. Und Feedback, Testen sind sehr willkommen. Gerne würde ich mich auch in Sachen Sun2000 / Luna 2000 austauschen. Ich habe da noch einige Fragen. Ich melde mich am Wochenende. Bin gerade ziemlich mit Arbeit zu...
                          Danke und Gruss

                          1 Antwort Letzte Antwort
                          0
                          • A anno171986

                            @Chris_B Vielen Dank für dein Skript. Ich habe die vorletzte Vdersion und mit der Ausnahme der Datenpunkterzeugung läuft es auch gut.

                            Was mich ein bisschen ärgert ist, das Huawei anscheinend nicht alle Werte hier per API bereitstellt die man über die App sieht. Mich interessiert z.B. der Gesamtstromverbrauch am Tag. Kann man den aus den vorliegenden Werten berechnen, bin da noch nicht fündig geworden.

                            VG

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

                            @anno171986 Was meinst Du genau mit dem Problem der Datenpunkterzeugung?
                            Am besten Skript stoppen, Alle Datenpunkte löschen und Skript wieder neu starten.
                            Noch eine Bemerkung: Gewisse Datenpunkte werden erst 'sinnvoll' wenn einmal Mitternacht durch ist, da Differenzen zum Vortag benötigt werden...
                            Gruss

                            A 1 Antwort Letzte Antwort
                            0
                            • C Chris_B

                              @anno171986 Was meinst Du genau mit dem Problem der Datenpunkterzeugung?
                              Am besten Skript stoppen, Alle Datenpunkte löschen und Skript wieder neu starten.
                              Noch eine Bemerkung: Gewisse Datenpunkte werden erst 'sinnvoll' wenn einmal Mitternacht durch ist, da Differenzen zum Vortag benötigt werden...
                              Gruss

                              A Offline
                              A Offline
                              anno171986
                              schrieb am zuletzt editiert von anno171986
                              #125

                              @chris_b
                              Vorweg: ich habe mein Skript noch nicht mit deinem neuen Stand vom 05.06.2023 aktualisiert.
                              Bei mir waren die Werte immer nur einmal aktualisiert worden, n achdem ich die Dtaenpunkte gelöscht hatte. Dann wurden sie per Skript einmaöl neu angelegt aber danach nicht mehr aktualisiert. Habe jetzt Teile ausgeklammert, damit funktioniert es:

                              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(Folder + objectname)) { createState(objectname, value, options); }
                                      else                                            { setState(objectname, value); testCreateState = 1; }
                                  } else
                                  {   setState(objectname, value);
                                  }
                                  */
                                  setState(objectname, value);
                              }  
                              

                              Wieviel kwh du verbraucht hast, das kannst du auch nicht auslesen oder berechnen, richtig?

                              C 1 Antwort Letzte Antwort
                              0
                              • A anno171986

                                @chris_b
                                Vorweg: ich habe mein Skript noch nicht mit deinem neuen Stand vom 05.06.2023 aktualisiert.
                                Bei mir waren die Werte immer nur einmal aktualisiert worden, n achdem ich die Dtaenpunkte gelöscht hatte. Dann wurden sie per Skript einmaöl neu angelegt aber danach nicht mehr aktualisiert. Habe jetzt Teile ausgeklammert, damit funktioniert es:

                                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(Folder + objectname)) { createState(objectname, value, options); }
                                        else                                            { setState(objectname, value); testCreateState = 1; }
                                    } else
                                    {   setState(objectname, value);
                                    }
                                    */
                                    setState(objectname, value);
                                }  
                                

                                Wieviel kwh du verbraucht hast, das kannst du auch nicht auslesen oder berechnen, richtig?

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

                                @anno171986 Ganz kurz: Bitte das neuste Skript nehmen. Das mit den Datenpunkten ist ein Problem des ursprünglichen Skripts (nicht von mir). Nochmals alle Datenpunkte löschen und das neuste Skript nehmen.
                                Den Verbrauch an einem Tag kann man rechnen. Das habe ich noch nicht gemacht, ist nicht sehr kompliziert, kommt vermutlich am Wochenende. Bitte etwas Geduld…
                                Ich möchte auch noch eine bessere Doku machen, damit es verständlich ist, was das Skript macht und kann. Ich möchte alle sinnvollen Werte der Huawei App in iobroker darstellen können…
                                Gruss

                                R 1 Antwort Letzte Antwort
                                0
                                • C Chris_B

                                  @anno171986 Ganz kurz: Bitte das neuste Skript nehmen. Das mit den Datenpunkten ist ein Problem des ursprünglichen Skripts (nicht von mir). Nochmals alle Datenpunkte löschen und das neuste Skript nehmen.
                                  Den Verbrauch an einem Tag kann man rechnen. Das habe ich noch nicht gemacht, ist nicht sehr kompliziert, kommt vermutlich am Wochenende. Bitte etwas Geduld…
                                  Ich möchte auch noch eine bessere Doku machen, damit es verständlich ist, was das Skript macht und kann. Ich möchte alle sinnvollen Werte der Huawei App in iobroker darstellen können…
                                  Gruss

                                  R Offline
                                  R Offline
                                  road_runner31
                                  schrieb am zuletzt editiert von road_runner31
                                  #127

                                  @chris_b Hi, ich habe diesen Thread gerade gefunden und das Script bei mir installiert. Wenn ich es starte, erscheinen nach einigen Sekunden Warnungen, die dann zyklisch wiederholt werden
                                  3806a15e-8c37-4ee2-8752-6267e944d054-image.png
                                  In den Objekten erscheinen Werte, die zunächst grün sind, dann rot werden. Auch scheinen die Werte falsch formatiert zu sein?
                                  0e0fb81d-eb37-40fc-b080-4965b245fb82-image.png
                                  Hab ich irgendwo einen Fehler in der Konfiguration gemacht?
                                  0d753b80-cda5-4b25-8bda-9f9269fc984c-image.png
                                  Der Battery Overview scheint ja auch nicht zu klappen.
                                  Habe eine SUN2000 mit 10kWh Speicher in 2 Modulen.. Ein Tipp wäre super!
                                  Und: VIELEN DANK für die Arbeit, die da drin steckt! :)

                                  C exelE 2 Antworten Letzte Antwort
                                  0
                                  • R road_runner31

                                    @chris_b Hi, ich habe diesen Thread gerade gefunden und das Script bei mir installiert. Wenn ich es starte, erscheinen nach einigen Sekunden Warnungen, die dann zyklisch wiederholt werden
                                    3806a15e-8c37-4ee2-8752-6267e944d054-image.png
                                    In den Objekten erscheinen Werte, die zunächst grün sind, dann rot werden. Auch scheinen die Werte falsch formatiert zu sein?
                                    0e0fb81d-eb37-40fc-b080-4965b245fb82-image.png
                                    Hab ich irgendwo einen Fehler in der Konfiguration gemacht?
                                    0d753b80-cda5-4b25-8bda-9f9269fc984c-image.png
                                    Der Battery Overview scheint ja auch nicht zu klappen.
                                    Habe eine SUN2000 mit 10kWh Speicher in 2 Modulen.. Ein Tipp wäre super!
                                    Und: VIELEN DANK für die Arbeit, die da drin steckt! :)

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

                                    @road_runner31 Hallo. Kurz ein paar Hinweise. Das ursprüngliche Skript ist nicht von mir, siehe ganz oben in diesem thread. Ich habe das Skript abgeändert, Fehler korrigiert und bin am erweitern. Was mir einfällt:

                                    1. Im Javascript Adapter muss (!!) Modbus-Serial eingetragen sein:
                                      2ff9b482-b420-4f49-ae75-ac99dff72798-grafik.png
                                    2. Prüfe Deine IP Adresse.
                                    3. Die PowerMeterID musst Du ausprobieren, scheint aber meist 0 zu sein.
                                    4. Du schreibst, dass Deine Luna2000 2 Module hat, dann solltest Du auch entsprechen BatteryUnits = [[2, 0]]; schreiben.
                                    5. Einige Werte unter 'Derived' sind erst nach dem erstamligen Überschreiten von Mitternacht sinnvoll gefüllt.

                                    Mehr fällt mir gerade nicht ein. Gruss

                                    R 1 Antwort Letzte Antwort
                                    0
                                    • C Chris_B

                                      @road_runner31 Hallo. Kurz ein paar Hinweise. Das ursprüngliche Skript ist nicht von mir, siehe ganz oben in diesem thread. Ich habe das Skript abgeändert, Fehler korrigiert und bin am erweitern. Was mir einfällt:

                                      1. Im Javascript Adapter muss (!!) Modbus-Serial eingetragen sein:
                                        2ff9b482-b420-4f49-ae75-ac99dff72798-grafik.png
                                      2. Prüfe Deine IP Adresse.
                                      3. Die PowerMeterID musst Du ausprobieren, scheint aber meist 0 zu sein.
                                      4. Du schreibst, dass Deine Luna2000 2 Module hat, dann solltest Du auch entsprechen BatteryUnits = [[2, 0]]; schreiben.
                                      5. Einige Werte unter 'Derived' sind erst nach dem erstamligen Überschreiten von Mitternacht sinnvoll gefüllt.

                                      Mehr fällt mir gerade nicht ein. Gruss

                                      R Offline
                                      R Offline
                                      road_runner31
                                      schrieb am zuletzt editiert von
                                      #129

                                      @chris_b Hallo, danke für die Antworten. Die Anzahl der Module hab ich schon korrigiert. Die IP-Adresse stimmt, es sind ja auch ein paar Werte korrekt (bspw. das Modell). "modbus-serial" ist auch eingebunden.
                                      Ich lasse das Script jetzt mal laufen, trotz Fehlern, mal schauen was morgen drinsteht..
                                      Viele Grüße!

                                      C 1 Antwort Letzte Antwort
                                      0
                                      • R road_runner31

                                        @chris_b Hallo, danke für die Antworten. Die Anzahl der Module hab ich schon korrigiert. Die IP-Adresse stimmt, es sind ja auch ein paar Werte korrekt (bspw. das Modell). "modbus-serial" ist auch eingebunden.
                                        Ich lasse das Script jetzt mal laufen, trotz Fehlern, mal schauen was morgen drinsteht..
                                        Viele Grüße!

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

                                        @road_runner31 Ich glaube aber, dass Du noch ein anderes Problem hast bei Deiner Anlage. Die Sache mit den Werten nach Mitternacht kann das nicht sein, das ergibt nur am ersten Tag für ein paar Werte sinnlose Zahlen, aber keine Fehlermeldungen.
                                        Ich glaube Deine Sun2000 ist nicht ansprechbar. Anwortet sie auf ein PING? Das würde ich einmal als nächstes checken. Gruss

                                        1 Antwort Letzte Antwort
                                        0
                                        • R road_runner31

                                          @chris_b Hi, ich habe diesen Thread gerade gefunden und das Script bei mir installiert. Wenn ich es starte, erscheinen nach einigen Sekunden Warnungen, die dann zyklisch wiederholt werden
                                          3806a15e-8c37-4ee2-8752-6267e944d054-image.png
                                          In den Objekten erscheinen Werte, die zunächst grün sind, dann rot werden. Auch scheinen die Werte falsch formatiert zu sein?
                                          0e0fb81d-eb37-40fc-b080-4965b245fb82-image.png
                                          Hab ich irgendwo einen Fehler in der Konfiguration gemacht?
                                          0d753b80-cda5-4b25-8bda-9f9269fc984c-image.png
                                          Der Battery Overview scheint ja auch nicht zu klappen.
                                          Habe eine SUN2000 mit 10kWh Speicher in 2 Modulen.. Ein Tipp wäre super!
                                          Und: VIELEN DANK für die Arbeit, die da drin steckt! :)

                                          exelE Offline
                                          exelE Offline
                                          exel
                                          schrieb am zuletzt editiert von exel
                                          #131

                                          @road_runner31 Ich kann das Verhalten bestätigen, sieht bei mir genauso aus.

                                          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

                                          528

                                          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