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.
  • Alex WarkentinA Alex Warkentin

    @juggi1962 Poste mal die Logs, wenn der Fehler auftritt

    Hier ist das Script, was ich für mich angepasst habe. Achtung! Ich habe die Batterie und andere für mich uninteressante Sachen rausgeschmissen und die Namen von Variablen und Funktionen angepasst. Für die Neuverbindung nach Verbindungsabbruch brauchst du die Zeilen 18 - 27 , 107-122 und 235 -237

    // License: Beerware! Do what ever you like with this, but I'm not liable for anything that you do with it.
    // If you like this code, feel free to buy me a beer ...
    // Have fun with it! der Kachel
    // @ts-ignore
    var modbusRTU = require("modbus-serial");
    var client = new modbusRTU();
    
    var modbusErrorMessages = [
        "Unknown error",
        "Illegal function (device does not support this read/write function)",
        "Illegal data address (register not supported by device)",
        "Illegal data value (value cannot be written to this register)",
        "Slave device failure (device reports internal error)",
        "Acknowledge (requested data will be available later)",
        "Slave device busy (retry request again later)"
    ];
    
    // Enter your inverter modbus IP and port here:
    const modbusHost = "000.000.000.000";
    const modbusPort = 502;
    // Enter the Modbus-IDs of your Sun2000 inverters here:
    const modbusID = [1];
    // On which Modbus-ID can we reach the power meter? (via Sun2000!)
    const powerMeterID = 0;
    
    // Connect to modbus client
    ConnectModbus();
    
    // These register spaces need to be read:
    const registerSpacesToReadContinuously = [[37100, 114], [32000, 116]];
    var registerSpacesToReadContinuouslyPtr = 0;
    
    var globalDataBuffer = new Array(1);
    globalDataBuffer[0] = new Array(50000); // not optimized....
    
    // ---------------------------------------------------------------
    // Some helper functions:
    function ReadUnsignedInt16(array) {
        var value = array[0];    
        return value;
    }
    
    function ReadUnsignedInt32(array) {
        var value = array[0] * 256 * 256 + array[1];    
        return value;
    }
    
    function ReadSignedInt16(array) {
        var value = 0;
        if (array[0] > 32767)
            value = array[0] - 65535; 
        else
            value = array[0];
    
        return value;
    }
    function ReadSignedInt32(array) {
        var value = 0;
        for (var i = 0; i < 2; i++) {
            value = (value << 16) | array[i];
        }
        return value;
    }
    function GetU16(dataarray, index) {
        var value = ReadUnsignedInt16(dataarray.slice(index, index+1));
        return value;
    }
    
    function GetU32(dataarray, index) {
        var value = ReadUnsignedInt32(dataarray.slice(index, index+2));
        return value;
    }
    
    function GetI16(dataarray, index) {
        var value = ReadSignedInt16(dataarray.slice(index, index+1));
        return value;
    }
    
    function GetI32(dataarray, index) {
        var value = ReadSignedInt32(dataarray.slice(index, index+2));
        return value;
    }
    
    function GetString(dataarray, index, length) {
        var shortarray = dataarray.slice(index, index+length);
        var bytearray = [];
        for(var i = 0; i < length; i++) {
            bytearray.push(dataarray[index+i] >> 8);
            bytearray.push(dataarray[index+i] & 0xff);
        }       
        var value =  String.fromCharCode.apply(null, bytearray);    
        return value;
    }
    
    function GetZeroTerminatedString(dataarray, index, length) {
        var shortarray = dataarray.slice(index, index+length);
        var bytearray = [];
        for(var i = 0; i < length; i++) {
            bytearray.push(dataarray[index+i] >> 8);
            bytearray.push(dataarray[index+i] & 0xff);
        }       
        var value =  String.fromCharCode.apply(null, bytearray);    
        var value2 = new String(value).trim();
        return value2;
    }
    
    // Funktion zum Herstellen einer Modbus-Verbindung
    function ConnectModbus() {
        console.log("Init connection to: " + modbusHost +":" + modbusPort);
        // set requests parameters
        client.setTimeout (10000);
        // try to connect
        client.connectTCP (modbusHost, { port: modbusPort })
            .then(function()
            {
                console.log("Connected, wait for reading...");
            })
            .catch(function(e)
            {
                console.log(e);
            });
    }
    
    // Funktion zum Anlegen und Beschreiben eines Datenpunkts
    function ForceSetState(objectname, value, options) {
        if(!existsState("javascript.0." + objectname))      createState(objectname, value, options);
        else                                                setState(objectname, value);
    }  
    // ---------------------------------------------------------------
    // Functions to map registers into ioBreaker objects:
    function ProcessPowerMeterStatus() {       
        ForceSetState("Solarpower.Huawei.Meter.Status",                     GetU16(globalDataBuffer[powerMeterID], 37100),          {name: "", unit: ""});
        ForceSetState("Solarpower.Huawei.Meter.VoltageL1",                  GetI32(globalDataBuffer[powerMeterID], 37101) / 10,     {name: "", unit: "V"});
        ForceSetState("Solarpower.Huawei.Meter.VoltageL2",                  GetI32(globalDataBuffer[powerMeterID], 37103) / 10,     {name: "", unit: "V"});
        ForceSetState("Solarpower.Huawei.Meter.VoltageL3",                  GetI32(globalDataBuffer[powerMeterID], 37105) / 10,     {name: "", unit: "V"});
        ForceSetState("Solarpower.Huawei.Meter.CurrentL1",                  GetI32(globalDataBuffer[powerMeterID], 37107) / 100,    {name: "", unit: "A"});
        ForceSetState("Solarpower.Huawei.Meter.CurrentL2",                  GetI32(globalDataBuffer[powerMeterID], 37109) / 100,    {name: "", unit: "A"});
        ForceSetState("Solarpower.Huawei.Meter.CurrentL3",                  GetI32(globalDataBuffer[powerMeterID], 37111) / 100,    {name: "", unit: "A"});
        ForceSetState("Solarpower.Huawei.Meter.ActivePower",                GetI32(globalDataBuffer[powerMeterID], 37113) / 1,      {name: "", unit: "W"});
        ForceSetState("Solarpower.Huawei.Meter.ReactivePower",              GetI32(globalDataBuffer[powerMeterID], 37115) / 1,      {name: "", unit: "Var"});
        ForceSetState("Solarpower.Huawei.Meter.PowerFactor",                GetI16(globalDataBuffer[powerMeterID], 37117) / 1000,   {name: "", unit: ""});
        ForceSetState("Solarpower.Huawei.Meter.GridFrequency",              GetI16(globalDataBuffer[powerMeterID], 37118) / 100,    {name: "", unit: "Hz"});
        ForceSetState("Solarpower.Huawei.Meter.PositiveActiveEnergy",       GetI32(globalDataBuffer[powerMeterID], 37119) / 100,    {name: "", unit: "kWh"});
        ForceSetState("Solarpower.Huawei.Meter.ReverseActiveEnergy",        GetI32(globalDataBuffer[powerMeterID], 37121) / 100,    {name: "", unit: "kWh"});
        ForceSetState("Solarpower.Huawei.Meter.AccumulatedReactivePower",   GetI32(globalDataBuffer[powerMeterID], 37123) / 100,    {name: "", unit: "kVarh"});
        //ForceSetState("Solarpower.Huawei.Meter.MeterType",                  GetU16(globalDataBuffer[powerMeterID], 37125),          {name: "", unit: ""});
        ForceSetState("Solarpower.Huawei.Meter.VoltageL1-L2",               GetI32(globalDataBuffer[powerMeterID], 37126) / 10,     {name: "", unit: "V"});
        ForceSetState("Solarpower.Huawei.Meter.VoltageL2-L3",               GetI32(globalDataBuffer[powerMeterID], 37128) / 10,     {name: "", unit: "V"});
        ForceSetState("Solarpower.Huawei.Meter.VoltageL3-L1",               GetI32(globalDataBuffer[powerMeterID], 37130) / 10,     {name: "", unit: "V"});
        ForceSetState("Solarpower.Huawei.Meter.ActivePowerL1",              GetI32(globalDataBuffer[powerMeterID], 37132) / 1,      {name: "", unit: "W"});
        ForceSetState("Solarpower.Huawei.Meter.ActivePowerL2",              GetI32(globalDataBuffer[powerMeterID], 37134) / 1,      {name: "", unit: "W"});
        ForceSetState("Solarpower.Huawei.Meter.ActivePowerL3",              GetI32(globalDataBuffer[powerMeterID], 37136) / 1,      {name: "", unit: "W"});
        //ForceSetState("Solarpower.Huawei.Meter.MeterModel",                 GetU16(globalDataBuffer[powerMeterID], 37138),          {name: "", unit: ""});
    }
    
    function ProcessInverterStatus(id) {
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".State1",                   GetU16(globalDataBuffer[id-1], 32000),          {name: "", unit: ""});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".State2",                   GetU16(globalDataBuffer[id-1], 32002),          {name: "", unit: ""});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".State3",                   GetU32(globalDataBuffer[id-1], 32003),          {name: "", unit: ""});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".Alarm1",                   GetU16(globalDataBuffer[id-1], 32008),          {name: "", unit: ""});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".Alarm2",                   GetU16(globalDataBuffer[id-1], 32009),          {name: "", unit: ""});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".Alarm3",                   GetU16(globalDataBuffer[id-1], 32010),          {name: "", unit: ""});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.1_Voltage",         GetI16(globalDataBuffer[id-1], 32016) / 10,     {name: "", unit: "V"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.1_Current",         GetI16(globalDataBuffer[id-1], 32017) / 100,    {name: "", unit: "A"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.2_Voltage",         GetI16(globalDataBuffer[id-1], 32018) / 10,     {name: "", unit: "V"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.2_Current",         GetI16(globalDataBuffer[id-1], 32019) / 100,    {name: "", unit: "A"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.3_Voltage",         GetI16(globalDataBuffer[id-1], 32020) / 10,     {name: "", unit: "V"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.3_Current",         GetI16(globalDataBuffer[id-1], 32021) / 100,    {name: "", unit: "A"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.4_Voltage",         GetI16(globalDataBuffer[id-1], 32022) / 10,     {name: "", unit: "V"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.4_Current",         GetI16(globalDataBuffer[id-1], 32023) / 100,    {name: "", unit: "A"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".InputPower",               GetI32(globalDataBuffer[id-1], 32064) / 1000,   {name: "", unit: "kW"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1-L2_Voltage",       GetU16(globalDataBuffer[id-1], 32066) / 10,     {name: "", unit: "V"});      
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2-L3_Voltage",       GetU16(globalDataBuffer[id-1], 32067) / 10,     {name: "", unit: "V"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3-L1_Voltage",       GetU16(globalDataBuffer[id-1], 32068) / 10,     {name: "", unit: "V"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1_Voltage",          GetU16(globalDataBuffer[id-1], 32069) / 10,     {name: "", unit: "V"});                              
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2_Voltage",          GetU16(globalDataBuffer[id-1], 32070) / 10,     {name: "", unit: "V"});                                                  
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3_Voltage",          GetU16(globalDataBuffer[id-1], 32071) / 10,     {name: "", unit: "V"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1_Current",          GetI32(globalDataBuffer[id-1], 32072) / 1000,   {name: "", unit: "A"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2_Current",          GetI32(globalDataBuffer[id-1], 32074) / 1000,   {name: "", unit: "A"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3_Current",          GetI32(globalDataBuffer[id-1], 32076) / 1000,   {name: "", unit: "A"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".PeakActivePowerDay",       GetI32(globalDataBuffer[id-1], 32078) / 1000,   {name: "", unit: "kW"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".ActivePower",              GetI32(globalDataBuffer[id-1], 32080) / 1000,   {name: "", unit: "kW"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".ReactivePower",            GetI32(globalDataBuffer[id-1], 32082) / 1000,   {name: "", unit: "kVar"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".PowerFactor",              GetI16(globalDataBuffer[id-1], 32084) / 1000,   {name: "", unit: ""});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".GridFrequency",            GetU16(globalDataBuffer[id-1], 32085) / 100,    {name: "", unit: "Hz"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".Efficiency",               GetU16(globalDataBuffer[id-1], 32086) / 100,    {name: "", unit: "%"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".InternalTemperature",      GetI16(globalDataBuffer[id-1], 32087) / 10,     {name: "", unit: "°C"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".InsulationResistance",     GetU16(globalDataBuffer[id-1], 32088) / 1000,   {name: "", unit: "MOhm"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".DeviceStatus",             GetU16(globalDataBuffer[id-1], 32089),          {name: "", unit: ""});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".FaultCode",                GetU16(globalDataBuffer[id-1], 32090),          {name: "", unit: ""});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".StartupTime",              String(new Date(GetU32(globalDataBuffer[id-1], 32091)*1000)),          {name: "", unit: ""});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".ShutdownTime",             String(new Date(GetU32(globalDataBuffer[id-1], 32093)*1000)),          {name: "", unit: ""});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".AccomulatedEnergyYield",   GetU32(globalDataBuffer[id-1], 32106),          {name: "", unit: "kWh"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".DailyEnergyYield",         GetU32(globalDataBuffer[id-1], 32114),          {name: "", unit: "kWh"});
    }
    
    function ReadRegisterSpace(id, address, length) {
        client.setID(modbusID[id-1]);
        client.readHoldingRegisters(address, length, function(err, data) {
            if (err) {
                console.warn("Error received reading address " + address + " from id: " + modbusID[id-1] + " with error: " + modbusErrorMessages[err.modbusCode]); 
            }
            else
            {   
                console.debug("Read data from id/address " + modbusID[id-1] + "/" + address + "\nData is: " + data.data);
                for(var i = 0; i < length; i++)  {
                    globalDataBuffer[id-1][address+i] = data.data[i];
                } 
            }
        });
    }
    
    function ProcessData() {
        //console.log("Processing new data...");
        for(var i = 1; i <= modbusID.length; i++) {
            //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 (!client.isOpen){
                ConnectModbus();
            }
            if(triggerprocessing == 1) {
            triggerprocessing = 0;
            ProcessData();        
            }      
       
        //console.log("Triggering read of inverter " + currentinverter + " at address " + registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][0] + " with length " +  registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][1]);
        ReadRegisterSpace(currentinverter, registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][0], registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][1]); 
        registerSpacesToReadContinuouslyPtr++;               
        if(registerSpacesToReadContinuouslyPtr >= registerSpacesToReadContinuously.length) {
            registerSpacesToReadContinuouslyPtr = 0;
            currentinverter++
            if(currentinverter > modbusID.length){
                currentinverter = 1;  
                triggerprocessing = 1;                    
            }
        }     
    }, 3000);
    
    J Offline
    J Offline
    juggi1962
    schrieb am zuletzt editiert von
    #67

    @alex-warkentin sagte in Huawei Sun2000 & ioBroker via JS script funktioniert:

    @juggi1962 Poste mal die Logs, wenn der Fehler auftritt

    Hier ist das Script, was ich für mich angepasst habe. Achtung! Ich habe die Batterie und andere für mich uninteressante Sachen rausgeschmissen und die Namen von Variablen und Funktionen angepasst. Für die Neuverbindung nach Verbindungsabbruch brauchst du die Zeilen 18 - 27 , 107-122 und 235 -237

    // License: Beerware! Do what ever you like with this, but I'm not liable for anything that you do with it.
    // If you like this code, feel free to buy me a beer ...
    // Have fun with it! der Kachel
    // @ts-ignore
    var modbusRTU = require("modbus-serial");
    var client = new modbusRTU();
    
    var modbusErrorMessages = [
        "Unknown error",
        "Illegal function (device does not support this read/write function)",
        "Illegal data address (register not supported by device)",
        "Illegal data value (value cannot be written to this register)",
        "Slave device failure (device reports internal error)",
        "Acknowledge (requested data will be available later)",
        "Slave device busy (retry request again later)"
    ];
    
    // Enter your inverter modbus IP and port here:
    const modbusHost = "000.000.000.000";
    const modbusPort = 502;
    // Enter the Modbus-IDs of your Sun2000 inverters here:
    const modbusID = [1];
    // On which Modbus-ID can we reach the power meter? (via Sun2000!)
    const powerMeterID = 0;
    
    // Connect to modbus client
    ConnectModbus();
    
    // These register spaces need to be read:
    const registerSpacesToReadContinuously = [[37100, 114], [32000, 116]];
    var registerSpacesToReadContinuouslyPtr = 0;
    
    var globalDataBuffer = new Array(1);
    globalDataBuffer[0] = new Array(50000); // not optimized....
    
    // ---------------------------------------------------------------
    // Some helper functions:
    function ReadUnsignedInt16(array) {
        var value = array[0];    
        return value;
    }
    
    function ReadUnsignedInt32(array) {
        var value = array[0] * 256 * 256 + array[1];    
        return value;
    }
    
    function ReadSignedInt16(array) {
        var value = 0;
        if (array[0] > 32767)
            value = array[0] - 65535; 
        else
            value = array[0];
    
        return value;
    }
    function ReadSignedInt32(array) {
        var value = 0;
        for (var i = 0; i < 2; i++) {
            value = (value << 16) | array[i];
        }
        return value;
    }
    function GetU16(dataarray, index) {
        var value = ReadUnsignedInt16(dataarray.slice(index, index+1));
        return value;
    }
    
    function GetU32(dataarray, index) {
        var value = ReadUnsignedInt32(dataarray.slice(index, index+2));
        return value;
    }
    
    function GetI16(dataarray, index) {
        var value = ReadSignedInt16(dataarray.slice(index, index+1));
        return value;
    }
    
    function GetI32(dataarray, index) {
        var value = ReadSignedInt32(dataarray.slice(index, index+2));
        return value;
    }
    
    function GetString(dataarray, index, length) {
        var shortarray = dataarray.slice(index, index+length);
        var bytearray = [];
        for(var i = 0; i < length; i++) {
            bytearray.push(dataarray[index+i] >> 8);
            bytearray.push(dataarray[index+i] & 0xff);
        }       
        var value =  String.fromCharCode.apply(null, bytearray);    
        return value;
    }
    
    function GetZeroTerminatedString(dataarray, index, length) {
        var shortarray = dataarray.slice(index, index+length);
        var bytearray = [];
        for(var i = 0; i < length; i++) {
            bytearray.push(dataarray[index+i] >> 8);
            bytearray.push(dataarray[index+i] & 0xff);
        }       
        var value =  String.fromCharCode.apply(null, bytearray);    
        var value2 = new String(value).trim();
        return value2;
    }
    
    // Funktion zum Herstellen einer Modbus-Verbindung
    function ConnectModbus() {
        console.log("Init connection to: " + modbusHost +":" + modbusPort);
        // set requests parameters
        client.setTimeout (10000);
        // try to connect
        client.connectTCP (modbusHost, { port: modbusPort })
            .then(function()
            {
                console.log("Connected, wait for reading...");
            })
            .catch(function(e)
            {
                console.log(e);
            });
    }
    
    // Funktion zum Anlegen und Beschreiben eines Datenpunkts
    function ForceSetState(objectname, value, options) {
        if(!existsState("javascript.0." + objectname))      createState(objectname, value, options);
        else                                                setState(objectname, value);
    }  
    // ---------------------------------------------------------------
    // Functions to map registers into ioBreaker objects:
    function ProcessPowerMeterStatus() {       
        ForceSetState("Solarpower.Huawei.Meter.Status",                     GetU16(globalDataBuffer[powerMeterID], 37100),          {name: "", unit: ""});
        ForceSetState("Solarpower.Huawei.Meter.VoltageL1",                  GetI32(globalDataBuffer[powerMeterID], 37101) / 10,     {name: "", unit: "V"});
        ForceSetState("Solarpower.Huawei.Meter.VoltageL2",                  GetI32(globalDataBuffer[powerMeterID], 37103) / 10,     {name: "", unit: "V"});
        ForceSetState("Solarpower.Huawei.Meter.VoltageL3",                  GetI32(globalDataBuffer[powerMeterID], 37105) / 10,     {name: "", unit: "V"});
        ForceSetState("Solarpower.Huawei.Meter.CurrentL1",                  GetI32(globalDataBuffer[powerMeterID], 37107) / 100,    {name: "", unit: "A"});
        ForceSetState("Solarpower.Huawei.Meter.CurrentL2",                  GetI32(globalDataBuffer[powerMeterID], 37109) / 100,    {name: "", unit: "A"});
        ForceSetState("Solarpower.Huawei.Meter.CurrentL3",                  GetI32(globalDataBuffer[powerMeterID], 37111) / 100,    {name: "", unit: "A"});
        ForceSetState("Solarpower.Huawei.Meter.ActivePower",                GetI32(globalDataBuffer[powerMeterID], 37113) / 1,      {name: "", unit: "W"});
        ForceSetState("Solarpower.Huawei.Meter.ReactivePower",              GetI32(globalDataBuffer[powerMeterID], 37115) / 1,      {name: "", unit: "Var"});
        ForceSetState("Solarpower.Huawei.Meter.PowerFactor",                GetI16(globalDataBuffer[powerMeterID], 37117) / 1000,   {name: "", unit: ""});
        ForceSetState("Solarpower.Huawei.Meter.GridFrequency",              GetI16(globalDataBuffer[powerMeterID], 37118) / 100,    {name: "", unit: "Hz"});
        ForceSetState("Solarpower.Huawei.Meter.PositiveActiveEnergy",       GetI32(globalDataBuffer[powerMeterID], 37119) / 100,    {name: "", unit: "kWh"});
        ForceSetState("Solarpower.Huawei.Meter.ReverseActiveEnergy",        GetI32(globalDataBuffer[powerMeterID], 37121) / 100,    {name: "", unit: "kWh"});
        ForceSetState("Solarpower.Huawei.Meter.AccumulatedReactivePower",   GetI32(globalDataBuffer[powerMeterID], 37123) / 100,    {name: "", unit: "kVarh"});
        //ForceSetState("Solarpower.Huawei.Meter.MeterType",                  GetU16(globalDataBuffer[powerMeterID], 37125),          {name: "", unit: ""});
        ForceSetState("Solarpower.Huawei.Meter.VoltageL1-L2",               GetI32(globalDataBuffer[powerMeterID], 37126) / 10,     {name: "", unit: "V"});
        ForceSetState("Solarpower.Huawei.Meter.VoltageL2-L3",               GetI32(globalDataBuffer[powerMeterID], 37128) / 10,     {name: "", unit: "V"});
        ForceSetState("Solarpower.Huawei.Meter.VoltageL3-L1",               GetI32(globalDataBuffer[powerMeterID], 37130) / 10,     {name: "", unit: "V"});
        ForceSetState("Solarpower.Huawei.Meter.ActivePowerL1",              GetI32(globalDataBuffer[powerMeterID], 37132) / 1,      {name: "", unit: "W"});
        ForceSetState("Solarpower.Huawei.Meter.ActivePowerL2",              GetI32(globalDataBuffer[powerMeterID], 37134) / 1,      {name: "", unit: "W"});
        ForceSetState("Solarpower.Huawei.Meter.ActivePowerL3",              GetI32(globalDataBuffer[powerMeterID], 37136) / 1,      {name: "", unit: "W"});
        //ForceSetState("Solarpower.Huawei.Meter.MeterModel",                 GetU16(globalDataBuffer[powerMeterID], 37138),          {name: "", unit: ""});
    }
    
    function ProcessInverterStatus(id) {
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".State1",                   GetU16(globalDataBuffer[id-1], 32000),          {name: "", unit: ""});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".State2",                   GetU16(globalDataBuffer[id-1], 32002),          {name: "", unit: ""});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".State3",                   GetU32(globalDataBuffer[id-1], 32003),          {name: "", unit: ""});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".Alarm1",                   GetU16(globalDataBuffer[id-1], 32008),          {name: "", unit: ""});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".Alarm2",                   GetU16(globalDataBuffer[id-1], 32009),          {name: "", unit: ""});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".Alarm3",                   GetU16(globalDataBuffer[id-1], 32010),          {name: "", unit: ""});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.1_Voltage",         GetI16(globalDataBuffer[id-1], 32016) / 10,     {name: "", unit: "V"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.1_Current",         GetI16(globalDataBuffer[id-1], 32017) / 100,    {name: "", unit: "A"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.2_Voltage",         GetI16(globalDataBuffer[id-1], 32018) / 10,     {name: "", unit: "V"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.2_Current",         GetI16(globalDataBuffer[id-1], 32019) / 100,    {name: "", unit: "A"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.3_Voltage",         GetI16(globalDataBuffer[id-1], 32020) / 10,     {name: "", unit: "V"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.3_Current",         GetI16(globalDataBuffer[id-1], 32021) / 100,    {name: "", unit: "A"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.4_Voltage",         GetI16(globalDataBuffer[id-1], 32022) / 10,     {name: "", unit: "V"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.4_Current",         GetI16(globalDataBuffer[id-1], 32023) / 100,    {name: "", unit: "A"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".InputPower",               GetI32(globalDataBuffer[id-1], 32064) / 1000,   {name: "", unit: "kW"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1-L2_Voltage",       GetU16(globalDataBuffer[id-1], 32066) / 10,     {name: "", unit: "V"});      
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2-L3_Voltage",       GetU16(globalDataBuffer[id-1], 32067) / 10,     {name: "", unit: "V"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3-L1_Voltage",       GetU16(globalDataBuffer[id-1], 32068) / 10,     {name: "", unit: "V"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1_Voltage",          GetU16(globalDataBuffer[id-1], 32069) / 10,     {name: "", unit: "V"});                              
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2_Voltage",          GetU16(globalDataBuffer[id-1], 32070) / 10,     {name: "", unit: "V"});                                                  
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3_Voltage",          GetU16(globalDataBuffer[id-1], 32071) / 10,     {name: "", unit: "V"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1_Current",          GetI32(globalDataBuffer[id-1], 32072) / 1000,   {name: "", unit: "A"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2_Current",          GetI32(globalDataBuffer[id-1], 32074) / 1000,   {name: "", unit: "A"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3_Current",          GetI32(globalDataBuffer[id-1], 32076) / 1000,   {name: "", unit: "A"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".PeakActivePowerDay",       GetI32(globalDataBuffer[id-1], 32078) / 1000,   {name: "", unit: "kW"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".ActivePower",              GetI32(globalDataBuffer[id-1], 32080) / 1000,   {name: "", unit: "kW"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".ReactivePower",            GetI32(globalDataBuffer[id-1], 32082) / 1000,   {name: "", unit: "kVar"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".PowerFactor",              GetI16(globalDataBuffer[id-1], 32084) / 1000,   {name: "", unit: ""});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".GridFrequency",            GetU16(globalDataBuffer[id-1], 32085) / 100,    {name: "", unit: "Hz"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".Efficiency",               GetU16(globalDataBuffer[id-1], 32086) / 100,    {name: "", unit: "%"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".InternalTemperature",      GetI16(globalDataBuffer[id-1], 32087) / 10,     {name: "", unit: "°C"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".InsulationResistance",     GetU16(globalDataBuffer[id-1], 32088) / 1000,   {name: "", unit: "MOhm"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".DeviceStatus",             GetU16(globalDataBuffer[id-1], 32089),          {name: "", unit: ""});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".FaultCode",                GetU16(globalDataBuffer[id-1], 32090),          {name: "", unit: ""});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".StartupTime",              String(new Date(GetU32(globalDataBuffer[id-1], 32091)*1000)),          {name: "", unit: ""});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".ShutdownTime",             String(new Date(GetU32(globalDataBuffer[id-1], 32093)*1000)),          {name: "", unit: ""});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".AccomulatedEnergyYield",   GetU32(globalDataBuffer[id-1], 32106),          {name: "", unit: "kWh"});
        ForceSetState("Solarpower.Huawei.Inverter." + id + ".DailyEnergyYield",         GetU32(globalDataBuffer[id-1], 32114),          {name: "", unit: "kWh"});
    }
    
    function ReadRegisterSpace(id, address, length) {
        client.setID(modbusID[id-1]);
        client.readHoldingRegisters(address, length, function(err, data) {
            if (err) {
                console.warn("Error received reading address " + address + " from id: " + modbusID[id-1] + " with error: " + modbusErrorMessages[err.modbusCode]); 
            }
            else
            {   
                console.debug("Read data from id/address " + modbusID[id-1] + "/" + address + "\nData is: " + data.data);
                for(var i = 0; i < length; i++)  {
                    globalDataBuffer[id-1][address+i] = data.data[i];
                } 
            }
        });
    }
    
    function ProcessData() {
        //console.log("Processing new data...");
        for(var i = 1; i <= modbusID.length; i++) {
            //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 (!client.isOpen){
                ConnectModbus();
            }
            if(triggerprocessing == 1) {
            triggerprocessing = 0;
            ProcessData();        
            }      
       
        //console.log("Triggering read of inverter " + currentinverter + " at address " + registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][0] + " with length " +  registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][1]);
        ReadRegisterSpace(currentinverter, registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][0], registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][1]); 
        registerSpacesToReadContinuouslyPtr++;               
        if(registerSpacesToReadContinuouslyPtr >= registerSpacesToReadContinuously.length) {
            registerSpacesToReadContinuouslyPtr = 0;
            currentinverter++
            if(currentinverter > modbusID.length){
                currentinverter = 1;  
                triggerprocessing = 1;                    
            }
        }     
    }, 3000);
    

    Super Danke.
    Hab eh keine Batterie. Werde es gleich testen.
    Gruß Jürgen

    J 1 Antwort Letzte Antwort
    0
    • J juggi1962

      @alex-warkentin sagte in Huawei Sun2000 & ioBroker via JS script funktioniert:

      @juggi1962 Poste mal die Logs, wenn der Fehler auftritt

      Hier ist das Script, was ich für mich angepasst habe. Achtung! Ich habe die Batterie und andere für mich uninteressante Sachen rausgeschmissen und die Namen von Variablen und Funktionen angepasst. Für die Neuverbindung nach Verbindungsabbruch brauchst du die Zeilen 18 - 27 , 107-122 und 235 -237

      // License: Beerware! Do what ever you like with this, but I'm not liable for anything that you do with it.
      // If you like this code, feel free to buy me a beer ...
      // Have fun with it! der Kachel
      // @ts-ignore
      var modbusRTU = require("modbus-serial");
      var client = new modbusRTU();
      
      var modbusErrorMessages = [
          "Unknown error",
          "Illegal function (device does not support this read/write function)",
          "Illegal data address (register not supported by device)",
          "Illegal data value (value cannot be written to this register)",
          "Slave device failure (device reports internal error)",
          "Acknowledge (requested data will be available later)",
          "Slave device busy (retry request again later)"
      ];
      
      // Enter your inverter modbus IP and port here:
      const modbusHost = "000.000.000.000";
      const modbusPort = 502;
      // Enter the Modbus-IDs of your Sun2000 inverters here:
      const modbusID = [1];
      // On which Modbus-ID can we reach the power meter? (via Sun2000!)
      const powerMeterID = 0;
      
      // Connect to modbus client
      ConnectModbus();
      
      // These register spaces need to be read:
      const registerSpacesToReadContinuously = [[37100, 114], [32000, 116]];
      var registerSpacesToReadContinuouslyPtr = 0;
      
      var globalDataBuffer = new Array(1);
      globalDataBuffer[0] = new Array(50000); // not optimized....
      
      // ---------------------------------------------------------------
      // Some helper functions:
      function ReadUnsignedInt16(array) {
          var value = array[0];    
          return value;
      }
      
      function ReadUnsignedInt32(array) {
          var value = array[0] * 256 * 256 + array[1];    
          return value;
      }
      
      function ReadSignedInt16(array) {
          var value = 0;
          if (array[0] > 32767)
              value = array[0] - 65535; 
          else
              value = array[0];
      
          return value;
      }
      function ReadSignedInt32(array) {
          var value = 0;
          for (var i = 0; i < 2; i++) {
              value = (value << 16) | array[i];
          }
          return value;
      }
      function GetU16(dataarray, index) {
          var value = ReadUnsignedInt16(dataarray.slice(index, index+1));
          return value;
      }
      
      function GetU32(dataarray, index) {
          var value = ReadUnsignedInt32(dataarray.slice(index, index+2));
          return value;
      }
      
      function GetI16(dataarray, index) {
          var value = ReadSignedInt16(dataarray.slice(index, index+1));
          return value;
      }
      
      function GetI32(dataarray, index) {
          var value = ReadSignedInt32(dataarray.slice(index, index+2));
          return value;
      }
      
      function GetString(dataarray, index, length) {
          var shortarray = dataarray.slice(index, index+length);
          var bytearray = [];
          for(var i = 0; i < length; i++) {
              bytearray.push(dataarray[index+i] >> 8);
              bytearray.push(dataarray[index+i] & 0xff);
          }       
          var value =  String.fromCharCode.apply(null, bytearray);    
          return value;
      }
      
      function GetZeroTerminatedString(dataarray, index, length) {
          var shortarray = dataarray.slice(index, index+length);
          var bytearray = [];
          for(var i = 0; i < length; i++) {
              bytearray.push(dataarray[index+i] >> 8);
              bytearray.push(dataarray[index+i] & 0xff);
          }       
          var value =  String.fromCharCode.apply(null, bytearray);    
          var value2 = new String(value).trim();
          return value2;
      }
      
      // Funktion zum Herstellen einer Modbus-Verbindung
      function ConnectModbus() {
          console.log("Init connection to: " + modbusHost +":" + modbusPort);
          // set requests parameters
          client.setTimeout (10000);
          // try to connect
          client.connectTCP (modbusHost, { port: modbusPort })
              .then(function()
              {
                  console.log("Connected, wait for reading...");
              })
              .catch(function(e)
              {
                  console.log(e);
              });
      }
      
      // Funktion zum Anlegen und Beschreiben eines Datenpunkts
      function ForceSetState(objectname, value, options) {
          if(!existsState("javascript.0." + objectname))      createState(objectname, value, options);
          else                                                setState(objectname, value);
      }  
      // ---------------------------------------------------------------
      // Functions to map registers into ioBreaker objects:
      function ProcessPowerMeterStatus() {       
          ForceSetState("Solarpower.Huawei.Meter.Status",                     GetU16(globalDataBuffer[powerMeterID], 37100),          {name: "", unit: ""});
          ForceSetState("Solarpower.Huawei.Meter.VoltageL1",                  GetI32(globalDataBuffer[powerMeterID], 37101) / 10,     {name: "", unit: "V"});
          ForceSetState("Solarpower.Huawei.Meter.VoltageL2",                  GetI32(globalDataBuffer[powerMeterID], 37103) / 10,     {name: "", unit: "V"});
          ForceSetState("Solarpower.Huawei.Meter.VoltageL3",                  GetI32(globalDataBuffer[powerMeterID], 37105) / 10,     {name: "", unit: "V"});
          ForceSetState("Solarpower.Huawei.Meter.CurrentL1",                  GetI32(globalDataBuffer[powerMeterID], 37107) / 100,    {name: "", unit: "A"});
          ForceSetState("Solarpower.Huawei.Meter.CurrentL2",                  GetI32(globalDataBuffer[powerMeterID], 37109) / 100,    {name: "", unit: "A"});
          ForceSetState("Solarpower.Huawei.Meter.CurrentL3",                  GetI32(globalDataBuffer[powerMeterID], 37111) / 100,    {name: "", unit: "A"});
          ForceSetState("Solarpower.Huawei.Meter.ActivePower",                GetI32(globalDataBuffer[powerMeterID], 37113) / 1,      {name: "", unit: "W"});
          ForceSetState("Solarpower.Huawei.Meter.ReactivePower",              GetI32(globalDataBuffer[powerMeterID], 37115) / 1,      {name: "", unit: "Var"});
          ForceSetState("Solarpower.Huawei.Meter.PowerFactor",                GetI16(globalDataBuffer[powerMeterID], 37117) / 1000,   {name: "", unit: ""});
          ForceSetState("Solarpower.Huawei.Meter.GridFrequency",              GetI16(globalDataBuffer[powerMeterID], 37118) / 100,    {name: "", unit: "Hz"});
          ForceSetState("Solarpower.Huawei.Meter.PositiveActiveEnergy",       GetI32(globalDataBuffer[powerMeterID], 37119) / 100,    {name: "", unit: "kWh"});
          ForceSetState("Solarpower.Huawei.Meter.ReverseActiveEnergy",        GetI32(globalDataBuffer[powerMeterID], 37121) / 100,    {name: "", unit: "kWh"});
          ForceSetState("Solarpower.Huawei.Meter.AccumulatedReactivePower",   GetI32(globalDataBuffer[powerMeterID], 37123) / 100,    {name: "", unit: "kVarh"});
          //ForceSetState("Solarpower.Huawei.Meter.MeterType",                  GetU16(globalDataBuffer[powerMeterID], 37125),          {name: "", unit: ""});
          ForceSetState("Solarpower.Huawei.Meter.VoltageL1-L2",               GetI32(globalDataBuffer[powerMeterID], 37126) / 10,     {name: "", unit: "V"});
          ForceSetState("Solarpower.Huawei.Meter.VoltageL2-L3",               GetI32(globalDataBuffer[powerMeterID], 37128) / 10,     {name: "", unit: "V"});
          ForceSetState("Solarpower.Huawei.Meter.VoltageL3-L1",               GetI32(globalDataBuffer[powerMeterID], 37130) / 10,     {name: "", unit: "V"});
          ForceSetState("Solarpower.Huawei.Meter.ActivePowerL1",              GetI32(globalDataBuffer[powerMeterID], 37132) / 1,      {name: "", unit: "W"});
          ForceSetState("Solarpower.Huawei.Meter.ActivePowerL2",              GetI32(globalDataBuffer[powerMeterID], 37134) / 1,      {name: "", unit: "W"});
          ForceSetState("Solarpower.Huawei.Meter.ActivePowerL3",              GetI32(globalDataBuffer[powerMeterID], 37136) / 1,      {name: "", unit: "W"});
          //ForceSetState("Solarpower.Huawei.Meter.MeterModel",                 GetU16(globalDataBuffer[powerMeterID], 37138),          {name: "", unit: ""});
      }
      
      function ProcessInverterStatus(id) {
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".State1",                   GetU16(globalDataBuffer[id-1], 32000),          {name: "", unit: ""});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".State2",                   GetU16(globalDataBuffer[id-1], 32002),          {name: "", unit: ""});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".State3",                   GetU32(globalDataBuffer[id-1], 32003),          {name: "", unit: ""});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".Alarm1",                   GetU16(globalDataBuffer[id-1], 32008),          {name: "", unit: ""});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".Alarm2",                   GetU16(globalDataBuffer[id-1], 32009),          {name: "", unit: ""});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".Alarm3",                   GetU16(globalDataBuffer[id-1], 32010),          {name: "", unit: ""});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.1_Voltage",         GetI16(globalDataBuffer[id-1], 32016) / 10,     {name: "", unit: "V"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.1_Current",         GetI16(globalDataBuffer[id-1], 32017) / 100,    {name: "", unit: "A"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.2_Voltage",         GetI16(globalDataBuffer[id-1], 32018) / 10,     {name: "", unit: "V"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.2_Current",         GetI16(globalDataBuffer[id-1], 32019) / 100,    {name: "", unit: "A"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.3_Voltage",         GetI16(globalDataBuffer[id-1], 32020) / 10,     {name: "", unit: "V"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.3_Current",         GetI16(globalDataBuffer[id-1], 32021) / 100,    {name: "", unit: "A"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.4_Voltage",         GetI16(globalDataBuffer[id-1], 32022) / 10,     {name: "", unit: "V"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.4_Current",         GetI16(globalDataBuffer[id-1], 32023) / 100,    {name: "", unit: "A"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".InputPower",               GetI32(globalDataBuffer[id-1], 32064) / 1000,   {name: "", unit: "kW"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1-L2_Voltage",       GetU16(globalDataBuffer[id-1], 32066) / 10,     {name: "", unit: "V"});      
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2-L3_Voltage",       GetU16(globalDataBuffer[id-1], 32067) / 10,     {name: "", unit: "V"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3-L1_Voltage",       GetU16(globalDataBuffer[id-1], 32068) / 10,     {name: "", unit: "V"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1_Voltage",          GetU16(globalDataBuffer[id-1], 32069) / 10,     {name: "", unit: "V"});                              
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2_Voltage",          GetU16(globalDataBuffer[id-1], 32070) / 10,     {name: "", unit: "V"});                                                  
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3_Voltage",          GetU16(globalDataBuffer[id-1], 32071) / 10,     {name: "", unit: "V"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1_Current",          GetI32(globalDataBuffer[id-1], 32072) / 1000,   {name: "", unit: "A"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2_Current",          GetI32(globalDataBuffer[id-1], 32074) / 1000,   {name: "", unit: "A"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3_Current",          GetI32(globalDataBuffer[id-1], 32076) / 1000,   {name: "", unit: "A"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".PeakActivePowerDay",       GetI32(globalDataBuffer[id-1], 32078) / 1000,   {name: "", unit: "kW"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".ActivePower",              GetI32(globalDataBuffer[id-1], 32080) / 1000,   {name: "", unit: "kW"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".ReactivePower",            GetI32(globalDataBuffer[id-1], 32082) / 1000,   {name: "", unit: "kVar"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".PowerFactor",              GetI16(globalDataBuffer[id-1], 32084) / 1000,   {name: "", unit: ""});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".GridFrequency",            GetU16(globalDataBuffer[id-1], 32085) / 100,    {name: "", unit: "Hz"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".Efficiency",               GetU16(globalDataBuffer[id-1], 32086) / 100,    {name: "", unit: "%"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".InternalTemperature",      GetI16(globalDataBuffer[id-1], 32087) / 10,     {name: "", unit: "°C"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".InsulationResistance",     GetU16(globalDataBuffer[id-1], 32088) / 1000,   {name: "", unit: "MOhm"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".DeviceStatus",             GetU16(globalDataBuffer[id-1], 32089),          {name: "", unit: ""});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".FaultCode",                GetU16(globalDataBuffer[id-1], 32090),          {name: "", unit: ""});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".StartupTime",              String(new Date(GetU32(globalDataBuffer[id-1], 32091)*1000)),          {name: "", unit: ""});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".ShutdownTime",             String(new Date(GetU32(globalDataBuffer[id-1], 32093)*1000)),          {name: "", unit: ""});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".AccomulatedEnergyYield",   GetU32(globalDataBuffer[id-1], 32106),          {name: "", unit: "kWh"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".DailyEnergyYield",         GetU32(globalDataBuffer[id-1], 32114),          {name: "", unit: "kWh"});
      }
      
      function ReadRegisterSpace(id, address, length) {
          client.setID(modbusID[id-1]);
          client.readHoldingRegisters(address, length, function(err, data) {
              if (err) {
                  console.warn("Error received reading address " + address + " from id: " + modbusID[id-1] + " with error: " + modbusErrorMessages[err.modbusCode]); 
              }
              else
              {   
                  console.debug("Read data from id/address " + modbusID[id-1] + "/" + address + "\nData is: " + data.data);
                  for(var i = 0; i < length; i++)  {
                      globalDataBuffer[id-1][address+i] = data.data[i];
                  } 
              }
          });
      }
      
      function ProcessData() {
          //console.log("Processing new data...");
          for(var i = 1; i <= modbusID.length; i++) {
              //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 (!client.isOpen){
                  ConnectModbus();
              }
              if(triggerprocessing == 1) {
              triggerprocessing = 0;
              ProcessData();        
              }      
         
          //console.log("Triggering read of inverter " + currentinverter + " at address " + registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][0] + " with length " +  registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][1]);
          ReadRegisterSpace(currentinverter, registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][0], registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][1]); 
          registerSpacesToReadContinuouslyPtr++;               
          if(registerSpacesToReadContinuouslyPtr >= registerSpacesToReadContinuously.length) {
              registerSpacesToReadContinuouslyPtr = 0;
              currentinverter++
              if(currentinverter > modbusID.length){
                  currentinverter = 1;  
                  triggerprocessing = 1;                    
              }
          }     
      }, 3000);
      

      Super Danke.
      Hab eh keine Batterie. Werde es gleich testen.
      Gruß Jürgen

      J Offline
      J Offline
      juggi1962
      schrieb am zuletzt editiert von
      #68

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

      @alex-warkentin sagte in Huawei Sun2000 & ioBroker via JS script funktioniert:

      @juggi1962 Poste mal die Logs, wenn der Fehler auftritt

      Hier ist das Script, was ich für mich angepasst habe. Achtung! Ich habe die Batterie und andere für mich uninteressante Sachen rausgeschmissen und die Namen von Variablen und Funktionen angepasst. Für die Neuverbindung nach Verbindungsabbruch brauchst du die Zeilen 18 - 27 , 107-122 und 235 -237

      // License: Beerware! Do what ever you like with this, but I'm not liable for anything that you do with it.
      // If you like this code, feel free to buy me a beer ...
      // Have fun with it! der Kachel
      // @ts-ignore
      var modbusRTU = require("modbus-serial");
      var client = new modbusRTU();
      
      var modbusErrorMessages = [
          "Unknown error",
          "Illegal function (device does not support this read/write function)",
          "Illegal data address (register not supported by device)",
          "Illegal data value (value cannot be written to this register)",
          "Slave device failure (device reports internal error)",
          "Acknowledge (requested data will be available later)",
          "Slave device busy (retry request again later)"
      ];
      
      // Enter your inverter modbus IP and port here:
      const modbusHost = "000.000.000.000";
      const modbusPort = 502;
      // Enter the Modbus-IDs of your Sun2000 inverters here:
      const modbusID = [1];
      // On which Modbus-ID can we reach the power meter? (via Sun2000!)
      const powerMeterID = 0;
      
      // Connect to modbus client
      ConnectModbus();
      
      // These register spaces need to be read:
      const registerSpacesToReadContinuously = [[37100, 114], [32000, 116]];
      var registerSpacesToReadContinuouslyPtr = 0;
      
      var globalDataBuffer = new Array(1);
      globalDataBuffer[0] = new Array(50000); // not optimized....
      
      // ---------------------------------------------------------------
      // Some helper functions:
      function ReadUnsignedInt16(array) {
          var value = array[0];    
          return value;
      }
      
      function ReadUnsignedInt32(array) {
          var value = array[0] * 256 * 256 + array[1];    
          return value;
      }
      
      function ReadSignedInt16(array) {
          var value = 0;
          if (array[0] > 32767)
              value = array[0] - 65535; 
          else
              value = array[0];
      
          return value;
      }
      function ReadSignedInt32(array) {
          var value = 0;
          for (var i = 0; i < 2; i++) {
              value = (value << 16) | array[i];
          }
          return value;
      }
      function GetU16(dataarray, index) {
          var value = ReadUnsignedInt16(dataarray.slice(index, index+1));
          return value;
      }
      
      function GetU32(dataarray, index) {
          var value = ReadUnsignedInt32(dataarray.slice(index, index+2));
          return value;
      }
      
      function GetI16(dataarray, index) {
          var value = ReadSignedInt16(dataarray.slice(index, index+1));
          return value;
      }
      
      function GetI32(dataarray, index) {
          var value = ReadSignedInt32(dataarray.slice(index, index+2));
          return value;
      }
      
      function GetString(dataarray, index, length) {
          var shortarray = dataarray.slice(index, index+length);
          var bytearray = [];
          for(var i = 0; i < length; i++) {
              bytearray.push(dataarray[index+i] >> 8);
              bytearray.push(dataarray[index+i] & 0xff);
          }       
          var value =  String.fromCharCode.apply(null, bytearray);    
          return value;
      }
      
      function GetZeroTerminatedString(dataarray, index, length) {
          var shortarray = dataarray.slice(index, index+length);
          var bytearray = [];
          for(var i = 0; i < length; i++) {
              bytearray.push(dataarray[index+i] >> 8);
              bytearray.push(dataarray[index+i] & 0xff);
          }       
          var value =  String.fromCharCode.apply(null, bytearray);    
          var value2 = new String(value).trim();
          return value2;
      }
      
      // Funktion zum Herstellen einer Modbus-Verbindung
      function ConnectModbus() {
          console.log("Init connection to: " + modbusHost +":" + modbusPort);
          // set requests parameters
          client.setTimeout (10000);
          // try to connect
          client.connectTCP (modbusHost, { port: modbusPort })
              .then(function()
              {
                  console.log("Connected, wait for reading...");
              })
              .catch(function(e)
              {
                  console.log(e);
              });
      }
      
      // Funktion zum Anlegen und Beschreiben eines Datenpunkts
      function ForceSetState(objectname, value, options) {
          if(!existsState("javascript.0." + objectname))      createState(objectname, value, options);
          else                                                setState(objectname, value);
      }  
      // ---------------------------------------------------------------
      // Functions to map registers into ioBreaker objects:
      function ProcessPowerMeterStatus() {       
          ForceSetState("Solarpower.Huawei.Meter.Status",                     GetU16(globalDataBuffer[powerMeterID], 37100),          {name: "", unit: ""});
          ForceSetState("Solarpower.Huawei.Meter.VoltageL1",                  GetI32(globalDataBuffer[powerMeterID], 37101) / 10,     {name: "", unit: "V"});
          ForceSetState("Solarpower.Huawei.Meter.VoltageL2",                  GetI32(globalDataBuffer[powerMeterID], 37103) / 10,     {name: "", unit: "V"});
          ForceSetState("Solarpower.Huawei.Meter.VoltageL3",                  GetI32(globalDataBuffer[powerMeterID], 37105) / 10,     {name: "", unit: "V"});
          ForceSetState("Solarpower.Huawei.Meter.CurrentL1",                  GetI32(globalDataBuffer[powerMeterID], 37107) / 100,    {name: "", unit: "A"});
          ForceSetState("Solarpower.Huawei.Meter.CurrentL2",                  GetI32(globalDataBuffer[powerMeterID], 37109) / 100,    {name: "", unit: "A"});
          ForceSetState("Solarpower.Huawei.Meter.CurrentL3",                  GetI32(globalDataBuffer[powerMeterID], 37111) / 100,    {name: "", unit: "A"});
          ForceSetState("Solarpower.Huawei.Meter.ActivePower",                GetI32(globalDataBuffer[powerMeterID], 37113) / 1,      {name: "", unit: "W"});
          ForceSetState("Solarpower.Huawei.Meter.ReactivePower",              GetI32(globalDataBuffer[powerMeterID], 37115) / 1,      {name: "", unit: "Var"});
          ForceSetState("Solarpower.Huawei.Meter.PowerFactor",                GetI16(globalDataBuffer[powerMeterID], 37117) / 1000,   {name: "", unit: ""});
          ForceSetState("Solarpower.Huawei.Meter.GridFrequency",              GetI16(globalDataBuffer[powerMeterID], 37118) / 100,    {name: "", unit: "Hz"});
          ForceSetState("Solarpower.Huawei.Meter.PositiveActiveEnergy",       GetI32(globalDataBuffer[powerMeterID], 37119) / 100,    {name: "", unit: "kWh"});
          ForceSetState("Solarpower.Huawei.Meter.ReverseActiveEnergy",        GetI32(globalDataBuffer[powerMeterID], 37121) / 100,    {name: "", unit: "kWh"});
          ForceSetState("Solarpower.Huawei.Meter.AccumulatedReactivePower",   GetI32(globalDataBuffer[powerMeterID], 37123) / 100,    {name: "", unit: "kVarh"});
          //ForceSetState("Solarpower.Huawei.Meter.MeterType",                  GetU16(globalDataBuffer[powerMeterID], 37125),          {name: "", unit: ""});
          ForceSetState("Solarpower.Huawei.Meter.VoltageL1-L2",               GetI32(globalDataBuffer[powerMeterID], 37126) / 10,     {name: "", unit: "V"});
          ForceSetState("Solarpower.Huawei.Meter.VoltageL2-L3",               GetI32(globalDataBuffer[powerMeterID], 37128) / 10,     {name: "", unit: "V"});
          ForceSetState("Solarpower.Huawei.Meter.VoltageL3-L1",               GetI32(globalDataBuffer[powerMeterID], 37130) / 10,     {name: "", unit: "V"});
          ForceSetState("Solarpower.Huawei.Meter.ActivePowerL1",              GetI32(globalDataBuffer[powerMeterID], 37132) / 1,      {name: "", unit: "W"});
          ForceSetState("Solarpower.Huawei.Meter.ActivePowerL2",              GetI32(globalDataBuffer[powerMeterID], 37134) / 1,      {name: "", unit: "W"});
          ForceSetState("Solarpower.Huawei.Meter.ActivePowerL3",              GetI32(globalDataBuffer[powerMeterID], 37136) / 1,      {name: "", unit: "W"});
          //ForceSetState("Solarpower.Huawei.Meter.MeterModel",                 GetU16(globalDataBuffer[powerMeterID], 37138),          {name: "", unit: ""});
      }
      
      function ProcessInverterStatus(id) {
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".State1",                   GetU16(globalDataBuffer[id-1], 32000),          {name: "", unit: ""});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".State2",                   GetU16(globalDataBuffer[id-1], 32002),          {name: "", unit: ""});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".State3",                   GetU32(globalDataBuffer[id-1], 32003),          {name: "", unit: ""});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".Alarm1",                   GetU16(globalDataBuffer[id-1], 32008),          {name: "", unit: ""});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".Alarm2",                   GetU16(globalDataBuffer[id-1], 32009),          {name: "", unit: ""});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".Alarm3",                   GetU16(globalDataBuffer[id-1], 32010),          {name: "", unit: ""});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.1_Voltage",         GetI16(globalDataBuffer[id-1], 32016) / 10,     {name: "", unit: "V"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.1_Current",         GetI16(globalDataBuffer[id-1], 32017) / 100,    {name: "", unit: "A"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.2_Voltage",         GetI16(globalDataBuffer[id-1], 32018) / 10,     {name: "", unit: "V"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.2_Current",         GetI16(globalDataBuffer[id-1], 32019) / 100,    {name: "", unit: "A"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.3_Voltage",         GetI16(globalDataBuffer[id-1], 32020) / 10,     {name: "", unit: "V"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.3_Current",         GetI16(globalDataBuffer[id-1], 32021) / 100,    {name: "", unit: "A"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.4_Voltage",         GetI16(globalDataBuffer[id-1], 32022) / 10,     {name: "", unit: "V"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.4_Current",         GetI16(globalDataBuffer[id-1], 32023) / 100,    {name: "", unit: "A"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".InputPower",               GetI32(globalDataBuffer[id-1], 32064) / 1000,   {name: "", unit: "kW"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1-L2_Voltage",       GetU16(globalDataBuffer[id-1], 32066) / 10,     {name: "", unit: "V"});      
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2-L3_Voltage",       GetU16(globalDataBuffer[id-1], 32067) / 10,     {name: "", unit: "V"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3-L1_Voltage",       GetU16(globalDataBuffer[id-1], 32068) / 10,     {name: "", unit: "V"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1_Voltage",          GetU16(globalDataBuffer[id-1], 32069) / 10,     {name: "", unit: "V"});                              
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2_Voltage",          GetU16(globalDataBuffer[id-1], 32070) / 10,     {name: "", unit: "V"});                                                  
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3_Voltage",          GetU16(globalDataBuffer[id-1], 32071) / 10,     {name: "", unit: "V"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1_Current",          GetI32(globalDataBuffer[id-1], 32072) / 1000,   {name: "", unit: "A"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2_Current",          GetI32(globalDataBuffer[id-1], 32074) / 1000,   {name: "", unit: "A"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3_Current",          GetI32(globalDataBuffer[id-1], 32076) / 1000,   {name: "", unit: "A"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".PeakActivePowerDay",       GetI32(globalDataBuffer[id-1], 32078) / 1000,   {name: "", unit: "kW"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".ActivePower",              GetI32(globalDataBuffer[id-1], 32080) / 1000,   {name: "", unit: "kW"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".ReactivePower",            GetI32(globalDataBuffer[id-1], 32082) / 1000,   {name: "", unit: "kVar"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".PowerFactor",              GetI16(globalDataBuffer[id-1], 32084) / 1000,   {name: "", unit: ""});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".GridFrequency",            GetU16(globalDataBuffer[id-1], 32085) / 100,    {name: "", unit: "Hz"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".Efficiency",               GetU16(globalDataBuffer[id-1], 32086) / 100,    {name: "", unit: "%"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".InternalTemperature",      GetI16(globalDataBuffer[id-1], 32087) / 10,     {name: "", unit: "°C"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".InsulationResistance",     GetU16(globalDataBuffer[id-1], 32088) / 1000,   {name: "", unit: "MOhm"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".DeviceStatus",             GetU16(globalDataBuffer[id-1], 32089),          {name: "", unit: ""});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".FaultCode",                GetU16(globalDataBuffer[id-1], 32090),          {name: "", unit: ""});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".StartupTime",              String(new Date(GetU32(globalDataBuffer[id-1], 32091)*1000)),          {name: "", unit: ""});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".ShutdownTime",             String(new Date(GetU32(globalDataBuffer[id-1], 32093)*1000)),          {name: "", unit: ""});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".AccomulatedEnergyYield",   GetU32(globalDataBuffer[id-1], 32106),          {name: "", unit: "kWh"});
          ForceSetState("Solarpower.Huawei.Inverter." + id + ".DailyEnergyYield",         GetU32(globalDataBuffer[id-1], 32114),          {name: "", unit: "kWh"});
      }
      
      function ReadRegisterSpace(id, address, length) {
          client.setID(modbusID[id-1]);
          client.readHoldingRegisters(address, length, function(err, data) {
              if (err) {
                  console.warn("Error received reading address " + address + " from id: " + modbusID[id-1] + " with error: " + modbusErrorMessages[err.modbusCode]); 
              }
              else
              {   
                  console.debug("Read data from id/address " + modbusID[id-1] + "/" + address + "\nData is: " + data.data);
                  for(var i = 0; i < length; i++)  {
                      globalDataBuffer[id-1][address+i] = data.data[i];
                  } 
              }
          });
      }
      
      function ProcessData() {
          //console.log("Processing new data...");
          for(var i = 1; i <= modbusID.length; i++) {
              //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 (!client.isOpen){
                  ConnectModbus();
              }
              if(triggerprocessing == 1) {
              triggerprocessing = 0;
              ProcessData();        
              }      
         
          //console.log("Triggering read of inverter " + currentinverter + " at address " + registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][0] + " with length " +  registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][1]);
          ReadRegisterSpace(currentinverter, registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][0], registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][1]); 
          registerSpacesToReadContinuouslyPtr++;               
          if(registerSpacesToReadContinuouslyPtr >= registerSpacesToReadContinuously.length) {
              registerSpacesToReadContinuouslyPtr = 0;
              currentinverter++
              if(currentinverter > modbusID.length){
                  currentinverter = 1;  
                  triggerprocessing = 1;                    
              }
          }     
      }, 3000);
      

      Super Danke.
      Hab eh keine Batterie. Werde es gleich testen.
      Gruß Jürgen

      Guten Morgen soweit läuft es mal, aber kann es sein, dass bei
      Solarpower Huawei Inverter 1 AccomulatedEnergyYield und
      Solarpower.Huawei.Inverter.1.DailyEnergyYield
      das Komma fehlt, denn der Tägliche Ertrag wäre schön aber nicht war :-)
      kann man das irgend wie ändern?

      Alex WarkentinA 1 Antwort Letzte Antwort
      0
      • Alex WarkentinA Alex Warkentin

        @juggi1962 Poste mal die Logs, wenn der Fehler auftritt

        Hier ist das Script, was ich für mich angepasst habe. Achtung! Ich habe die Batterie und andere für mich uninteressante Sachen rausgeschmissen und die Namen von Variablen und Funktionen angepasst. Für die Neuverbindung nach Verbindungsabbruch brauchst du die Zeilen 18 - 27 , 107-122 und 235 -237

        // License: Beerware! Do what ever you like with this, but I'm not liable for anything that you do with it.
        // If you like this code, feel free to buy me a beer ...
        // Have fun with it! der Kachel
        // @ts-ignore
        var modbusRTU = require("modbus-serial");
        var client = new modbusRTU();
        
        var modbusErrorMessages = [
            "Unknown error",
            "Illegal function (device does not support this read/write function)",
            "Illegal data address (register not supported by device)",
            "Illegal data value (value cannot be written to this register)",
            "Slave device failure (device reports internal error)",
            "Acknowledge (requested data will be available later)",
            "Slave device busy (retry request again later)"
        ];
        
        // Enter your inverter modbus IP and port here:
        const modbusHost = "000.000.000.000";
        const modbusPort = 502;
        // Enter the Modbus-IDs of your Sun2000 inverters here:
        const modbusID = [1];
        // On which Modbus-ID can we reach the power meter? (via Sun2000!)
        const powerMeterID = 0;
        
        // Connect to modbus client
        ConnectModbus();
        
        // These register spaces need to be read:
        const registerSpacesToReadContinuously = [[37100, 114], [32000, 116]];
        var registerSpacesToReadContinuouslyPtr = 0;
        
        var globalDataBuffer = new Array(1);
        globalDataBuffer[0] = new Array(50000); // not optimized....
        
        // ---------------------------------------------------------------
        // Some helper functions:
        function ReadUnsignedInt16(array) {
            var value = array[0];    
            return value;
        }
        
        function ReadUnsignedInt32(array) {
            var value = array[0] * 256 * 256 + array[1];    
            return value;
        }
        
        function ReadSignedInt16(array) {
            var value = 0;
            if (array[0] > 32767)
                value = array[0] - 65535; 
            else
                value = array[0];
        
            return value;
        }
        function ReadSignedInt32(array) {
            var value = 0;
            for (var i = 0; i < 2; i++) {
                value = (value << 16) | array[i];
            }
            return value;
        }
        function GetU16(dataarray, index) {
            var value = ReadUnsignedInt16(dataarray.slice(index, index+1));
            return value;
        }
        
        function GetU32(dataarray, index) {
            var value = ReadUnsignedInt32(dataarray.slice(index, index+2));
            return value;
        }
        
        function GetI16(dataarray, index) {
            var value = ReadSignedInt16(dataarray.slice(index, index+1));
            return value;
        }
        
        function GetI32(dataarray, index) {
            var value = ReadSignedInt32(dataarray.slice(index, index+2));
            return value;
        }
        
        function GetString(dataarray, index, length) {
            var shortarray = dataarray.slice(index, index+length);
            var bytearray = [];
            for(var i = 0; i < length; i++) {
                bytearray.push(dataarray[index+i] >> 8);
                bytearray.push(dataarray[index+i] & 0xff);
            }       
            var value =  String.fromCharCode.apply(null, bytearray);    
            return value;
        }
        
        function GetZeroTerminatedString(dataarray, index, length) {
            var shortarray = dataarray.slice(index, index+length);
            var bytearray = [];
            for(var i = 0; i < length; i++) {
                bytearray.push(dataarray[index+i] >> 8);
                bytearray.push(dataarray[index+i] & 0xff);
            }       
            var value =  String.fromCharCode.apply(null, bytearray);    
            var value2 = new String(value).trim();
            return value2;
        }
        
        // Funktion zum Herstellen einer Modbus-Verbindung
        function ConnectModbus() {
            console.log("Init connection to: " + modbusHost +":" + modbusPort);
            // set requests parameters
            client.setTimeout (10000);
            // try to connect
            client.connectTCP (modbusHost, { port: modbusPort })
                .then(function()
                {
                    console.log("Connected, wait for reading...");
                })
                .catch(function(e)
                {
                    console.log(e);
                });
        }
        
        // Funktion zum Anlegen und Beschreiben eines Datenpunkts
        function ForceSetState(objectname, value, options) {
            if(!existsState("javascript.0." + objectname))      createState(objectname, value, options);
            else                                                setState(objectname, value);
        }  
        // ---------------------------------------------------------------
        // Functions to map registers into ioBreaker objects:
        function ProcessPowerMeterStatus() {       
            ForceSetState("Solarpower.Huawei.Meter.Status",                     GetU16(globalDataBuffer[powerMeterID], 37100),          {name: "", unit: ""});
            ForceSetState("Solarpower.Huawei.Meter.VoltageL1",                  GetI32(globalDataBuffer[powerMeterID], 37101) / 10,     {name: "", unit: "V"});
            ForceSetState("Solarpower.Huawei.Meter.VoltageL2",                  GetI32(globalDataBuffer[powerMeterID], 37103) / 10,     {name: "", unit: "V"});
            ForceSetState("Solarpower.Huawei.Meter.VoltageL3",                  GetI32(globalDataBuffer[powerMeterID], 37105) / 10,     {name: "", unit: "V"});
            ForceSetState("Solarpower.Huawei.Meter.CurrentL1",                  GetI32(globalDataBuffer[powerMeterID], 37107) / 100,    {name: "", unit: "A"});
            ForceSetState("Solarpower.Huawei.Meter.CurrentL2",                  GetI32(globalDataBuffer[powerMeterID], 37109) / 100,    {name: "", unit: "A"});
            ForceSetState("Solarpower.Huawei.Meter.CurrentL3",                  GetI32(globalDataBuffer[powerMeterID], 37111) / 100,    {name: "", unit: "A"});
            ForceSetState("Solarpower.Huawei.Meter.ActivePower",                GetI32(globalDataBuffer[powerMeterID], 37113) / 1,      {name: "", unit: "W"});
            ForceSetState("Solarpower.Huawei.Meter.ReactivePower",              GetI32(globalDataBuffer[powerMeterID], 37115) / 1,      {name: "", unit: "Var"});
            ForceSetState("Solarpower.Huawei.Meter.PowerFactor",                GetI16(globalDataBuffer[powerMeterID], 37117) / 1000,   {name: "", unit: ""});
            ForceSetState("Solarpower.Huawei.Meter.GridFrequency",              GetI16(globalDataBuffer[powerMeterID], 37118) / 100,    {name: "", unit: "Hz"});
            ForceSetState("Solarpower.Huawei.Meter.PositiveActiveEnergy",       GetI32(globalDataBuffer[powerMeterID], 37119) / 100,    {name: "", unit: "kWh"});
            ForceSetState("Solarpower.Huawei.Meter.ReverseActiveEnergy",        GetI32(globalDataBuffer[powerMeterID], 37121) / 100,    {name: "", unit: "kWh"});
            ForceSetState("Solarpower.Huawei.Meter.AccumulatedReactivePower",   GetI32(globalDataBuffer[powerMeterID], 37123) / 100,    {name: "", unit: "kVarh"});
            //ForceSetState("Solarpower.Huawei.Meter.MeterType",                  GetU16(globalDataBuffer[powerMeterID], 37125),          {name: "", unit: ""});
            ForceSetState("Solarpower.Huawei.Meter.VoltageL1-L2",               GetI32(globalDataBuffer[powerMeterID], 37126) / 10,     {name: "", unit: "V"});
            ForceSetState("Solarpower.Huawei.Meter.VoltageL2-L3",               GetI32(globalDataBuffer[powerMeterID], 37128) / 10,     {name: "", unit: "V"});
            ForceSetState("Solarpower.Huawei.Meter.VoltageL3-L1",               GetI32(globalDataBuffer[powerMeterID], 37130) / 10,     {name: "", unit: "V"});
            ForceSetState("Solarpower.Huawei.Meter.ActivePowerL1",              GetI32(globalDataBuffer[powerMeterID], 37132) / 1,      {name: "", unit: "W"});
            ForceSetState("Solarpower.Huawei.Meter.ActivePowerL2",              GetI32(globalDataBuffer[powerMeterID], 37134) / 1,      {name: "", unit: "W"});
            ForceSetState("Solarpower.Huawei.Meter.ActivePowerL3",              GetI32(globalDataBuffer[powerMeterID], 37136) / 1,      {name: "", unit: "W"});
            //ForceSetState("Solarpower.Huawei.Meter.MeterModel",                 GetU16(globalDataBuffer[powerMeterID], 37138),          {name: "", unit: ""});
        }
        
        function ProcessInverterStatus(id) {
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".State1",                   GetU16(globalDataBuffer[id-1], 32000),          {name: "", unit: ""});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".State2",                   GetU16(globalDataBuffer[id-1], 32002),          {name: "", unit: ""});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".State3",                   GetU32(globalDataBuffer[id-1], 32003),          {name: "", unit: ""});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".Alarm1",                   GetU16(globalDataBuffer[id-1], 32008),          {name: "", unit: ""});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".Alarm2",                   GetU16(globalDataBuffer[id-1], 32009),          {name: "", unit: ""});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".Alarm3",                   GetU16(globalDataBuffer[id-1], 32010),          {name: "", unit: ""});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.1_Voltage",         GetI16(globalDataBuffer[id-1], 32016) / 10,     {name: "", unit: "V"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.1_Current",         GetI16(globalDataBuffer[id-1], 32017) / 100,    {name: "", unit: "A"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.2_Voltage",         GetI16(globalDataBuffer[id-1], 32018) / 10,     {name: "", unit: "V"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.2_Current",         GetI16(globalDataBuffer[id-1], 32019) / 100,    {name: "", unit: "A"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.3_Voltage",         GetI16(globalDataBuffer[id-1], 32020) / 10,     {name: "", unit: "V"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.3_Current",         GetI16(globalDataBuffer[id-1], 32021) / 100,    {name: "", unit: "A"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.4_Voltage",         GetI16(globalDataBuffer[id-1], 32022) / 10,     {name: "", unit: "V"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.4_Current",         GetI16(globalDataBuffer[id-1], 32023) / 100,    {name: "", unit: "A"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".InputPower",               GetI32(globalDataBuffer[id-1], 32064) / 1000,   {name: "", unit: "kW"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1-L2_Voltage",       GetU16(globalDataBuffer[id-1], 32066) / 10,     {name: "", unit: "V"});      
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2-L3_Voltage",       GetU16(globalDataBuffer[id-1], 32067) / 10,     {name: "", unit: "V"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3-L1_Voltage",       GetU16(globalDataBuffer[id-1], 32068) / 10,     {name: "", unit: "V"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1_Voltage",          GetU16(globalDataBuffer[id-1], 32069) / 10,     {name: "", unit: "V"});                              
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2_Voltage",          GetU16(globalDataBuffer[id-1], 32070) / 10,     {name: "", unit: "V"});                                                  
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3_Voltage",          GetU16(globalDataBuffer[id-1], 32071) / 10,     {name: "", unit: "V"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1_Current",          GetI32(globalDataBuffer[id-1], 32072) / 1000,   {name: "", unit: "A"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2_Current",          GetI32(globalDataBuffer[id-1], 32074) / 1000,   {name: "", unit: "A"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3_Current",          GetI32(globalDataBuffer[id-1], 32076) / 1000,   {name: "", unit: "A"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".PeakActivePowerDay",       GetI32(globalDataBuffer[id-1], 32078) / 1000,   {name: "", unit: "kW"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".ActivePower",              GetI32(globalDataBuffer[id-1], 32080) / 1000,   {name: "", unit: "kW"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".ReactivePower",            GetI32(globalDataBuffer[id-1], 32082) / 1000,   {name: "", unit: "kVar"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".PowerFactor",              GetI16(globalDataBuffer[id-1], 32084) / 1000,   {name: "", unit: ""});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".GridFrequency",            GetU16(globalDataBuffer[id-1], 32085) / 100,    {name: "", unit: "Hz"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".Efficiency",               GetU16(globalDataBuffer[id-1], 32086) / 100,    {name: "", unit: "%"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".InternalTemperature",      GetI16(globalDataBuffer[id-1], 32087) / 10,     {name: "", unit: "°C"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".InsulationResistance",     GetU16(globalDataBuffer[id-1], 32088) / 1000,   {name: "", unit: "MOhm"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".DeviceStatus",             GetU16(globalDataBuffer[id-1], 32089),          {name: "", unit: ""});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".FaultCode",                GetU16(globalDataBuffer[id-1], 32090),          {name: "", unit: ""});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".StartupTime",              String(new Date(GetU32(globalDataBuffer[id-1], 32091)*1000)),          {name: "", unit: ""});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".ShutdownTime",             String(new Date(GetU32(globalDataBuffer[id-1], 32093)*1000)),          {name: "", unit: ""});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".AccomulatedEnergyYield",   GetU32(globalDataBuffer[id-1], 32106),          {name: "", unit: "kWh"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".DailyEnergyYield",         GetU32(globalDataBuffer[id-1], 32114),          {name: "", unit: "kWh"});
        }
        
        function ReadRegisterSpace(id, address, length) {
            client.setID(modbusID[id-1]);
            client.readHoldingRegisters(address, length, function(err, data) {
                if (err) {
                    console.warn("Error received reading address " + address + " from id: " + modbusID[id-1] + " with error: " + modbusErrorMessages[err.modbusCode]); 
                }
                else
                {   
                    console.debug("Read data from id/address " + modbusID[id-1] + "/" + address + "\nData is: " + data.data);
                    for(var i = 0; i < length; i++)  {
                        globalDataBuffer[id-1][address+i] = data.data[i];
                    } 
                }
            });
        }
        
        function ProcessData() {
            //console.log("Processing new data...");
            for(var i = 1; i <= modbusID.length; i++) {
                //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 (!client.isOpen){
                    ConnectModbus();
                }
                if(triggerprocessing == 1) {
                triggerprocessing = 0;
                ProcessData();        
                }      
           
            //console.log("Triggering read of inverter " + currentinverter + " at address " + registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][0] + " with length " +  registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][1]);
            ReadRegisterSpace(currentinverter, registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][0], registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][1]); 
            registerSpacesToReadContinuouslyPtr++;               
            if(registerSpacesToReadContinuouslyPtr >= registerSpacesToReadContinuously.length) {
                registerSpacesToReadContinuouslyPtr = 0;
                currentinverter++
                if(currentinverter > modbusID.length){
                    currentinverter = 1;  
                    triggerprocessing = 1;                    
                }
            }     
        }, 3000);
        
        J Offline
        J Offline
        juggi1962
        schrieb am zuletzt editiert von
        #69

        @alex-warkentin sagte in Huawei Sun2000 & ioBroker via JS script funktioniert:

        @juggi1962 Poste mal die Logs, wenn der Fehler auftritt

        Hier ist das Script, was ich für mich angepasst habe. Achtung! Ich habe die Batterie und andere für mich uninteressante Sachen rausgeschmissen und die Namen von Variablen und Funktionen angepasst. Für die Neuverbindung nach Verbindungsabbruch brauchst du die Zeilen 18 - 27 , 107-122 und 235 -237

        // License: Beerware! Do what ever you like with this, but I'm not liable for anything that you do with it.
        // If you like this code, feel free to buy me a beer ...
        // Have fun with it! der Kachel
        // @ts-ignore
        var modbusRTU = require("modbus-serial");
        var client = new modbusRTU();
        
        var modbusErrorMessages = [
            "Unknown error",
            "Illegal function (device does not support this read/write function)",
            "Illegal data address (register not supported by device)",
            "Illegal data value (value cannot be written to this register)",
            "Slave device failure (device reports internal error)",
            "Acknowledge (requested data will be available later)",
            "Slave device busy (retry request again later)"
        ];
        
        // Enter your inverter modbus IP and port here:
        const modbusHost = "000.000.000.000";
        const modbusPort = 502;
        // Enter the Modbus-IDs of your Sun2000 inverters here:
        const modbusID = [1];
        // On which Modbus-ID can we reach the power meter? (via Sun2000!)
        const powerMeterID = 0;
        
        // Connect to modbus client
        ConnectModbus();
        
        // These register spaces need to be read:
        const registerSpacesToReadContinuously = [[37100, 114], [32000, 116]];
        var registerSpacesToReadContinuouslyPtr = 0;
        
        var globalDataBuffer = new Array(1);
        globalDataBuffer[0] = new Array(50000); // not optimized....
        
        // ---------------------------------------------------------------
        // Some helper functions:
        function ReadUnsignedInt16(array) {
            var value = array[0];    
            return value;
        }
        
        function ReadUnsignedInt32(array) {
            var value = array[0] * 256 * 256 + array[1];    
            return value;
        }
        
        function ReadSignedInt16(array) {
            var value = 0;
            if (array[0] > 32767)
                value = array[0] - 65535; 
            else
                value = array[0];
        
            return value;
        }
        function ReadSignedInt32(array) {
            var value = 0;
            for (var i = 0; i < 2; i++) {
                value = (value << 16) | array[i];
            }
            return value;
        }
        function GetU16(dataarray, index) {
            var value = ReadUnsignedInt16(dataarray.slice(index, index+1));
            return value;
        }
        
        function GetU32(dataarray, index) {
            var value = ReadUnsignedInt32(dataarray.slice(index, index+2));
            return value;
        }
        
        function GetI16(dataarray, index) {
            var value = ReadSignedInt16(dataarray.slice(index, index+1));
            return value;
        }
        
        function GetI32(dataarray, index) {
            var value = ReadSignedInt32(dataarray.slice(index, index+2));
            return value;
        }
        
        function GetString(dataarray, index, length) {
            var shortarray = dataarray.slice(index, index+length);
            var bytearray = [];
            for(var i = 0; i < length; i++) {
                bytearray.push(dataarray[index+i] >> 8);
                bytearray.push(dataarray[index+i] & 0xff);
            }       
            var value =  String.fromCharCode.apply(null, bytearray);    
            return value;
        }
        
        function GetZeroTerminatedString(dataarray, index, length) {
            var shortarray = dataarray.slice(index, index+length);
            var bytearray = [];
            for(var i = 0; i < length; i++) {
                bytearray.push(dataarray[index+i] >> 8);
                bytearray.push(dataarray[index+i] & 0xff);
            }       
            var value =  String.fromCharCode.apply(null, bytearray);    
            var value2 = new String(value).trim();
            return value2;
        }
        
        // Funktion zum Herstellen einer Modbus-Verbindung
        function ConnectModbus() {
            console.log("Init connection to: " + modbusHost +":" + modbusPort);
            // set requests parameters
            client.setTimeout (10000);
            // try to connect
            client.connectTCP (modbusHost, { port: modbusPort })
                .then(function()
                {
                    console.log("Connected, wait for reading...");
                })
                .catch(function(e)
                {
                    console.log(e);
                });
        }
        
        // Funktion zum Anlegen und Beschreiben eines Datenpunkts
        function ForceSetState(objectname, value, options) {
            if(!existsState("javascript.0." + objectname))      createState(objectname, value, options);
            else                                                setState(objectname, value);
        }  
        // ---------------------------------------------------------------
        // Functions to map registers into ioBreaker objects:
        function ProcessPowerMeterStatus() {       
            ForceSetState("Solarpower.Huawei.Meter.Status",                     GetU16(globalDataBuffer[powerMeterID], 37100),          {name: "", unit: ""});
            ForceSetState("Solarpower.Huawei.Meter.VoltageL1",                  GetI32(globalDataBuffer[powerMeterID], 37101) / 10,     {name: "", unit: "V"});
            ForceSetState("Solarpower.Huawei.Meter.VoltageL2",                  GetI32(globalDataBuffer[powerMeterID], 37103) / 10,     {name: "", unit: "V"});
            ForceSetState("Solarpower.Huawei.Meter.VoltageL3",                  GetI32(globalDataBuffer[powerMeterID], 37105) / 10,     {name: "", unit: "V"});
            ForceSetState("Solarpower.Huawei.Meter.CurrentL1",                  GetI32(globalDataBuffer[powerMeterID], 37107) / 100,    {name: "", unit: "A"});
            ForceSetState("Solarpower.Huawei.Meter.CurrentL2",                  GetI32(globalDataBuffer[powerMeterID], 37109) / 100,    {name: "", unit: "A"});
            ForceSetState("Solarpower.Huawei.Meter.CurrentL3",                  GetI32(globalDataBuffer[powerMeterID], 37111) / 100,    {name: "", unit: "A"});
            ForceSetState("Solarpower.Huawei.Meter.ActivePower",                GetI32(globalDataBuffer[powerMeterID], 37113) / 1,      {name: "", unit: "W"});
            ForceSetState("Solarpower.Huawei.Meter.ReactivePower",              GetI32(globalDataBuffer[powerMeterID], 37115) / 1,      {name: "", unit: "Var"});
            ForceSetState("Solarpower.Huawei.Meter.PowerFactor",                GetI16(globalDataBuffer[powerMeterID], 37117) / 1000,   {name: "", unit: ""});
            ForceSetState("Solarpower.Huawei.Meter.GridFrequency",              GetI16(globalDataBuffer[powerMeterID], 37118) / 100,    {name: "", unit: "Hz"});
            ForceSetState("Solarpower.Huawei.Meter.PositiveActiveEnergy",       GetI32(globalDataBuffer[powerMeterID], 37119) / 100,    {name: "", unit: "kWh"});
            ForceSetState("Solarpower.Huawei.Meter.ReverseActiveEnergy",        GetI32(globalDataBuffer[powerMeterID], 37121) / 100,    {name: "", unit: "kWh"});
            ForceSetState("Solarpower.Huawei.Meter.AccumulatedReactivePower",   GetI32(globalDataBuffer[powerMeterID], 37123) / 100,    {name: "", unit: "kVarh"});
            //ForceSetState("Solarpower.Huawei.Meter.MeterType",                  GetU16(globalDataBuffer[powerMeterID], 37125),          {name: "", unit: ""});
            ForceSetState("Solarpower.Huawei.Meter.VoltageL1-L2",               GetI32(globalDataBuffer[powerMeterID], 37126) / 10,     {name: "", unit: "V"});
            ForceSetState("Solarpower.Huawei.Meter.VoltageL2-L3",               GetI32(globalDataBuffer[powerMeterID], 37128) / 10,     {name: "", unit: "V"});
            ForceSetState("Solarpower.Huawei.Meter.VoltageL3-L1",               GetI32(globalDataBuffer[powerMeterID], 37130) / 10,     {name: "", unit: "V"});
            ForceSetState("Solarpower.Huawei.Meter.ActivePowerL1",              GetI32(globalDataBuffer[powerMeterID], 37132) / 1,      {name: "", unit: "W"});
            ForceSetState("Solarpower.Huawei.Meter.ActivePowerL2",              GetI32(globalDataBuffer[powerMeterID], 37134) / 1,      {name: "", unit: "W"});
            ForceSetState("Solarpower.Huawei.Meter.ActivePowerL3",              GetI32(globalDataBuffer[powerMeterID], 37136) / 1,      {name: "", unit: "W"});
            //ForceSetState("Solarpower.Huawei.Meter.MeterModel",                 GetU16(globalDataBuffer[powerMeterID], 37138),          {name: "", unit: ""});
        }
        
        function ProcessInverterStatus(id) {
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".State1",                   GetU16(globalDataBuffer[id-1], 32000),          {name: "", unit: ""});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".State2",                   GetU16(globalDataBuffer[id-1], 32002),          {name: "", unit: ""});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".State3",                   GetU32(globalDataBuffer[id-1], 32003),          {name: "", unit: ""});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".Alarm1",                   GetU16(globalDataBuffer[id-1], 32008),          {name: "", unit: ""});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".Alarm2",                   GetU16(globalDataBuffer[id-1], 32009),          {name: "", unit: ""});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".Alarm3",                   GetU16(globalDataBuffer[id-1], 32010),          {name: "", unit: ""});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.1_Voltage",         GetI16(globalDataBuffer[id-1], 32016) / 10,     {name: "", unit: "V"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.1_Current",         GetI16(globalDataBuffer[id-1], 32017) / 100,    {name: "", unit: "A"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.2_Voltage",         GetI16(globalDataBuffer[id-1], 32018) / 10,     {name: "", unit: "V"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.2_Current",         GetI16(globalDataBuffer[id-1], 32019) / 100,    {name: "", unit: "A"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.3_Voltage",         GetI16(globalDataBuffer[id-1], 32020) / 10,     {name: "", unit: "V"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.3_Current",         GetI16(globalDataBuffer[id-1], 32021) / 100,    {name: "", unit: "A"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.4_Voltage",         GetI16(globalDataBuffer[id-1], 32022) / 10,     {name: "", unit: "V"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.4_Current",         GetI16(globalDataBuffer[id-1], 32023) / 100,    {name: "", unit: "A"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".InputPower",               GetI32(globalDataBuffer[id-1], 32064) / 1000,   {name: "", unit: "kW"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1-L2_Voltage",       GetU16(globalDataBuffer[id-1], 32066) / 10,     {name: "", unit: "V"});      
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2-L3_Voltage",       GetU16(globalDataBuffer[id-1], 32067) / 10,     {name: "", unit: "V"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3-L1_Voltage",       GetU16(globalDataBuffer[id-1], 32068) / 10,     {name: "", unit: "V"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1_Voltage",          GetU16(globalDataBuffer[id-1], 32069) / 10,     {name: "", unit: "V"});                              
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2_Voltage",          GetU16(globalDataBuffer[id-1], 32070) / 10,     {name: "", unit: "V"});                                                  
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3_Voltage",          GetU16(globalDataBuffer[id-1], 32071) / 10,     {name: "", unit: "V"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1_Current",          GetI32(globalDataBuffer[id-1], 32072) / 1000,   {name: "", unit: "A"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2_Current",          GetI32(globalDataBuffer[id-1], 32074) / 1000,   {name: "", unit: "A"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3_Current",          GetI32(globalDataBuffer[id-1], 32076) / 1000,   {name: "", unit: "A"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".PeakActivePowerDay",       GetI32(globalDataBuffer[id-1], 32078) / 1000,   {name: "", unit: "kW"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".ActivePower",              GetI32(globalDataBuffer[id-1], 32080) / 1000,   {name: "", unit: "kW"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".ReactivePower",            GetI32(globalDataBuffer[id-1], 32082) / 1000,   {name: "", unit: "kVar"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".PowerFactor",              GetI16(globalDataBuffer[id-1], 32084) / 1000,   {name: "", unit: ""});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".GridFrequency",            GetU16(globalDataBuffer[id-1], 32085) / 100,    {name: "", unit: "Hz"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".Efficiency",               GetU16(globalDataBuffer[id-1], 32086) / 100,    {name: "", unit: "%"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".InternalTemperature",      GetI16(globalDataBuffer[id-1], 32087) / 10,     {name: "", unit: "°C"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".InsulationResistance",     GetU16(globalDataBuffer[id-1], 32088) / 1000,   {name: "", unit: "MOhm"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".DeviceStatus",             GetU16(globalDataBuffer[id-1], 32089),          {name: "", unit: ""});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".FaultCode",                GetU16(globalDataBuffer[id-1], 32090),          {name: "", unit: ""});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".StartupTime",              String(new Date(GetU32(globalDataBuffer[id-1], 32091)*1000)),          {name: "", unit: ""});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".ShutdownTime",             String(new Date(GetU32(globalDataBuffer[id-1], 32093)*1000)),          {name: "", unit: ""});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".AccomulatedEnergyYield",   GetU32(globalDataBuffer[id-1], 32106),          {name: "", unit: "kWh"});
            ForceSetState("Solarpower.Huawei.Inverter." + id + ".DailyEnergyYield",         GetU32(globalDataBuffer[id-1], 32114),          {name: "", unit: "kWh"});
        }
        
        function ReadRegisterSpace(id, address, length) {
            client.setID(modbusID[id-1]);
            client.readHoldingRegisters(address, length, function(err, data) {
                if (err) {
                    console.warn("Error received reading address " + address + " from id: " + modbusID[id-1] + " with error: " + modbusErrorMessages[err.modbusCode]); 
                }
                else
                {   
                    console.debug("Read data from id/address " + modbusID[id-1] + "/" + address + "\nData is: " + data.data);
                    for(var i = 0; i < length; i++)  {
                        globalDataBuffer[id-1][address+i] = data.data[i];
                    } 
                }
            });
        }
        
        function ProcessData() {
            //console.log("Processing new data...");
            for(var i = 1; i <= modbusID.length; i++) {
                //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 (!client.isOpen){
                    ConnectModbus();
                }
                if(triggerprocessing == 1) {
                triggerprocessing = 0;
                ProcessData();        
                }      
           
            //console.log("Triggering read of inverter " + currentinverter + " at address " + registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][0] + " with length " +  registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][1]);
            ReadRegisterSpace(currentinverter, registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][0], registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][1]); 
            registerSpacesToReadContinuouslyPtr++;               
            if(registerSpacesToReadContinuouslyPtr >= registerSpacesToReadContinuously.length) {
                registerSpacesToReadContinuouslyPtr = 0;
                currentinverter++
                if(currentinverter > modbusID.length){
                    currentinverter = 1;  
                    triggerprocessing = 1;                    
                }
            }     
        }, 3000);
        

        So der Fehler ist wieder da, die Freude hat nicht lange angehalten.
        Hier die Logs vom Fehler, nach Neustart des Skrips läufts wieder :-(

        
        
        javascript.0
        2023-03-06 10:27:26.845	warn	script.js.Neu.PV_Anlage.Modbus_Huawei_Sun2000_neu: Error received reading address 32000 from id: 1 with error: undefined
        
        javascript.0
        2023-03-06 10:27:23.846	warn	script.js.Neu.PV_Anlage.Modbus_Huawei_Sun2000_neu: Error received reading address 37100 from id: 1 with error: undefined
        
        javascript.0
        2023-03-06 10:27:20.841	warn	script.js.Neu.PV_Anlage.Modbus_Huawei_Sun2000_neu: Error received reading address 32000 from id: 1 with error: undefined
        
        javascript.0
        2023-03-06 10:27:17.842	warn	script.js.Neu.PV_Anlage.Modbus_Huawei_Sun2000_neu: Error received reading address 37100 from id: 1 with error: undefined
        
        javascript.0
        2023-03-06 10:27:14.840	warn	script.js.Neu.PV_Anlage.Modbus_Huawei_Sun2000_neu: Error received reading address 32000 from id: 1 with error: undefined
        
        javascript.0
        2023-03-06 10:27:11.842	warn	script.js.Neu.PV_Anlage.Modbus_Huawei_Sun2000_neu: Error received reading address 37100 from id: 1 with error: undefined
        
        javascript.0
        2023-03-06 10:27:08.839	warn	script.js.Neu.PV_Anlage.Modbus_Huawei_Sun2000_neu: Error received reading address 32000 from id: 1 with error: undefined
        
        javascript.0
        2023-03-06 10:27:05.841	warn	script.js.Neu.PV_Anlage.Modbus_Huawei_Sun2000_neu: Error received reading address 37100 from id: 1 with error: undefined
        
        javascript.0
        2023-03-06 10:27:02.838	warn	script.js.Neu.PV_Anlage.Modbus_Huawei_Sun2000_neu: Error received reading address 32000 from id: 1 with error: undefined
        
        javascript.0
        2023-03-06 10:26:59.839	warn	script.js.Neu.PV_Anlage.Modbus_Huawei_Sun2000_neu: Error received reading address 37100 from id: 1 with error: undefined
        
        javascript.0
        2023-03-06 10:26:56.837	warn	script.js.Neu.PV_Anlage.Modbus_Huawei_Sun2000_neu: Error received reading address 32000 from id: 1 with error: undefined
        
        javascript.0
        2023-03-06 10:26:53.840	warn	script.js.Neu.PV_Anlage.Modbus_Huawei_Sun2000_neu: Error received reading address 37100 from id: 1 with error: undefined
        
        1 Antwort Letzte Antwort
        0
        • J juggi1962

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

          @alex-warkentin sagte in Huawei Sun2000 & ioBroker via JS script funktioniert:

          @juggi1962 Poste mal die Logs, wenn der Fehler auftritt

          Hier ist das Script, was ich für mich angepasst habe. Achtung! Ich habe die Batterie und andere für mich uninteressante Sachen rausgeschmissen und die Namen von Variablen und Funktionen angepasst. Für die Neuverbindung nach Verbindungsabbruch brauchst du die Zeilen 18 - 27 , 107-122 und 235 -237

          // License: Beerware! Do what ever you like with this, but I'm not liable for anything that you do with it.
          // If you like this code, feel free to buy me a beer ...
          // Have fun with it! der Kachel
          // @ts-ignore
          var modbusRTU = require("modbus-serial");
          var client = new modbusRTU();
          
          var modbusErrorMessages = [
              "Unknown error",
              "Illegal function (device does not support this read/write function)",
              "Illegal data address (register not supported by device)",
              "Illegal data value (value cannot be written to this register)",
              "Slave device failure (device reports internal error)",
              "Acknowledge (requested data will be available later)",
              "Slave device busy (retry request again later)"
          ];
          
          // Enter your inverter modbus IP and port here:
          const modbusHost = "000.000.000.000";
          const modbusPort = 502;
          // Enter the Modbus-IDs of your Sun2000 inverters here:
          const modbusID = [1];
          // On which Modbus-ID can we reach the power meter? (via Sun2000!)
          const powerMeterID = 0;
          
          // Connect to modbus client
          ConnectModbus();
          
          // These register spaces need to be read:
          const registerSpacesToReadContinuously = [[37100, 114], [32000, 116]];
          var registerSpacesToReadContinuouslyPtr = 0;
          
          var globalDataBuffer = new Array(1);
          globalDataBuffer[0] = new Array(50000); // not optimized....
          
          // ---------------------------------------------------------------
          // Some helper functions:
          function ReadUnsignedInt16(array) {
              var value = array[0];    
              return value;
          }
          
          function ReadUnsignedInt32(array) {
              var value = array[0] * 256 * 256 + array[1];    
              return value;
          }
          
          function ReadSignedInt16(array) {
              var value = 0;
              if (array[0] > 32767)
                  value = array[0] - 65535; 
              else
                  value = array[0];
          
              return value;
          }
          function ReadSignedInt32(array) {
              var value = 0;
              for (var i = 0; i < 2; i++) {
                  value = (value << 16) | array[i];
              }
              return value;
          }
          function GetU16(dataarray, index) {
              var value = ReadUnsignedInt16(dataarray.slice(index, index+1));
              return value;
          }
          
          function GetU32(dataarray, index) {
              var value = ReadUnsignedInt32(dataarray.slice(index, index+2));
              return value;
          }
          
          function GetI16(dataarray, index) {
              var value = ReadSignedInt16(dataarray.slice(index, index+1));
              return value;
          }
          
          function GetI32(dataarray, index) {
              var value = ReadSignedInt32(dataarray.slice(index, index+2));
              return value;
          }
          
          function GetString(dataarray, index, length) {
              var shortarray = dataarray.slice(index, index+length);
              var bytearray = [];
              for(var i = 0; i < length; i++) {
                  bytearray.push(dataarray[index+i] >> 8);
                  bytearray.push(dataarray[index+i] & 0xff);
              }       
              var value =  String.fromCharCode.apply(null, bytearray);    
              return value;
          }
          
          function GetZeroTerminatedString(dataarray, index, length) {
              var shortarray = dataarray.slice(index, index+length);
              var bytearray = [];
              for(var i = 0; i < length; i++) {
                  bytearray.push(dataarray[index+i] >> 8);
                  bytearray.push(dataarray[index+i] & 0xff);
              }       
              var value =  String.fromCharCode.apply(null, bytearray);    
              var value2 = new String(value).trim();
              return value2;
          }
          
          // Funktion zum Herstellen einer Modbus-Verbindung
          function ConnectModbus() {
              console.log("Init connection to: " + modbusHost +":" + modbusPort);
              // set requests parameters
              client.setTimeout (10000);
              // try to connect
              client.connectTCP (modbusHost, { port: modbusPort })
                  .then(function()
                  {
                      console.log("Connected, wait for reading...");
                  })
                  .catch(function(e)
                  {
                      console.log(e);
                  });
          }
          
          // Funktion zum Anlegen und Beschreiben eines Datenpunkts
          function ForceSetState(objectname, value, options) {
              if(!existsState("javascript.0." + objectname))      createState(objectname, value, options);
              else                                                setState(objectname, value);
          }  
          // ---------------------------------------------------------------
          // Functions to map registers into ioBreaker objects:
          function ProcessPowerMeterStatus() {       
              ForceSetState("Solarpower.Huawei.Meter.Status",                     GetU16(globalDataBuffer[powerMeterID], 37100),          {name: "", unit: ""});
              ForceSetState("Solarpower.Huawei.Meter.VoltageL1",                  GetI32(globalDataBuffer[powerMeterID], 37101) / 10,     {name: "", unit: "V"});
              ForceSetState("Solarpower.Huawei.Meter.VoltageL2",                  GetI32(globalDataBuffer[powerMeterID], 37103) / 10,     {name: "", unit: "V"});
              ForceSetState("Solarpower.Huawei.Meter.VoltageL3",                  GetI32(globalDataBuffer[powerMeterID], 37105) / 10,     {name: "", unit: "V"});
              ForceSetState("Solarpower.Huawei.Meter.CurrentL1",                  GetI32(globalDataBuffer[powerMeterID], 37107) / 100,    {name: "", unit: "A"});
              ForceSetState("Solarpower.Huawei.Meter.CurrentL2",                  GetI32(globalDataBuffer[powerMeterID], 37109) / 100,    {name: "", unit: "A"});
              ForceSetState("Solarpower.Huawei.Meter.CurrentL3",                  GetI32(globalDataBuffer[powerMeterID], 37111) / 100,    {name: "", unit: "A"});
              ForceSetState("Solarpower.Huawei.Meter.ActivePower",                GetI32(globalDataBuffer[powerMeterID], 37113) / 1,      {name: "", unit: "W"});
              ForceSetState("Solarpower.Huawei.Meter.ReactivePower",              GetI32(globalDataBuffer[powerMeterID], 37115) / 1,      {name: "", unit: "Var"});
              ForceSetState("Solarpower.Huawei.Meter.PowerFactor",                GetI16(globalDataBuffer[powerMeterID], 37117) / 1000,   {name: "", unit: ""});
              ForceSetState("Solarpower.Huawei.Meter.GridFrequency",              GetI16(globalDataBuffer[powerMeterID], 37118) / 100,    {name: "", unit: "Hz"});
              ForceSetState("Solarpower.Huawei.Meter.PositiveActiveEnergy",       GetI32(globalDataBuffer[powerMeterID], 37119) / 100,    {name: "", unit: "kWh"});
              ForceSetState("Solarpower.Huawei.Meter.ReverseActiveEnergy",        GetI32(globalDataBuffer[powerMeterID], 37121) / 100,    {name: "", unit: "kWh"});
              ForceSetState("Solarpower.Huawei.Meter.AccumulatedReactivePower",   GetI32(globalDataBuffer[powerMeterID], 37123) / 100,    {name: "", unit: "kVarh"});
              //ForceSetState("Solarpower.Huawei.Meter.MeterType",                  GetU16(globalDataBuffer[powerMeterID], 37125),          {name: "", unit: ""});
              ForceSetState("Solarpower.Huawei.Meter.VoltageL1-L2",               GetI32(globalDataBuffer[powerMeterID], 37126) / 10,     {name: "", unit: "V"});
              ForceSetState("Solarpower.Huawei.Meter.VoltageL2-L3",               GetI32(globalDataBuffer[powerMeterID], 37128) / 10,     {name: "", unit: "V"});
              ForceSetState("Solarpower.Huawei.Meter.VoltageL3-L1",               GetI32(globalDataBuffer[powerMeterID], 37130) / 10,     {name: "", unit: "V"});
              ForceSetState("Solarpower.Huawei.Meter.ActivePowerL1",              GetI32(globalDataBuffer[powerMeterID], 37132) / 1,      {name: "", unit: "W"});
              ForceSetState("Solarpower.Huawei.Meter.ActivePowerL2",              GetI32(globalDataBuffer[powerMeterID], 37134) / 1,      {name: "", unit: "W"});
              ForceSetState("Solarpower.Huawei.Meter.ActivePowerL3",              GetI32(globalDataBuffer[powerMeterID], 37136) / 1,      {name: "", unit: "W"});
              //ForceSetState("Solarpower.Huawei.Meter.MeterModel",                 GetU16(globalDataBuffer[powerMeterID], 37138),          {name: "", unit: ""});
          }
          
          function ProcessInverterStatus(id) {
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".State1",                   GetU16(globalDataBuffer[id-1], 32000),          {name: "", unit: ""});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".State2",                   GetU16(globalDataBuffer[id-1], 32002),          {name: "", unit: ""});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".State3",                   GetU32(globalDataBuffer[id-1], 32003),          {name: "", unit: ""});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".Alarm1",                   GetU16(globalDataBuffer[id-1], 32008),          {name: "", unit: ""});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".Alarm2",                   GetU16(globalDataBuffer[id-1], 32009),          {name: "", unit: ""});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".Alarm3",                   GetU16(globalDataBuffer[id-1], 32010),          {name: "", unit: ""});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.1_Voltage",         GetI16(globalDataBuffer[id-1], 32016) / 10,     {name: "", unit: "V"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.1_Current",         GetI16(globalDataBuffer[id-1], 32017) / 100,    {name: "", unit: "A"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.2_Voltage",         GetI16(globalDataBuffer[id-1], 32018) / 10,     {name: "", unit: "V"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.2_Current",         GetI16(globalDataBuffer[id-1], 32019) / 100,    {name: "", unit: "A"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.3_Voltage",         GetI16(globalDataBuffer[id-1], 32020) / 10,     {name: "", unit: "V"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.3_Current",         GetI16(globalDataBuffer[id-1], 32021) / 100,    {name: "", unit: "A"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.4_Voltage",         GetI16(globalDataBuffer[id-1], 32022) / 10,     {name: "", unit: "V"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.4_Current",         GetI16(globalDataBuffer[id-1], 32023) / 100,    {name: "", unit: "A"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".InputPower",               GetI32(globalDataBuffer[id-1], 32064) / 1000,   {name: "", unit: "kW"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1-L2_Voltage",       GetU16(globalDataBuffer[id-1], 32066) / 10,     {name: "", unit: "V"});      
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2-L3_Voltage",       GetU16(globalDataBuffer[id-1], 32067) / 10,     {name: "", unit: "V"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3-L1_Voltage",       GetU16(globalDataBuffer[id-1], 32068) / 10,     {name: "", unit: "V"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1_Voltage",          GetU16(globalDataBuffer[id-1], 32069) / 10,     {name: "", unit: "V"});                              
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2_Voltage",          GetU16(globalDataBuffer[id-1], 32070) / 10,     {name: "", unit: "V"});                                                  
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3_Voltage",          GetU16(globalDataBuffer[id-1], 32071) / 10,     {name: "", unit: "V"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1_Current",          GetI32(globalDataBuffer[id-1], 32072) / 1000,   {name: "", unit: "A"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2_Current",          GetI32(globalDataBuffer[id-1], 32074) / 1000,   {name: "", unit: "A"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3_Current",          GetI32(globalDataBuffer[id-1], 32076) / 1000,   {name: "", unit: "A"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".PeakActivePowerDay",       GetI32(globalDataBuffer[id-1], 32078) / 1000,   {name: "", unit: "kW"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".ActivePower",              GetI32(globalDataBuffer[id-1], 32080) / 1000,   {name: "", unit: "kW"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".ReactivePower",            GetI32(globalDataBuffer[id-1], 32082) / 1000,   {name: "", unit: "kVar"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".PowerFactor",              GetI16(globalDataBuffer[id-1], 32084) / 1000,   {name: "", unit: ""});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".GridFrequency",            GetU16(globalDataBuffer[id-1], 32085) / 100,    {name: "", unit: "Hz"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".Efficiency",               GetU16(globalDataBuffer[id-1], 32086) / 100,    {name: "", unit: "%"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".InternalTemperature",      GetI16(globalDataBuffer[id-1], 32087) / 10,     {name: "", unit: "°C"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".InsulationResistance",     GetU16(globalDataBuffer[id-1], 32088) / 1000,   {name: "", unit: "MOhm"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".DeviceStatus",             GetU16(globalDataBuffer[id-1], 32089),          {name: "", unit: ""});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".FaultCode",                GetU16(globalDataBuffer[id-1], 32090),          {name: "", unit: ""});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".StartupTime",              String(new Date(GetU32(globalDataBuffer[id-1], 32091)*1000)),          {name: "", unit: ""});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".ShutdownTime",             String(new Date(GetU32(globalDataBuffer[id-1], 32093)*1000)),          {name: "", unit: ""});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".AccomulatedEnergyYield",   GetU32(globalDataBuffer[id-1], 32106),          {name: "", unit: "kWh"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".DailyEnergyYield",         GetU32(globalDataBuffer[id-1], 32114),          {name: "", unit: "kWh"});
          }
          
          function ReadRegisterSpace(id, address, length) {
              client.setID(modbusID[id-1]);
              client.readHoldingRegisters(address, length, function(err, data) {
                  if (err) {
                      console.warn("Error received reading address " + address + " from id: " + modbusID[id-1] + " with error: " + modbusErrorMessages[err.modbusCode]); 
                  }
                  else
                  {   
                      console.debug("Read data from id/address " + modbusID[id-1] + "/" + address + "\nData is: " + data.data);
                      for(var i = 0; i < length; i++)  {
                          globalDataBuffer[id-1][address+i] = data.data[i];
                      } 
                  }
              });
          }
          
          function ProcessData() {
              //console.log("Processing new data...");
              for(var i = 1; i <= modbusID.length; i++) {
                  //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 (!client.isOpen){
                      ConnectModbus();
                  }
                  if(triggerprocessing == 1) {
                  triggerprocessing = 0;
                  ProcessData();        
                  }      
             
              //console.log("Triggering read of inverter " + currentinverter + " at address " + registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][0] + " with length " +  registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][1]);
              ReadRegisterSpace(currentinverter, registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][0], registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][1]); 
              registerSpacesToReadContinuouslyPtr++;               
              if(registerSpacesToReadContinuouslyPtr >= registerSpacesToReadContinuously.length) {
                  registerSpacesToReadContinuouslyPtr = 0;
                  currentinverter++
                  if(currentinverter > modbusID.length){
                      currentinverter = 1;  
                      triggerprocessing = 1;                    
                  }
              }     
          }, 3000);
          

          Super Danke.
          Hab eh keine Batterie. Werde es gleich testen.
          Gruß Jürgen

          Guten Morgen soweit läuft es mal, aber kann es sein, dass bei
          Solarpower Huawei Inverter 1 AccomulatedEnergyYield und
          Solarpower.Huawei.Inverter.1.DailyEnergyYield
          das Komma fehlt, denn der Tägliche Ertrag wäre schön aber nicht war :-)
          kann man das irgend wie ändern?

          Alex WarkentinA Offline
          Alex WarkentinA Offline
          Alex Warkentin
          schrieb am zuletzt editiert von
          #70

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

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

          @alex-warkentin sagte in Huawei Sun2000 & ioBroker via JS script funktioniert:

          @juggi1962 Poste mal die Logs, wenn der Fehler auftritt

          Hier ist das Script, was ich für mich angepasst habe. Achtung! Ich habe die Batterie und andere für mich uninteressante Sachen rausgeschmissen und die Namen von Variablen und Funktionen angepasst. Für die Neuverbindung nach Verbindungsabbruch brauchst du die Zeilen 18 - 27 , 107-122 und 235 -237

          // License: Beerware! Do what ever you like with this, but I'm not liable for anything that you do with it.
          // If you like this code, feel free to buy me a beer ...
          // Have fun with it! der Kachel
          // @ts-ignore
          var modbusRTU = require("modbus-serial");
          var client = new modbusRTU();
          
          var modbusErrorMessages = [
              "Unknown error",
              "Illegal function (device does not support this read/write function)",
              "Illegal data address (register not supported by device)",
              "Illegal data value (value cannot be written to this register)",
              "Slave device failure (device reports internal error)",
              "Acknowledge (requested data will be available later)",
              "Slave device busy (retry request again later)"
          ];
          
          // Enter your inverter modbus IP and port here:
          const modbusHost = "000.000.000.000";
          const modbusPort = 502;
          // Enter the Modbus-IDs of your Sun2000 inverters here:
          const modbusID = [1];
          // On which Modbus-ID can we reach the power meter? (via Sun2000!)
          const powerMeterID = 0;
          
          // Connect to modbus client
          ConnectModbus();
          
          // These register spaces need to be read:
          const registerSpacesToReadContinuously = [[37100, 114], [32000, 116]];
          var registerSpacesToReadContinuouslyPtr = 0;
          
          var globalDataBuffer = new Array(1);
          globalDataBuffer[0] = new Array(50000); // not optimized....
          
          // ---------------------------------------------------------------
          // Some helper functions:
          function ReadUnsignedInt16(array) {
              var value = array[0];    
              return value;
          }
          
          function ReadUnsignedInt32(array) {
              var value = array[0] * 256 * 256 + array[1];    
              return value;
          }
          
          function ReadSignedInt16(array) {
              var value = 0;
              if (array[0] > 32767)
                  value = array[0] - 65535; 
              else
                  value = array[0];
          
              return value;
          }
          function ReadSignedInt32(array) {
              var value = 0;
              for (var i = 0; i < 2; i++) {
                  value = (value << 16) | array[i];
              }
              return value;
          }
          function GetU16(dataarray, index) {
              var value = ReadUnsignedInt16(dataarray.slice(index, index+1));
              return value;
          }
          
          function GetU32(dataarray, index) {
              var value = ReadUnsignedInt32(dataarray.slice(index, index+2));
              return value;
          }
          
          function GetI16(dataarray, index) {
              var value = ReadSignedInt16(dataarray.slice(index, index+1));
              return value;
          }
          
          function GetI32(dataarray, index) {
              var value = ReadSignedInt32(dataarray.slice(index, index+2));
              return value;
          }
          
          function GetString(dataarray, index, length) {
              var shortarray = dataarray.slice(index, index+length);
              var bytearray = [];
              for(var i = 0; i < length; i++) {
                  bytearray.push(dataarray[index+i] >> 8);
                  bytearray.push(dataarray[index+i] & 0xff);
              }       
              var value =  String.fromCharCode.apply(null, bytearray);    
              return value;
          }
          
          function GetZeroTerminatedString(dataarray, index, length) {
              var shortarray = dataarray.slice(index, index+length);
              var bytearray = [];
              for(var i = 0; i < length; i++) {
                  bytearray.push(dataarray[index+i] >> 8);
                  bytearray.push(dataarray[index+i] & 0xff);
              }       
              var value =  String.fromCharCode.apply(null, bytearray);    
              var value2 = new String(value).trim();
              return value2;
          }
          
          // Funktion zum Herstellen einer Modbus-Verbindung
          function ConnectModbus() {
              console.log("Init connection to: " + modbusHost +":" + modbusPort);
              // set requests parameters
              client.setTimeout (10000);
              // try to connect
              client.connectTCP (modbusHost, { port: modbusPort })
                  .then(function()
                  {
                      console.log("Connected, wait for reading...");
                  })
                  .catch(function(e)
                  {
                      console.log(e);
                  });
          }
          
          // Funktion zum Anlegen und Beschreiben eines Datenpunkts
          function ForceSetState(objectname, value, options) {
              if(!existsState("javascript.0." + objectname))      createState(objectname, value, options);
              else                                                setState(objectname, value);
          }  
          // ---------------------------------------------------------------
          // Functions to map registers into ioBreaker objects:
          function ProcessPowerMeterStatus() {       
              ForceSetState("Solarpower.Huawei.Meter.Status",                     GetU16(globalDataBuffer[powerMeterID], 37100),          {name: "", unit: ""});
              ForceSetState("Solarpower.Huawei.Meter.VoltageL1",                  GetI32(globalDataBuffer[powerMeterID], 37101) / 10,     {name: "", unit: "V"});
              ForceSetState("Solarpower.Huawei.Meter.VoltageL2",                  GetI32(globalDataBuffer[powerMeterID], 37103) / 10,     {name: "", unit: "V"});
              ForceSetState("Solarpower.Huawei.Meter.VoltageL3",                  GetI32(globalDataBuffer[powerMeterID], 37105) / 10,     {name: "", unit: "V"});
              ForceSetState("Solarpower.Huawei.Meter.CurrentL1",                  GetI32(globalDataBuffer[powerMeterID], 37107) / 100,    {name: "", unit: "A"});
              ForceSetState("Solarpower.Huawei.Meter.CurrentL2",                  GetI32(globalDataBuffer[powerMeterID], 37109) / 100,    {name: "", unit: "A"});
              ForceSetState("Solarpower.Huawei.Meter.CurrentL3",                  GetI32(globalDataBuffer[powerMeterID], 37111) / 100,    {name: "", unit: "A"});
              ForceSetState("Solarpower.Huawei.Meter.ActivePower",                GetI32(globalDataBuffer[powerMeterID], 37113) / 1,      {name: "", unit: "W"});
              ForceSetState("Solarpower.Huawei.Meter.ReactivePower",              GetI32(globalDataBuffer[powerMeterID], 37115) / 1,      {name: "", unit: "Var"});
              ForceSetState("Solarpower.Huawei.Meter.PowerFactor",                GetI16(globalDataBuffer[powerMeterID], 37117) / 1000,   {name: "", unit: ""});
              ForceSetState("Solarpower.Huawei.Meter.GridFrequency",              GetI16(globalDataBuffer[powerMeterID], 37118) / 100,    {name: "", unit: "Hz"});
              ForceSetState("Solarpower.Huawei.Meter.PositiveActiveEnergy",       GetI32(globalDataBuffer[powerMeterID], 37119) / 100,    {name: "", unit: "kWh"});
              ForceSetState("Solarpower.Huawei.Meter.ReverseActiveEnergy",        GetI32(globalDataBuffer[powerMeterID], 37121) / 100,    {name: "", unit: "kWh"});
              ForceSetState("Solarpower.Huawei.Meter.AccumulatedReactivePower",   GetI32(globalDataBuffer[powerMeterID], 37123) / 100,    {name: "", unit: "kVarh"});
              //ForceSetState("Solarpower.Huawei.Meter.MeterType",                  GetU16(globalDataBuffer[powerMeterID], 37125),          {name: "", unit: ""});
              ForceSetState("Solarpower.Huawei.Meter.VoltageL1-L2",               GetI32(globalDataBuffer[powerMeterID], 37126) / 10,     {name: "", unit: "V"});
              ForceSetState("Solarpower.Huawei.Meter.VoltageL2-L3",               GetI32(globalDataBuffer[powerMeterID], 37128) / 10,     {name: "", unit: "V"});
              ForceSetState("Solarpower.Huawei.Meter.VoltageL3-L1",               GetI32(globalDataBuffer[powerMeterID], 37130) / 10,     {name: "", unit: "V"});
              ForceSetState("Solarpower.Huawei.Meter.ActivePowerL1",              GetI32(globalDataBuffer[powerMeterID], 37132) / 1,      {name: "", unit: "W"});
              ForceSetState("Solarpower.Huawei.Meter.ActivePowerL2",              GetI32(globalDataBuffer[powerMeterID], 37134) / 1,      {name: "", unit: "W"});
              ForceSetState("Solarpower.Huawei.Meter.ActivePowerL3",              GetI32(globalDataBuffer[powerMeterID], 37136) / 1,      {name: "", unit: "W"});
              //ForceSetState("Solarpower.Huawei.Meter.MeterModel",                 GetU16(globalDataBuffer[powerMeterID], 37138),          {name: "", unit: ""});
          }
          
          function ProcessInverterStatus(id) {
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".State1",                   GetU16(globalDataBuffer[id-1], 32000),          {name: "", unit: ""});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".State2",                   GetU16(globalDataBuffer[id-1], 32002),          {name: "", unit: ""});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".State3",                   GetU32(globalDataBuffer[id-1], 32003),          {name: "", unit: ""});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".Alarm1",                   GetU16(globalDataBuffer[id-1], 32008),          {name: "", unit: ""});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".Alarm2",                   GetU16(globalDataBuffer[id-1], 32009),          {name: "", unit: ""});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".Alarm3",                   GetU16(globalDataBuffer[id-1], 32010),          {name: "", unit: ""});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.1_Voltage",         GetI16(globalDataBuffer[id-1], 32016) / 10,     {name: "", unit: "V"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.1_Current",         GetI16(globalDataBuffer[id-1], 32017) / 100,    {name: "", unit: "A"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.2_Voltage",         GetI16(globalDataBuffer[id-1], 32018) / 10,     {name: "", unit: "V"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.2_Current",         GetI16(globalDataBuffer[id-1], 32019) / 100,    {name: "", unit: "A"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.3_Voltage",         GetI16(globalDataBuffer[id-1], 32020) / 10,     {name: "", unit: "V"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.3_Current",         GetI16(globalDataBuffer[id-1], 32021) / 100,    {name: "", unit: "A"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.4_Voltage",         GetI16(globalDataBuffer[id-1], 32022) / 10,     {name: "", unit: "V"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.4_Current",         GetI16(globalDataBuffer[id-1], 32023) / 100,    {name: "", unit: "A"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".InputPower",               GetI32(globalDataBuffer[id-1], 32064) / 1000,   {name: "", unit: "kW"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1-L2_Voltage",       GetU16(globalDataBuffer[id-1], 32066) / 10,     {name: "", unit: "V"});      
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2-L3_Voltage",       GetU16(globalDataBuffer[id-1], 32067) / 10,     {name: "", unit: "V"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3-L1_Voltage",       GetU16(globalDataBuffer[id-1], 32068) / 10,     {name: "", unit: "V"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1_Voltage",          GetU16(globalDataBuffer[id-1], 32069) / 10,     {name: "", unit: "V"});                              
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2_Voltage",          GetU16(globalDataBuffer[id-1], 32070) / 10,     {name: "", unit: "V"});                                                  
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3_Voltage",          GetU16(globalDataBuffer[id-1], 32071) / 10,     {name: "", unit: "V"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1_Current",          GetI32(globalDataBuffer[id-1], 32072) / 1000,   {name: "", unit: "A"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2_Current",          GetI32(globalDataBuffer[id-1], 32074) / 1000,   {name: "", unit: "A"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3_Current",          GetI32(globalDataBuffer[id-1], 32076) / 1000,   {name: "", unit: "A"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".PeakActivePowerDay",       GetI32(globalDataBuffer[id-1], 32078) / 1000,   {name: "", unit: "kW"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".ActivePower",              GetI32(globalDataBuffer[id-1], 32080) / 1000,   {name: "", unit: "kW"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".ReactivePower",            GetI32(globalDataBuffer[id-1], 32082) / 1000,   {name: "", unit: "kVar"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".PowerFactor",              GetI16(globalDataBuffer[id-1], 32084) / 1000,   {name: "", unit: ""});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".GridFrequency",            GetU16(globalDataBuffer[id-1], 32085) / 100,    {name: "", unit: "Hz"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".Efficiency",               GetU16(globalDataBuffer[id-1], 32086) / 100,    {name: "", unit: "%"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".InternalTemperature",      GetI16(globalDataBuffer[id-1], 32087) / 10,     {name: "", unit: "°C"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".InsulationResistance",     GetU16(globalDataBuffer[id-1], 32088) / 1000,   {name: "", unit: "MOhm"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".DeviceStatus",             GetU16(globalDataBuffer[id-1], 32089),          {name: "", unit: ""});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".FaultCode",                GetU16(globalDataBuffer[id-1], 32090),          {name: "", unit: ""});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".StartupTime",              String(new Date(GetU32(globalDataBuffer[id-1], 32091)*1000)),          {name: "", unit: ""});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".ShutdownTime",             String(new Date(GetU32(globalDataBuffer[id-1], 32093)*1000)),          {name: "", unit: ""});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".AccomulatedEnergyYield",   GetU32(globalDataBuffer[id-1], 32106),          {name: "", unit: "kWh"});
              ForceSetState("Solarpower.Huawei.Inverter." + id + ".DailyEnergyYield",         GetU32(globalDataBuffer[id-1], 32114),          {name: "", unit: "kWh"});
          }
          
          function ReadRegisterSpace(id, address, length) {
              client.setID(modbusID[id-1]);
              client.readHoldingRegisters(address, length, function(err, data) {
                  if (err) {
                      console.warn("Error received reading address " + address + " from id: " + modbusID[id-1] + " with error: " + modbusErrorMessages[err.modbusCode]); 
                  }
                  else
                  {   
                      console.debug("Read data from id/address " + modbusID[id-1] + "/" + address + "\nData is: " + data.data);
                      for(var i = 0; i < length; i++)  {
                          globalDataBuffer[id-1][address+i] = data.data[i];
                      } 
                  }
              });
          }
          
          function ProcessData() {
              //console.log("Processing new data...");
              for(var i = 1; i <= modbusID.length; i++) {
                  //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 (!client.isOpen){
                      ConnectModbus();
                  }
                  if(triggerprocessing == 1) {
                  triggerprocessing = 0;
                  ProcessData();        
                  }      
             
              //console.log("Triggering read of inverter " + currentinverter + " at address " + registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][0] + " with length " +  registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][1]);
              ReadRegisterSpace(currentinverter, registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][0], registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][1]); 
              registerSpacesToReadContinuouslyPtr++;               
              if(registerSpacesToReadContinuouslyPtr >= registerSpacesToReadContinuously.length) {
                  registerSpacesToReadContinuouslyPtr = 0;
                  currentinverter++
                  if(currentinverter > modbusID.length){
                      currentinverter = 1;  
                      triggerprocessing = 1;                    
                  }
              }     
          }, 3000);
          

          Super Danke.
          Hab eh keine Batterie. Werde es gleich testen.
          Gruß Jürgen

          Guten Morgen soweit läuft es mal, aber kann es sein, dass bei
          Solarpower Huawei Inverter 1 AccomulatedEnergyYield und
          Solarpower.Huawei.Inverter.1.DailyEnergyYield
          das Komma fehlt, denn der Tägliche Ertrag wäre schön aber nicht war :-)
          kann man das irgend wie ändern?

          Diese Werte habe ich mir noch gar nicht angeschaut. Hier fehlt im Script (Zeilen 193 und 194) tatsächlich der Multiplikator.

          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"});
          

          Zu deinem Hauptproblem: Ich bin mir aktuell nicht ganz sicher, ob die Wiederverbindung im Script korrekt funktioniert. Ich habe bisher nur das Netzwerkkabel des ioBrokers für 10 Sekunden gezogen und das machte ihm nichts aus. Aber die Meldung, die bei einer neuen Verbindung geloggt werden sollten, kamen nicht. Daher kann es gut sein, dass client.isOpen vielleicht gar nicht so funktioniert wie erhofft.

          J 1 Antwort Letzte Antwort
          0
          • Alex WarkentinA Alex Warkentin

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

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

            @alex-warkentin sagte in Huawei Sun2000 & ioBroker via JS script funktioniert:

            @juggi1962 Poste mal die Logs, wenn der Fehler auftritt

            Hier ist das Script, was ich für mich angepasst habe. Achtung! Ich habe die Batterie und andere für mich uninteressante Sachen rausgeschmissen und die Namen von Variablen und Funktionen angepasst. Für die Neuverbindung nach Verbindungsabbruch brauchst du die Zeilen 18 - 27 , 107-122 und 235 -237

            // License: Beerware! Do what ever you like with this, but I'm not liable for anything that you do with it.
            // If you like this code, feel free to buy me a beer ...
            // Have fun with it! der Kachel
            // @ts-ignore
            var modbusRTU = require("modbus-serial");
            var client = new modbusRTU();
            
            var modbusErrorMessages = [
                "Unknown error",
                "Illegal function (device does not support this read/write function)",
                "Illegal data address (register not supported by device)",
                "Illegal data value (value cannot be written to this register)",
                "Slave device failure (device reports internal error)",
                "Acknowledge (requested data will be available later)",
                "Slave device busy (retry request again later)"
            ];
            
            // Enter your inverter modbus IP and port here:
            const modbusHost = "000.000.000.000";
            const modbusPort = 502;
            // Enter the Modbus-IDs of your Sun2000 inverters here:
            const modbusID = [1];
            // On which Modbus-ID can we reach the power meter? (via Sun2000!)
            const powerMeterID = 0;
            
            // Connect to modbus client
            ConnectModbus();
            
            // These register spaces need to be read:
            const registerSpacesToReadContinuously = [[37100, 114], [32000, 116]];
            var registerSpacesToReadContinuouslyPtr = 0;
            
            var globalDataBuffer = new Array(1);
            globalDataBuffer[0] = new Array(50000); // not optimized....
            
            // ---------------------------------------------------------------
            // Some helper functions:
            function ReadUnsignedInt16(array) {
                var value = array[0];    
                return value;
            }
            
            function ReadUnsignedInt32(array) {
                var value = array[0] * 256 * 256 + array[1];    
                return value;
            }
            
            function ReadSignedInt16(array) {
                var value = 0;
                if (array[0] > 32767)
                    value = array[0] - 65535; 
                else
                    value = array[0];
            
                return value;
            }
            function ReadSignedInt32(array) {
                var value = 0;
                for (var i = 0; i < 2; i++) {
                    value = (value << 16) | array[i];
                }
                return value;
            }
            function GetU16(dataarray, index) {
                var value = ReadUnsignedInt16(dataarray.slice(index, index+1));
                return value;
            }
            
            function GetU32(dataarray, index) {
                var value = ReadUnsignedInt32(dataarray.slice(index, index+2));
                return value;
            }
            
            function GetI16(dataarray, index) {
                var value = ReadSignedInt16(dataarray.slice(index, index+1));
                return value;
            }
            
            function GetI32(dataarray, index) {
                var value = ReadSignedInt32(dataarray.slice(index, index+2));
                return value;
            }
            
            function GetString(dataarray, index, length) {
                var shortarray = dataarray.slice(index, index+length);
                var bytearray = [];
                for(var i = 0; i < length; i++) {
                    bytearray.push(dataarray[index+i] >> 8);
                    bytearray.push(dataarray[index+i] & 0xff);
                }       
                var value =  String.fromCharCode.apply(null, bytearray);    
                return value;
            }
            
            function GetZeroTerminatedString(dataarray, index, length) {
                var shortarray = dataarray.slice(index, index+length);
                var bytearray = [];
                for(var i = 0; i < length; i++) {
                    bytearray.push(dataarray[index+i] >> 8);
                    bytearray.push(dataarray[index+i] & 0xff);
                }       
                var value =  String.fromCharCode.apply(null, bytearray);    
                var value2 = new String(value).trim();
                return value2;
            }
            
            // Funktion zum Herstellen einer Modbus-Verbindung
            function ConnectModbus() {
                console.log("Init connection to: " + modbusHost +":" + modbusPort);
                // set requests parameters
                client.setTimeout (10000);
                // try to connect
                client.connectTCP (modbusHost, { port: modbusPort })
                    .then(function()
                    {
                        console.log("Connected, wait for reading...");
                    })
                    .catch(function(e)
                    {
                        console.log(e);
                    });
            }
            
            // Funktion zum Anlegen und Beschreiben eines Datenpunkts
            function ForceSetState(objectname, value, options) {
                if(!existsState("javascript.0." + objectname))      createState(objectname, value, options);
                else                                                setState(objectname, value);
            }  
            // ---------------------------------------------------------------
            // Functions to map registers into ioBreaker objects:
            function ProcessPowerMeterStatus() {       
                ForceSetState("Solarpower.Huawei.Meter.Status",                     GetU16(globalDataBuffer[powerMeterID], 37100),          {name: "", unit: ""});
                ForceSetState("Solarpower.Huawei.Meter.VoltageL1",                  GetI32(globalDataBuffer[powerMeterID], 37101) / 10,     {name: "", unit: "V"});
                ForceSetState("Solarpower.Huawei.Meter.VoltageL2",                  GetI32(globalDataBuffer[powerMeterID], 37103) / 10,     {name: "", unit: "V"});
                ForceSetState("Solarpower.Huawei.Meter.VoltageL3",                  GetI32(globalDataBuffer[powerMeterID], 37105) / 10,     {name: "", unit: "V"});
                ForceSetState("Solarpower.Huawei.Meter.CurrentL1",                  GetI32(globalDataBuffer[powerMeterID], 37107) / 100,    {name: "", unit: "A"});
                ForceSetState("Solarpower.Huawei.Meter.CurrentL2",                  GetI32(globalDataBuffer[powerMeterID], 37109) / 100,    {name: "", unit: "A"});
                ForceSetState("Solarpower.Huawei.Meter.CurrentL3",                  GetI32(globalDataBuffer[powerMeterID], 37111) / 100,    {name: "", unit: "A"});
                ForceSetState("Solarpower.Huawei.Meter.ActivePower",                GetI32(globalDataBuffer[powerMeterID], 37113) / 1,      {name: "", unit: "W"});
                ForceSetState("Solarpower.Huawei.Meter.ReactivePower",              GetI32(globalDataBuffer[powerMeterID], 37115) / 1,      {name: "", unit: "Var"});
                ForceSetState("Solarpower.Huawei.Meter.PowerFactor",                GetI16(globalDataBuffer[powerMeterID], 37117) / 1000,   {name: "", unit: ""});
                ForceSetState("Solarpower.Huawei.Meter.GridFrequency",              GetI16(globalDataBuffer[powerMeterID], 37118) / 100,    {name: "", unit: "Hz"});
                ForceSetState("Solarpower.Huawei.Meter.PositiveActiveEnergy",       GetI32(globalDataBuffer[powerMeterID], 37119) / 100,    {name: "", unit: "kWh"});
                ForceSetState("Solarpower.Huawei.Meter.ReverseActiveEnergy",        GetI32(globalDataBuffer[powerMeterID], 37121) / 100,    {name: "", unit: "kWh"});
                ForceSetState("Solarpower.Huawei.Meter.AccumulatedReactivePower",   GetI32(globalDataBuffer[powerMeterID], 37123) / 100,    {name: "", unit: "kVarh"});
                //ForceSetState("Solarpower.Huawei.Meter.MeterType",                  GetU16(globalDataBuffer[powerMeterID], 37125),          {name: "", unit: ""});
                ForceSetState("Solarpower.Huawei.Meter.VoltageL1-L2",               GetI32(globalDataBuffer[powerMeterID], 37126) / 10,     {name: "", unit: "V"});
                ForceSetState("Solarpower.Huawei.Meter.VoltageL2-L3",               GetI32(globalDataBuffer[powerMeterID], 37128) / 10,     {name: "", unit: "V"});
                ForceSetState("Solarpower.Huawei.Meter.VoltageL3-L1",               GetI32(globalDataBuffer[powerMeterID], 37130) / 10,     {name: "", unit: "V"});
                ForceSetState("Solarpower.Huawei.Meter.ActivePowerL1",              GetI32(globalDataBuffer[powerMeterID], 37132) / 1,      {name: "", unit: "W"});
                ForceSetState("Solarpower.Huawei.Meter.ActivePowerL2",              GetI32(globalDataBuffer[powerMeterID], 37134) / 1,      {name: "", unit: "W"});
                ForceSetState("Solarpower.Huawei.Meter.ActivePowerL3",              GetI32(globalDataBuffer[powerMeterID], 37136) / 1,      {name: "", unit: "W"});
                //ForceSetState("Solarpower.Huawei.Meter.MeterModel",                 GetU16(globalDataBuffer[powerMeterID], 37138),          {name: "", unit: ""});
            }
            
            function ProcessInverterStatus(id) {
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".State1",                   GetU16(globalDataBuffer[id-1], 32000),          {name: "", unit: ""});
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".State2",                   GetU16(globalDataBuffer[id-1], 32002),          {name: "", unit: ""});
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".State3",                   GetU32(globalDataBuffer[id-1], 32003),          {name: "", unit: ""});
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".Alarm1",                   GetU16(globalDataBuffer[id-1], 32008),          {name: "", unit: ""});
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".Alarm2",                   GetU16(globalDataBuffer[id-1], 32009),          {name: "", unit: ""});
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".Alarm3",                   GetU16(globalDataBuffer[id-1], 32010),          {name: "", unit: ""});
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.1_Voltage",         GetI16(globalDataBuffer[id-1], 32016) / 10,     {name: "", unit: "V"});
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.1_Current",         GetI16(globalDataBuffer[id-1], 32017) / 100,    {name: "", unit: "A"});
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.2_Voltage",         GetI16(globalDataBuffer[id-1], 32018) / 10,     {name: "", unit: "V"});
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.2_Current",         GetI16(globalDataBuffer[id-1], 32019) / 100,    {name: "", unit: "A"});
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.3_Voltage",         GetI16(globalDataBuffer[id-1], 32020) / 10,     {name: "", unit: "V"});
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.3_Current",         GetI16(globalDataBuffer[id-1], 32021) / 100,    {name: "", unit: "A"});
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.4_Voltage",         GetI16(globalDataBuffer[id-1], 32022) / 10,     {name: "", unit: "V"});
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.4_Current",         GetI16(globalDataBuffer[id-1], 32023) / 100,    {name: "", unit: "A"});
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".InputPower",               GetI32(globalDataBuffer[id-1], 32064) / 1000,   {name: "", unit: "kW"});
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1-L2_Voltage",       GetU16(globalDataBuffer[id-1], 32066) / 10,     {name: "", unit: "V"});      
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2-L3_Voltage",       GetU16(globalDataBuffer[id-1], 32067) / 10,     {name: "", unit: "V"});
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3-L1_Voltage",       GetU16(globalDataBuffer[id-1], 32068) / 10,     {name: "", unit: "V"});
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1_Voltage",          GetU16(globalDataBuffer[id-1], 32069) / 10,     {name: "", unit: "V"});                              
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2_Voltage",          GetU16(globalDataBuffer[id-1], 32070) / 10,     {name: "", unit: "V"});                                                  
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3_Voltage",          GetU16(globalDataBuffer[id-1], 32071) / 10,     {name: "", unit: "V"});
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1_Current",          GetI32(globalDataBuffer[id-1], 32072) / 1000,   {name: "", unit: "A"});
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2_Current",          GetI32(globalDataBuffer[id-1], 32074) / 1000,   {name: "", unit: "A"});
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3_Current",          GetI32(globalDataBuffer[id-1], 32076) / 1000,   {name: "", unit: "A"});
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".PeakActivePowerDay",       GetI32(globalDataBuffer[id-1], 32078) / 1000,   {name: "", unit: "kW"});
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".ActivePower",              GetI32(globalDataBuffer[id-1], 32080) / 1000,   {name: "", unit: "kW"});
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".ReactivePower",            GetI32(globalDataBuffer[id-1], 32082) / 1000,   {name: "", unit: "kVar"});
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".PowerFactor",              GetI16(globalDataBuffer[id-1], 32084) / 1000,   {name: "", unit: ""});
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".GridFrequency",            GetU16(globalDataBuffer[id-1], 32085) / 100,    {name: "", unit: "Hz"});
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".Efficiency",               GetU16(globalDataBuffer[id-1], 32086) / 100,    {name: "", unit: "%"});
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".InternalTemperature",      GetI16(globalDataBuffer[id-1], 32087) / 10,     {name: "", unit: "°C"});
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".InsulationResistance",     GetU16(globalDataBuffer[id-1], 32088) / 1000,   {name: "", unit: "MOhm"});
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".DeviceStatus",             GetU16(globalDataBuffer[id-1], 32089),          {name: "", unit: ""});
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".FaultCode",                GetU16(globalDataBuffer[id-1], 32090),          {name: "", unit: ""});
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".StartupTime",              String(new Date(GetU32(globalDataBuffer[id-1], 32091)*1000)),          {name: "", unit: ""});
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".ShutdownTime",             String(new Date(GetU32(globalDataBuffer[id-1], 32093)*1000)),          {name: "", unit: ""});
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".AccomulatedEnergyYield",   GetU32(globalDataBuffer[id-1], 32106),          {name: "", unit: "kWh"});
                ForceSetState("Solarpower.Huawei.Inverter." + id + ".DailyEnergyYield",         GetU32(globalDataBuffer[id-1], 32114),          {name: "", unit: "kWh"});
            }
            
            function ReadRegisterSpace(id, address, length) {
                client.setID(modbusID[id-1]);
                client.readHoldingRegisters(address, length, function(err, data) {
                    if (err) {
                        console.warn("Error received reading address " + address + " from id: " + modbusID[id-1] + " with error: " + modbusErrorMessages[err.modbusCode]); 
                    }
                    else
                    {   
                        console.debug("Read data from id/address " + modbusID[id-1] + "/" + address + "\nData is: " + data.data);
                        for(var i = 0; i < length; i++)  {
                            globalDataBuffer[id-1][address+i] = data.data[i];
                        } 
                    }
                });
            }
            
            function ProcessData() {
                //console.log("Processing new data...");
                for(var i = 1; i <= modbusID.length; i++) {
                    //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 (!client.isOpen){
                        ConnectModbus();
                    }
                    if(triggerprocessing == 1) {
                    triggerprocessing = 0;
                    ProcessData();        
                    }      
               
                //console.log("Triggering read of inverter " + currentinverter + " at address " + registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][0] + " with length " +  registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][1]);
                ReadRegisterSpace(currentinverter, registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][0], registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][1]); 
                registerSpacesToReadContinuouslyPtr++;               
                if(registerSpacesToReadContinuouslyPtr >= registerSpacesToReadContinuously.length) {
                    registerSpacesToReadContinuouslyPtr = 0;
                    currentinverter++
                    if(currentinverter > modbusID.length){
                        currentinverter = 1;  
                        triggerprocessing = 1;                    
                    }
                }     
            }, 3000);
            

            Super Danke.
            Hab eh keine Batterie. Werde es gleich testen.
            Gruß Jürgen

            Guten Morgen soweit läuft es mal, aber kann es sein, dass bei
            Solarpower Huawei Inverter 1 AccomulatedEnergyYield und
            Solarpower.Huawei.Inverter.1.DailyEnergyYield
            das Komma fehlt, denn der Tägliche Ertrag wäre schön aber nicht war :-)
            kann man das irgend wie ändern?

            Diese Werte habe ich mir noch gar nicht angeschaut. Hier fehlt im Script (Zeilen 193 und 194) tatsächlich der Multiplikator.

            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"});
            

            Zu deinem Hauptproblem: Ich bin mir aktuell nicht ganz sicher, ob die Wiederverbindung im Script korrekt funktioniert. Ich habe bisher nur das Netzwerkkabel des ioBrokers für 10 Sekunden gezogen und das machte ihm nichts aus. Aber die Meldung, die bei einer neuen Verbindung geloggt werden sollten, kamen nicht. Daher kann es gut sein, dass client.isOpen vielleicht gar nicht so funktioniert wie erhofft.

            J Offline
            J Offline
            juggi1962
            schrieb am zuletzt editiert von
            #71

            @alex-warkentin
            Danke für deine Bemühungen und für die Richtigstellung der Multiplikatoren :+1:
            Kannst du das mit dem client.isOpen vielleicht testen und verbessern, das wäre echt super.
            Ich kenne mich leider mit JS gar nicht aus.
            Danke im Voraus, Gruß Jürgen

            Alex WarkentinA 2 Antworten Letzte Antwort
            0
            • J juggi1962

              @alex-warkentin
              Danke für deine Bemühungen und für die Richtigstellung der Multiplikatoren :+1:
              Kannst du das mit dem client.isOpen vielleicht testen und verbessern, das wäre echt super.
              Ich kenne mich leider mit JS gar nicht aus.
              Danke im Voraus, Gruß Jürgen

              Alex WarkentinA Offline
              Alex WarkentinA Offline
              Alex Warkentin
              schrieb am zuletzt editiert von
              #72

              @juggi1962
              Ich bin aktuell beruflich ziemlich eingespannt, aber mich interessiert das auch. Ich werde das bei Gelegenheit mal genauer anschauen.

              1 Antwort Letzte Antwort
              0
              • J juggi1962

                @alex-warkentin
                Danke für deine Bemühungen und für die Richtigstellung der Multiplikatoren :+1:
                Kannst du das mit dem client.isOpen vielleicht testen und verbessern, das wäre echt super.
                Ich kenne mich leider mit JS gar nicht aus.
                Danke im Voraus, Gruß Jürgen

                Alex WarkentinA Offline
                Alex WarkentinA Offline
                Alex Warkentin
                schrieb am zuletzt editiert von
                #73

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

                @alex-warkentin
                Danke für deine Bemühungen und für die Richtigstellung der Multiplikatoren :+1:
                Kannst du das mit dem client.isOpen vielleicht testen und verbessern, das wäre echt super.
                Ich kenne mich leider mit JS gar nicht aus.
                Danke im Voraus, Gruß Jürgen

                isOpen soll laut Doku eigentlich ein Funktion an. Wird aber als solche nicht zur Verfügung gestellt und ist sonst auch immer true. Probiere bitte dein Script mit folgendem Snippet ab Zeile 197 zu überschreiben. Nun frage ich den ErrorCode nach null ab und reconnecte dann.

                function ReadRegisterSpace(id, address, length) {
                    client.setID(modbusID[id-1]);
                    client.readHoldingRegisters(address, length, function(err, data) {
                        if (err) {
                            if (err.modbusCode == null) {
                                console.warn("Lost connection to client. Trying to reconnect...");
                                ConnectModbus();
                            } 
                            else console.warn("Error received reading address " + address + " from id: " + modbusID[id-1] + " with error: " + modbusErrorMessages[err.modbusCode]); 
                        }
                        else
                        {   
                            console.debug("Read data from id/address " + modbusID[id-1] + "/" + address + "\nData is: " + data.data);
                            for(var i = 0; i < length; i++)  {
                                globalDataBuffer[id-1][address+i] = data.data[i];
                            } 
                        }
                    });
                }
                
                function ProcessData() {
                    //console.log("Processing new data...");
                    for(var i = 1; i <= modbusID.length; i++) {
                        ProcessInverterStatus(i);
                    }    
                    ProcessPowerMeterStatus();
                    //console.log("Processing done!");
                }
                
                
                // -------------------------------------------------------------------
                // This is the main function triggering a  read via modbus-tcp every two seconds.
                // Processing of data is triggered as soon as one complete set of registers is copied.
                var triggerprocessing = 0; 
                var currentinverter = 1;
                
                
                setInterval(function() {
                    if(triggerprocessing == 1) {
                        triggerprocessing = 0;
                        ProcessData();        
                    }      
                   
                    //console.log("Triggering read of inverter " + currentinverter + " at address " + registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][0] + " with length " +  registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][1]);
                    ReadRegisterSpace(currentinverter, registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][0], registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][1]); 
                    registerSpacesToReadContinuouslyPtr++;               
                    if(registerSpacesToReadContinuouslyPtr >= registerSpacesToReadContinuously.length) {
                        registerSpacesToReadContinuouslyPtr = 0;
                        currentinverter++
                        if(currentinverter > modbusID.length){
                            currentinverter = 1;  
                            triggerprocessing = 1;                    
                        }
                    }     
                }, 3000);
                

                Du solltest aber trotzdem versuchen zu ergründen, warum die ständigen Verbindungsabbrüche kommen. Falls möglich vielleicht das Ethernet-Kabel tauschen.

                J 1 Antwort Letzte Antwort
                0
                • Alex WarkentinA Alex Warkentin

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

                  @alex-warkentin
                  Danke für deine Bemühungen und für die Richtigstellung der Multiplikatoren :+1:
                  Kannst du das mit dem client.isOpen vielleicht testen und verbessern, das wäre echt super.
                  Ich kenne mich leider mit JS gar nicht aus.
                  Danke im Voraus, Gruß Jürgen

                  isOpen soll laut Doku eigentlich ein Funktion an. Wird aber als solche nicht zur Verfügung gestellt und ist sonst auch immer true. Probiere bitte dein Script mit folgendem Snippet ab Zeile 197 zu überschreiben. Nun frage ich den ErrorCode nach null ab und reconnecte dann.

                  function ReadRegisterSpace(id, address, length) {
                      client.setID(modbusID[id-1]);
                      client.readHoldingRegisters(address, length, function(err, data) {
                          if (err) {
                              if (err.modbusCode == null) {
                                  console.warn("Lost connection to client. Trying to reconnect...");
                                  ConnectModbus();
                              } 
                              else console.warn("Error received reading address " + address + " from id: " + modbusID[id-1] + " with error: " + modbusErrorMessages[err.modbusCode]); 
                          }
                          else
                          {   
                              console.debug("Read data from id/address " + modbusID[id-1] + "/" + address + "\nData is: " + data.data);
                              for(var i = 0; i < length; i++)  {
                                  globalDataBuffer[id-1][address+i] = data.data[i];
                              } 
                          }
                      });
                  }
                  
                  function ProcessData() {
                      //console.log("Processing new data...");
                      for(var i = 1; i <= modbusID.length; i++) {
                          ProcessInverterStatus(i);
                      }    
                      ProcessPowerMeterStatus();
                      //console.log("Processing done!");
                  }
                  
                  
                  // -------------------------------------------------------------------
                  // This is the main function triggering a  read via modbus-tcp every two seconds.
                  // Processing of data is triggered as soon as one complete set of registers is copied.
                  var triggerprocessing = 0; 
                  var currentinverter = 1;
                  
                  
                  setInterval(function() {
                      if(triggerprocessing == 1) {
                          triggerprocessing = 0;
                          ProcessData();        
                      }      
                     
                      //console.log("Triggering read of inverter " + currentinverter + " at address " + registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][0] + " with length " +  registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][1]);
                      ReadRegisterSpace(currentinverter, registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][0], registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][1]); 
                      registerSpacesToReadContinuouslyPtr++;               
                      if(registerSpacesToReadContinuouslyPtr >= registerSpacesToReadContinuously.length) {
                          registerSpacesToReadContinuouslyPtr = 0;
                          currentinverter++
                          if(currentinverter > modbusID.length){
                              currentinverter = 1;  
                              triggerprocessing = 1;                    
                          }
                      }     
                  }, 3000);
                  

                  Du solltest aber trotzdem versuchen zu ergründen, warum die ständigen Verbindungsabbrüche kommen. Falls möglich vielleicht das Ethernet-Kabel tauschen.

                  J Offline
                  J Offline
                  juggi1962
                  schrieb am zuletzt editiert von
                  #74

                  @alex-warkentin
                  Hallo und noch mal danke für deine Bemühungen.
                  Leider gibt es immer noch die selben Fehlermeldungen, bis jetzt immer mal einzelne,
                  mal schauen ob es wieder dauerhaft wird.
                  Ich habe jetzt für eine Stunde einen Ping laufen lassen und hatte beim Ping keine Abbrüche aber im Skript 10 Fehler.
                  Lankabel wurde vorher gegen ein neues getauscht.
                  Hmmmmm komisch :disappointed:

                  Alex WarkentinA 1 Antwort Letzte Antwort
                  0
                  • J juggi1962

                    @alex-warkentin
                    Hallo und noch mal danke für deine Bemühungen.
                    Leider gibt es immer noch die selben Fehlermeldungen, bis jetzt immer mal einzelne,
                    mal schauen ob es wieder dauerhaft wird.
                    Ich habe jetzt für eine Stunde einen Ping laufen lassen und hatte beim Ping keine Abbrüche aber im Skript 10 Fehler.
                    Lankabel wurde vorher gegen ein neues getauscht.
                    Hmmmmm komisch :disappointed:

                    Alex WarkentinA Offline
                    Alex WarkentinA Offline
                    Alex Warkentin
                    schrieb am zuletzt editiert von
                    #75

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

                    @alex-warkentin
                    Hallo und noch mal danke für deine Bemühungen.
                    Leider gibt es immer noch die selben Fehlermeldungen, bis jetzt immer mal einzelne,
                    mal schauen ob es wieder dauerhaft wird.
                    Ich habe jetzt für eine Stunde einen Ping laufen lassen und hatte beim Ping keine Abbrüche aber im Skript 10 Fehler.
                    Lankabel wurde vorher gegen ein neues getauscht.
                    Hmmmmm komisch :disappointed:

                    Naja, jetzt müsste die Fehlermeldung "Lost connection...." lauten. Und danach die Verbindung neu aufgebaut werden. Dann funktioniert das Script erwartungsgemäß.

                    Wie ist es denn mit deiner ioBroker Hardware? Kann es sein, dass hier die Abbrüche stattfinden?

                    J 1 Antwort Letzte Antwort
                    0
                    • Alex WarkentinA Alex Warkentin

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

                      @alex-warkentin
                      Hallo und noch mal danke für deine Bemühungen.
                      Leider gibt es immer noch die selben Fehlermeldungen, bis jetzt immer mal einzelne,
                      mal schauen ob es wieder dauerhaft wird.
                      Ich habe jetzt für eine Stunde einen Ping laufen lassen und hatte beim Ping keine Abbrüche aber im Skript 10 Fehler.
                      Lankabel wurde vorher gegen ein neues getauscht.
                      Hmmmmm komisch :disappointed:

                      Naja, jetzt müsste die Fehlermeldung "Lost connection...." lauten. Und danach die Verbindung neu aufgebaut werden. Dann funktioniert das Script erwartungsgemäß.

                      Wie ist es denn mit deiner ioBroker Hardware? Kann es sein, dass hier die Abbrüche stattfinden?

                      J Offline
                      J Offline
                      juggi1962
                      schrieb am zuletzt editiert von
                      #76

                      @alex-warkentin
                      Die Fehlermeldung Lost connection... kommt nur wenn ich das LAN Kabel ziehe.
                      Mein Raspberry und IoBroker laufen ohne Aussetzer.
                      Diese Fehlermeldungen auch mit 32000 kommen immer mal wieder, hören aber dazwischen wieder auf.
                      Gruß Jürgen.

                      Error received reading address 37100 from id: 1 with error: undefined
                      
                      Alex WarkentinA 1 Antwort Letzte Antwort
                      0
                      • J juggi1962

                        @alex-warkentin
                        Die Fehlermeldung Lost connection... kommt nur wenn ich das LAN Kabel ziehe.
                        Mein Raspberry und IoBroker laufen ohne Aussetzer.
                        Diese Fehlermeldungen auch mit 32000 kommen immer mal wieder, hören aber dazwischen wieder auf.
                        Gruß Jürgen.

                        Error received reading address 37100 from id: 1 with error: undefined
                        
                        Alex WarkentinA Offline
                        Alex WarkentinA Offline
                        Alex Warkentin
                        schrieb am zuletzt editiert von
                        #77

                        @juggi1962
                        Modbus hat einige Fehlercodes. Nur einige davon werden von dem Script auch in Klartext übersetzt. Ich weiß auch nicht, ob das Plugin was wir da verwenden, die ganzen Fehlercodes behandeln kann. Vielleicht hast du ja gar keine Verbindungsabbrüche, sondern der Errorcode liegt einfach außerhalb des Arrays der Messages.

                        Gehe mal zu der Zeile wo die Warnung generiert wird und dort ganz ans Ende und lösche modbuserrormessages und die eckigen Klammern um den errorcode, sodass nicht die oben definierten Messages, sondern der Fehlercode selbst dargestellt wird. Vielleicht kommt da ja ne Meldung, die man besser analysieren kann.

                        J 1 Antwort Letzte Antwort
                        0
                        • Alex WarkentinA Alex Warkentin

                          @juggi1962
                          Modbus hat einige Fehlercodes. Nur einige davon werden von dem Script auch in Klartext übersetzt. Ich weiß auch nicht, ob das Plugin was wir da verwenden, die ganzen Fehlercodes behandeln kann. Vielleicht hast du ja gar keine Verbindungsabbrüche, sondern der Errorcode liegt einfach außerhalb des Arrays der Messages.

                          Gehe mal zu der Zeile wo die Warnung generiert wird und dort ganz ans Ende und lösche modbuserrormessages und die eckigen Klammern um den errorcode, sodass nicht die oben definierten Messages, sondern der Fehlercode selbst dargestellt wird. Vielleicht kommt da ja ne Meldung, die man besser analysieren kann.

                          J Offline
                          J Offline
                          juggi1962
                          schrieb am zuletzt editiert von juggi1962
                          #78

                          @alex-warkentin
                          Danke, hab das gerade gemacht und werde es heute beobachten.
                          Wenn ich weiterhin lästig sein darf geb ich dir falls was daher kommt Bescheid.
                          Gruß Jürgen.

                          So nun sind die ersten Fehlermeldungen gekommen und zwar

                          Error received reading address 37100 from id: 1 with error: 6
                          Error received reading address 32000 from id: 1 with error: 6
                          

                          Gruß Jürgen

                          B Alex WarkentinA 2 Antworten Letzte Antwort
                          0
                          • J juggi1962

                            @alex-warkentin
                            Danke, hab das gerade gemacht und werde es heute beobachten.
                            Wenn ich weiterhin lästig sein darf geb ich dir falls was daher kommt Bescheid.
                            Gruß Jürgen.

                            So nun sind die ersten Fehlermeldungen gekommen und zwar

                            Error received reading address 37100 from id: 1 with error: 6
                            Error received reading address 32000 from id: 1 with error: 6
                            

                            Gruß Jürgen

                            B Online
                            B Online
                            badsnoopy667
                            schrieb am zuletzt editiert von
                            #79

                            @juggi1962
                            Ließt er denn den Rest der Register, oder geht gar nix?

                            37100 scheint laut Modbus Interface Definitions V4 eine Adresse des Energy Meters zu sein. Ist die dann unter der ID 1 ansprechbar, oder muss man da eine andere ID nehmen? Ist aber auch nur der "Meter status", also eig. relativ uninteressant würde ich sagen.
                            32000 hat als Typ "Bitfield16". Vielleicht wird hier nicht der richtige Typ abgefragt? Aber auch 32000 ist (aus meiner Sicht) ein relativ uninteressantes Register. Sprich: Wenn der Rest geht, würde ich die beiden Register einfach nicht abfragen.

                            J 1 Antwort Letzte Antwort
                            0
                            • B badsnoopy667

                              @juggi1962
                              Ließt er denn den Rest der Register, oder geht gar nix?

                              37100 scheint laut Modbus Interface Definitions V4 eine Adresse des Energy Meters zu sein. Ist die dann unter der ID 1 ansprechbar, oder muss man da eine andere ID nehmen? Ist aber auch nur der "Meter status", also eig. relativ uninteressant würde ich sagen.
                              32000 hat als Typ "Bitfield16". Vielleicht wird hier nicht der richtige Typ abgefragt? Aber auch 32000 ist (aus meiner Sicht) ein relativ uninteressantes Register. Sprich: Wenn der Rest geht, würde ich die beiden Register einfach nicht abfragen.

                              J Offline
                              J Offline
                              juggi1962
                              schrieb am zuletzt editiert von
                              #80

                              @badsnoopy667
                              Die Fehler kommen nur bei 37100 und 37200
                              Ich habe aber das Skript von @Alex-Warkentin und da wurde einiges rausgestrichen.
                              bei dem Original Skript kamen viel mehr Fehlermeldungen.
                              Hier das Skript.

                              
                              
                              // License: Beerware! Do what ever you like with this, but I'm not liable for anything that you do with it.
                              
                              // If you like this code, feel free to buy me a beer ...
                              
                              // Have fun with it! der Kachel
                              
                              // @ts-ignore
                              
                              var modbusRTU = require("modbus-serial");
                              
                              var client = new modbusRTU();
                              
                               
                              
                              var modbusErrorMessages = [
                              
                                  "Unknown error",
                              
                                  "Illegal function (device does not support this read/write function)",
                              
                                  "Illegal data address (register not supported by device)",
                              
                                  "Illegal data value (value cannot be written to this register)",
                              
                                  "Slave device failure (device reports internal error)",
                              
                                  "Acknowledge (requested data will be available later)",
                              
                                  // "Slave device busy (retry request again later)"
                              
                              ];
                              
                               
                              
                              // Enter your inverter modbus IP and port here:
                              
                              const modbusHost = "192.168.1.7";
                              
                              const modbusPort = 502;
                              
                              // Enter the Modbus-IDs of your Sun2000 inverters here:
                              
                              const modbusID = [1];
                              
                              // On which Modbus-ID can we reach the power meter? (via Sun2000!)
                              
                              const powerMeterID = 0;
                              
                               
                              
                              // Connect to modbus client
                              
                              ConnectModbus();
                              
                               
                              
                              // These register spaces need to be read:
                              
                              const registerSpacesToReadContinuously = [[37100, 114], [32000, 116]];
                              
                              var registerSpacesToReadContinuouslyPtr = 0;
                              
                               
                              
                              var globalDataBuffer = new Array(1);
                              
                              globalDataBuffer[0] = new Array(50000); // not optimized....
                              
                               
                              
                              // ---------------------------------------------------------------
                              
                              // Some helper functions:
                              
                              function ReadUnsignedInt16(array) {
                              
                                  var value = array[0];    
                              
                                  return value;
                              
                              }
                              
                               
                              
                              function ReadUnsignedInt32(array) {
                              
                                  var value = array[0] * 256 * 256 + array[1];    
                              
                                  return value;
                              
                              }
                              
                               
                              
                              function ReadSignedInt16(array) {
                              
                                  var value = 0;
                              
                                  if (array[0] > 32767)
                              
                                      value = array[0] - 65535; 
                              
                                  else
                              
                                      value = array[0];
                              
                               
                              
                                  return value;
                              
                              }
                              
                              function ReadSignedInt32(array) {
                              
                                  var value = 0;
                              
                                  for (var i = 0; i < 2; i++) {
                              
                                      value = (value << 16) | array[i];
                              
                                  }
                              
                                  return value;
                              
                              }
                              
                              function GetU16(dataarray, index) {
                              
                                  var value = ReadUnsignedInt16(dataarray.slice(index, index+1));
                              
                                  return value;
                              
                              }
                              
                               
                              
                              function GetU32(dataarray, index) {
                              
                                  var value = ReadUnsignedInt32(dataarray.slice(index, index+2));
                              
                                  return value;
                              
                              }
                              
                               
                              
                              function GetI16(dataarray, index) {
                              
                                  var value = ReadSignedInt16(dataarray.slice(index, index+1));
                              
                                  return value;
                              
                              }
                              
                               
                              
                              function GetI32(dataarray, index) {
                              
                                  var value = ReadSignedInt32(dataarray.slice(index, index+2));
                              
                                  return value;
                              
                              }
                              
                               
                              
                              function GetString(dataarray, index, length) {
                              
                                  var shortarray = dataarray.slice(index, index+length);
                              
                                  var bytearray = [];
                              
                                  for(var i = 0; i < length; i++) {
                              
                                      bytearray.push(dataarray[index+i] >> 8);
                              
                                      bytearray.push(dataarray[index+i] & 0xff);
                              
                                  }       
                              
                                  var value =  String.fromCharCode.apply(null, bytearray);    
                              
                                  return value;
                              
                              }
                              
                               
                              
                              function GetZeroTerminatedString(dataarray, index, length) {
                              
                                  var shortarray = dataarray.slice(index, index+length);
                              
                                  var bytearray = [];
                              
                                  for(var i = 0; i < length; i++) {
                              
                                      bytearray.push(dataarray[index+i] >> 8);
                              
                                      bytearray.push(dataarray[index+i] & 0xff);
                              
                                  }       
                              
                                  var value =  String.fromCharCode.apply(null, bytearray);    
                              
                                  var value2 = new String(value).trim();
                              
                                  return value2;
                              
                              }
                              
                               
                              
                              // Funktion zum Herstellen einer Modbus-Verbindung
                              
                              function ConnectModbus() {
                              
                                  console.log("Init connection to: " + modbusHost +":" + modbusPort);
                              
                                  // set requests parameters
                              
                                  client.setTimeout (10000);
                              
                                  // try to connect
                              
                                  client.connectTCP (modbusHost, { port: modbusPort })
                              
                                      .then(function()
                              
                                      {
                              
                                          console.log("Connected, wait for reading...");
                              
                                      })
                              
                                      .catch(function(e)
                              
                                      {
                              
                                          console.log(e);
                              
                                      });
                              
                              }
                              
                               
                              
                              // Funktion zum Anlegen und Beschreiben eines Datenpunkts
                              
                              function ForceSetState(objectname, value, options) {
                              
                                  if(!existsState("javascript.0." + objectname))      createState(objectname, value, options);
                              
                                  else                                                setState(objectname, value);
                              
                              }  
                              
                              // ---------------------------------------------------------------
                              
                              // Functions to map registers into ioBreaker objects:
                              
                              function ProcessPowerMeterStatus() {       
                              
                                  ForceSetState("Solarpower.Huawei.Meter.Status",                     GetU16(globalDataBuffer[powerMeterID], 37100),          {name: "", unit: ""});
                              
                                  ForceSetState("Solarpower.Huawei.Meter.VoltageL1",                  GetI32(globalDataBuffer[powerMeterID], 37101) / 10,     {name: "", unit: "V"});
                              
                                  ForceSetState("Solarpower.Huawei.Meter.VoltageL2",                  GetI32(globalDataBuffer[powerMeterID], 37103) / 10,     {name: "", unit: "V"});
                              
                                  ForceSetState("Solarpower.Huawei.Meter.VoltageL3",                  GetI32(globalDataBuffer[powerMeterID], 37105) / 10,     {name: "", unit: "V"});
                              
                                  ForceSetState("Solarpower.Huawei.Meter.CurrentL1",                  GetI32(globalDataBuffer[powerMeterID], 37107) / 100,    {name: "", unit: "A"});
                              
                                  ForceSetState("Solarpower.Huawei.Meter.CurrentL2",                  GetI32(globalDataBuffer[powerMeterID], 37109) / 100,    {name: "", unit: "A"});
                              
                                  ForceSetState("Solarpower.Huawei.Meter.CurrentL3",                  GetI32(globalDataBuffer[powerMeterID], 37111) / 100,    {name: "", unit: "A"});
                              
                                  ForceSetState("Solarpower.Huawei.Meter.ActivePower",                GetI32(globalDataBuffer[powerMeterID], 37113) / 1,      {name: "", unit: "W"});
                              
                                  ForceSetState("Solarpower.Huawei.Meter.ReactivePower",              GetI32(globalDataBuffer[powerMeterID], 37115) / 1,      {name: "", unit: "Var"});
                              
                                  ForceSetState("Solarpower.Huawei.Meter.PowerFactor",                GetI16(globalDataBuffer[powerMeterID], 37117) / 1000,   {name: "", unit: ""});
                              
                                  ForceSetState("Solarpower.Huawei.Meter.GridFrequency",              GetI16(globalDataBuffer[powerMeterID], 37118) / 100,    {name: "", unit: "Hz"});
                              
                                  ForceSetState("Solarpower.Huawei.Meter.PositiveActiveEnergy",       GetI32(globalDataBuffer[powerMeterID], 37119) / 100,    {name: "", unit: "kWh"});
                              
                                  ForceSetState("Solarpower.Huawei.Meter.ReverseActiveEnergy",        GetI32(globalDataBuffer[powerMeterID], 37121) / 100,    {name: "", unit: "kWh"});
                              
                                  ForceSetState("Solarpower.Huawei.Meter.AccumulatedReactivePower",   GetI32(globalDataBuffer[powerMeterID], 37123) / 100,    {name: "", unit: "kVarh"});
                              
                                  //ForceSetState("Solarpower.Huawei.Meter.MeterType",                  GetU16(globalDataBuffer[powerMeterID], 37125),          {name: "", unit: ""});
                              
                                  ForceSetState("Solarpower.Huawei.Meter.VoltageL1-L2",               GetI32(globalDataBuffer[powerMeterID], 37126) / 10,     {name: "", unit: "V"});
                              
                                  ForceSetState("Solarpower.Huawei.Meter.VoltageL2-L3",               GetI32(globalDataBuffer[powerMeterID], 37128) / 10,     {name: "", unit: "V"});
                              
                                  ForceSetState("Solarpower.Huawei.Meter.VoltageL3-L1",               GetI32(globalDataBuffer[powerMeterID], 37130) / 10,     {name: "", unit: "V"});
                              
                                  ForceSetState("Solarpower.Huawei.Meter.ActivePowerL1",              GetI32(globalDataBuffer[powerMeterID], 37132) / 1,      {name: "", unit: "W"});
                              
                                  ForceSetState("Solarpower.Huawei.Meter.ActivePowerL2",              GetI32(globalDataBuffer[powerMeterID], 37134) / 1,      {name: "", unit: "W"});
                              
                                  ForceSetState("Solarpower.Huawei.Meter.ActivePowerL3",              GetI32(globalDataBuffer[powerMeterID], 37136) / 1,      {name: "", unit: "W"});
                              
                                  //ForceSetState("Solarpower.Huawei.Meter.MeterModel",                 GetU16(globalDataBuffer[powerMeterID], 37138),          {name: "", unit: ""});
                              
                              }
                              
                               
                              
                              function ProcessInverterStatus(id) {
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".State1",                   GetU16(globalDataBuffer[id-1], 32000),          {name: "", unit: ""});
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".State2",                   GetU16(globalDataBuffer[id-1], 32002),          {name: "", unit: ""});
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".State3",                   GetU32(globalDataBuffer[id-1], 32003),          {name: "", unit: ""});
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".Alarm1",                   GetU16(globalDataBuffer[id-1], 32008),          {name: "", unit: ""});
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".Alarm2",                   GetU16(globalDataBuffer[id-1], 32009),          {name: "", unit: ""});
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".Alarm3",                   GetU16(globalDataBuffer[id-1], 32010),          {name: "", unit: ""});
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.1_Voltage",         GetI16(globalDataBuffer[id-1], 32016) / 10,     {name: "", unit: "V"});
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.1_Current",         GetI16(globalDataBuffer[id-1], 32017) / 100,    {name: "", unit: "A"});
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.2_Voltage",         GetI16(globalDataBuffer[id-1], 32018) / 10,     {name: "", unit: "V"});
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.2_Current",         GetI16(globalDataBuffer[id-1], 32019) / 100,    {name: "", unit: "A"});
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.3_Voltage",         GetI16(globalDataBuffer[id-1], 32020) / 10,     {name: "", unit: "V"});
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.3_Current",         GetI16(globalDataBuffer[id-1], 32021) / 100,    {name: "", unit: "A"});
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.4_Voltage",         GetI16(globalDataBuffer[id-1], 32022) / 10,     {name: "", unit: "V"});
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.4_Current",         GetI16(globalDataBuffer[id-1], 32023) / 100,    {name: "", unit: "A"});
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".InputPower",               GetI32(globalDataBuffer[id-1], 32064) / 1000,   {name: "", unit: "kW"});
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1-L2_Voltage",       GetU16(globalDataBuffer[id-1], 32066) / 10,     {name: "", unit: "V"});      
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2-L3_Voltage",       GetU16(globalDataBuffer[id-1], 32067) / 10,     {name: "", unit: "V"});
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3-L1_Voltage",       GetU16(globalDataBuffer[id-1], 32068) / 10,     {name: "", unit: "V"});
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1_Voltage",          GetU16(globalDataBuffer[id-1], 32069) / 10,     {name: "", unit: "V"});                              
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2_Voltage",          GetU16(globalDataBuffer[id-1], 32070) / 10,     {name: "", unit: "V"});                                                  
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3_Voltage",          GetU16(globalDataBuffer[id-1], 32071) / 10,     {name: "", unit: "V"});
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1_Current",          GetI32(globalDataBuffer[id-1], 32072) / 1000,   {name: "", unit: "A"});
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2_Current",          GetI32(globalDataBuffer[id-1], 32074) / 1000,   {name: "", unit: "A"});
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3_Current",          GetI32(globalDataBuffer[id-1], 32076) / 1000,   {name: "", unit: "A"});
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".PeakActivePowerDay",       GetI32(globalDataBuffer[id-1], 32078) / 1000,   {name: "", unit: "kW"});
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".ActivePower",              GetI32(globalDataBuffer[id-1], 32080) / 1000,   {name: "", unit: "kW"});
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".ReactivePower",            GetI32(globalDataBuffer[id-1], 32082) / 1000,   {name: "", unit: "kVar"});
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".PowerFactor",              GetI16(globalDataBuffer[id-1], 32084) / 1000,   {name: "", unit: ""});
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".GridFrequency",            GetU16(globalDataBuffer[id-1], 32085) / 100,    {name: "", unit: "Hz"});
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".Efficiency",               GetU16(globalDataBuffer[id-1], 32086) / 100,    {name: "", unit: "%"});
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".InternalTemperature",      GetI16(globalDataBuffer[id-1], 32087) / 10,     {name: "", unit: "°C"});
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".InsulationResistance",     GetU16(globalDataBuffer[id-1], 32088) / 1000,   {name: "", unit: "MOhm"});
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".DeviceStatus",             GetU16(globalDataBuffer[id-1], 32089),          {name: "", unit: ""});
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".FaultCode",                GetU16(globalDataBuffer[id-1], 32090),          {name: "", unit: ""});
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".StartupTime",              String(new Date(GetU32(globalDataBuffer[id-1], 32091)*1000)),          {name: "", unit: ""});
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".ShutdownTime",             String(new Date(GetU32(globalDataBuffer[id-1], 32093)*1000)),          {name: "", unit: ""});
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".AccomulatedEnergyYield",   GetU32(globalDataBuffer[id-1], 32106) / 100,          {name: "", unit: "kWh"});
                              
                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".DailyEnergyYield",         GetU32(globalDataBuffer[id-1], 32114) / 100,          {name: "", unit: "kWh"});
                              
                              }
                              
                               
                              
                              
                              
                              function ReadRegisterSpace(id, address, length) {
                              
                                  client.setID(modbusID[id-1]);
                              
                                  client.readHoldingRegisters(address, length, function(err, data) {
                              
                                      if (err) {
                              
                                          if (err.modbusCode == null) {
                              
                                              console.warn("Lost connection to client. Trying to reconnect...");
                              
                                              ConnectModbus();
                              
                                          } 
                              
                                          else console.warn("Error received reading address " + address + " from id: " + modbusID[id-1] + " with error: " + err.modbusCode); 
                              
                                      }
                              
                                      else
                              
                                      {   
                              
                                          console.debug("Read data from id/address " + modbusID[id-1] + "/" + address + "\nData is: " + data.data);
                              
                                          for(var i = 0; i < length; i++)  {
                              
                                              globalDataBuffer[id-1][address+i] = data.data[i];
                              
                                          } 
                              
                                      }
                              
                                  });
                              
                              }
                              
                               
                              
                              function ProcessData() {
                              
                                  //console.log("Processing new data...");
                              
                                  for(var i = 1; i <= modbusID.length; i++) {
                              
                                      ProcessInverterStatus(i);
                              
                                  }    
                              
                                  ProcessPowerMeterStatus();
                              
                                  //console.log("Processing done!");
                              
                              }
                              
                               
                              
                               
                              
                              // -------------------------------------------------------------------
                              
                              // This is the main function triggering a  read via modbus-tcp every two seconds.
                              
                              // Processing of data is triggered as soon as one complete set of registers is copied.
                              
                              var triggerprocessing = 0; 
                              
                              var currentinverter = 1;
                              
                               
                              
                               
                              
                              setInterval(function() {
                              
                                  if(triggerprocessing == 1) {
                              
                                      triggerprocessing = 0;
                              
                                      ProcessData();        
                              
                                  }      
                              
                                 
                              
                                  //console.log("Triggering read of inverter " + currentinverter + " at address " + registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][0] + " with length " +  registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][1]);
                              
                                  ReadRegisterSpace(currentinverter, registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][0], registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][1]); 
                              
                                  registerSpacesToReadContinuouslyPtr++;               
                              
                                  if(registerSpacesToReadContinuouslyPtr >= registerSpacesToReadContinuously.length) {
                              
                                      registerSpacesToReadContinuouslyPtr = 0;
                              
                                      currentinverter++
                              
                                      if(currentinverter > modbusID.length){
                              
                                          currentinverter = 1;  
                              
                                          triggerprocessing = 1;                    
                              
                                      }
                              
                                  }     
                              
                              }, 3000);
                              
                              

                              Leider kenne ich mich mit dem JS überhaupt nicht aus :disappointed:

                              Gruß Jürgen

                              B 1 Antwort Letzte Antwort
                              0
                              • J juggi1962

                                @badsnoopy667
                                Die Fehler kommen nur bei 37100 und 37200
                                Ich habe aber das Skript von @Alex-Warkentin und da wurde einiges rausgestrichen.
                                bei dem Original Skript kamen viel mehr Fehlermeldungen.
                                Hier das Skript.

                                
                                
                                // License: Beerware! Do what ever you like with this, but I'm not liable for anything that you do with it.
                                
                                // If you like this code, feel free to buy me a beer ...
                                
                                // Have fun with it! der Kachel
                                
                                // @ts-ignore
                                
                                var modbusRTU = require("modbus-serial");
                                
                                var client = new modbusRTU();
                                
                                 
                                
                                var modbusErrorMessages = [
                                
                                    "Unknown error",
                                
                                    "Illegal function (device does not support this read/write function)",
                                
                                    "Illegal data address (register not supported by device)",
                                
                                    "Illegal data value (value cannot be written to this register)",
                                
                                    "Slave device failure (device reports internal error)",
                                
                                    "Acknowledge (requested data will be available later)",
                                
                                    // "Slave device busy (retry request again later)"
                                
                                ];
                                
                                 
                                
                                // Enter your inverter modbus IP and port here:
                                
                                const modbusHost = "192.168.1.7";
                                
                                const modbusPort = 502;
                                
                                // Enter the Modbus-IDs of your Sun2000 inverters here:
                                
                                const modbusID = [1];
                                
                                // On which Modbus-ID can we reach the power meter? (via Sun2000!)
                                
                                const powerMeterID = 0;
                                
                                 
                                
                                // Connect to modbus client
                                
                                ConnectModbus();
                                
                                 
                                
                                // These register spaces need to be read:
                                
                                const registerSpacesToReadContinuously = [[37100, 114], [32000, 116]];
                                
                                var registerSpacesToReadContinuouslyPtr = 0;
                                
                                 
                                
                                var globalDataBuffer = new Array(1);
                                
                                globalDataBuffer[0] = new Array(50000); // not optimized....
                                
                                 
                                
                                // ---------------------------------------------------------------
                                
                                // Some helper functions:
                                
                                function ReadUnsignedInt16(array) {
                                
                                    var value = array[0];    
                                
                                    return value;
                                
                                }
                                
                                 
                                
                                function ReadUnsignedInt32(array) {
                                
                                    var value = array[0] * 256 * 256 + array[1];    
                                
                                    return value;
                                
                                }
                                
                                 
                                
                                function ReadSignedInt16(array) {
                                
                                    var value = 0;
                                
                                    if (array[0] > 32767)
                                
                                        value = array[0] - 65535; 
                                
                                    else
                                
                                        value = array[0];
                                
                                 
                                
                                    return value;
                                
                                }
                                
                                function ReadSignedInt32(array) {
                                
                                    var value = 0;
                                
                                    for (var i = 0; i < 2; i++) {
                                
                                        value = (value << 16) | array[i];
                                
                                    }
                                
                                    return value;
                                
                                }
                                
                                function GetU16(dataarray, index) {
                                
                                    var value = ReadUnsignedInt16(dataarray.slice(index, index+1));
                                
                                    return value;
                                
                                }
                                
                                 
                                
                                function GetU32(dataarray, index) {
                                
                                    var value = ReadUnsignedInt32(dataarray.slice(index, index+2));
                                
                                    return value;
                                
                                }
                                
                                 
                                
                                function GetI16(dataarray, index) {
                                
                                    var value = ReadSignedInt16(dataarray.slice(index, index+1));
                                
                                    return value;
                                
                                }
                                
                                 
                                
                                function GetI32(dataarray, index) {
                                
                                    var value = ReadSignedInt32(dataarray.slice(index, index+2));
                                
                                    return value;
                                
                                }
                                
                                 
                                
                                function GetString(dataarray, index, length) {
                                
                                    var shortarray = dataarray.slice(index, index+length);
                                
                                    var bytearray = [];
                                
                                    for(var i = 0; i < length; i++) {
                                
                                        bytearray.push(dataarray[index+i] >> 8);
                                
                                        bytearray.push(dataarray[index+i] & 0xff);
                                
                                    }       
                                
                                    var value =  String.fromCharCode.apply(null, bytearray);    
                                
                                    return value;
                                
                                }
                                
                                 
                                
                                function GetZeroTerminatedString(dataarray, index, length) {
                                
                                    var shortarray = dataarray.slice(index, index+length);
                                
                                    var bytearray = [];
                                
                                    for(var i = 0; i < length; i++) {
                                
                                        bytearray.push(dataarray[index+i] >> 8);
                                
                                        bytearray.push(dataarray[index+i] & 0xff);
                                
                                    }       
                                
                                    var value =  String.fromCharCode.apply(null, bytearray);    
                                
                                    var value2 = new String(value).trim();
                                
                                    return value2;
                                
                                }
                                
                                 
                                
                                // Funktion zum Herstellen einer Modbus-Verbindung
                                
                                function ConnectModbus() {
                                
                                    console.log("Init connection to: " + modbusHost +":" + modbusPort);
                                
                                    // set requests parameters
                                
                                    client.setTimeout (10000);
                                
                                    // try to connect
                                
                                    client.connectTCP (modbusHost, { port: modbusPort })
                                
                                        .then(function()
                                
                                        {
                                
                                            console.log("Connected, wait for reading...");
                                
                                        })
                                
                                        .catch(function(e)
                                
                                        {
                                
                                            console.log(e);
                                
                                        });
                                
                                }
                                
                                 
                                
                                // Funktion zum Anlegen und Beschreiben eines Datenpunkts
                                
                                function ForceSetState(objectname, value, options) {
                                
                                    if(!existsState("javascript.0." + objectname))      createState(objectname, value, options);
                                
                                    else                                                setState(objectname, value);
                                
                                }  
                                
                                // ---------------------------------------------------------------
                                
                                // Functions to map registers into ioBreaker objects:
                                
                                function ProcessPowerMeterStatus() {       
                                
                                    ForceSetState("Solarpower.Huawei.Meter.Status",                     GetU16(globalDataBuffer[powerMeterID], 37100),          {name: "", unit: ""});
                                
                                    ForceSetState("Solarpower.Huawei.Meter.VoltageL1",                  GetI32(globalDataBuffer[powerMeterID], 37101) / 10,     {name: "", unit: "V"});
                                
                                    ForceSetState("Solarpower.Huawei.Meter.VoltageL2",                  GetI32(globalDataBuffer[powerMeterID], 37103) / 10,     {name: "", unit: "V"});
                                
                                    ForceSetState("Solarpower.Huawei.Meter.VoltageL3",                  GetI32(globalDataBuffer[powerMeterID], 37105) / 10,     {name: "", unit: "V"});
                                
                                    ForceSetState("Solarpower.Huawei.Meter.CurrentL1",                  GetI32(globalDataBuffer[powerMeterID], 37107) / 100,    {name: "", unit: "A"});
                                
                                    ForceSetState("Solarpower.Huawei.Meter.CurrentL2",                  GetI32(globalDataBuffer[powerMeterID], 37109) / 100,    {name: "", unit: "A"});
                                
                                    ForceSetState("Solarpower.Huawei.Meter.CurrentL3",                  GetI32(globalDataBuffer[powerMeterID], 37111) / 100,    {name: "", unit: "A"});
                                
                                    ForceSetState("Solarpower.Huawei.Meter.ActivePower",                GetI32(globalDataBuffer[powerMeterID], 37113) / 1,      {name: "", unit: "W"});
                                
                                    ForceSetState("Solarpower.Huawei.Meter.ReactivePower",              GetI32(globalDataBuffer[powerMeterID], 37115) / 1,      {name: "", unit: "Var"});
                                
                                    ForceSetState("Solarpower.Huawei.Meter.PowerFactor",                GetI16(globalDataBuffer[powerMeterID], 37117) / 1000,   {name: "", unit: ""});
                                
                                    ForceSetState("Solarpower.Huawei.Meter.GridFrequency",              GetI16(globalDataBuffer[powerMeterID], 37118) / 100,    {name: "", unit: "Hz"});
                                
                                    ForceSetState("Solarpower.Huawei.Meter.PositiveActiveEnergy",       GetI32(globalDataBuffer[powerMeterID], 37119) / 100,    {name: "", unit: "kWh"});
                                
                                    ForceSetState("Solarpower.Huawei.Meter.ReverseActiveEnergy",        GetI32(globalDataBuffer[powerMeterID], 37121) / 100,    {name: "", unit: "kWh"});
                                
                                    ForceSetState("Solarpower.Huawei.Meter.AccumulatedReactivePower",   GetI32(globalDataBuffer[powerMeterID], 37123) / 100,    {name: "", unit: "kVarh"});
                                
                                    //ForceSetState("Solarpower.Huawei.Meter.MeterType",                  GetU16(globalDataBuffer[powerMeterID], 37125),          {name: "", unit: ""});
                                
                                    ForceSetState("Solarpower.Huawei.Meter.VoltageL1-L2",               GetI32(globalDataBuffer[powerMeterID], 37126) / 10,     {name: "", unit: "V"});
                                
                                    ForceSetState("Solarpower.Huawei.Meter.VoltageL2-L3",               GetI32(globalDataBuffer[powerMeterID], 37128) / 10,     {name: "", unit: "V"});
                                
                                    ForceSetState("Solarpower.Huawei.Meter.VoltageL3-L1",               GetI32(globalDataBuffer[powerMeterID], 37130) / 10,     {name: "", unit: "V"});
                                
                                    ForceSetState("Solarpower.Huawei.Meter.ActivePowerL1",              GetI32(globalDataBuffer[powerMeterID], 37132) / 1,      {name: "", unit: "W"});
                                
                                    ForceSetState("Solarpower.Huawei.Meter.ActivePowerL2",              GetI32(globalDataBuffer[powerMeterID], 37134) / 1,      {name: "", unit: "W"});
                                
                                    ForceSetState("Solarpower.Huawei.Meter.ActivePowerL3",              GetI32(globalDataBuffer[powerMeterID], 37136) / 1,      {name: "", unit: "W"});
                                
                                    //ForceSetState("Solarpower.Huawei.Meter.MeterModel",                 GetU16(globalDataBuffer[powerMeterID], 37138),          {name: "", unit: ""});
                                
                                }
                                
                                 
                                
                                function ProcessInverterStatus(id) {
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".State1",                   GetU16(globalDataBuffer[id-1], 32000),          {name: "", unit: ""});
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".State2",                   GetU16(globalDataBuffer[id-1], 32002),          {name: "", unit: ""});
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".State3",                   GetU32(globalDataBuffer[id-1], 32003),          {name: "", unit: ""});
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".Alarm1",                   GetU16(globalDataBuffer[id-1], 32008),          {name: "", unit: ""});
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".Alarm2",                   GetU16(globalDataBuffer[id-1], 32009),          {name: "", unit: ""});
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".Alarm3",                   GetU16(globalDataBuffer[id-1], 32010),          {name: "", unit: ""});
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.1_Voltage",         GetI16(globalDataBuffer[id-1], 32016) / 10,     {name: "", unit: "V"});
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.1_Current",         GetI16(globalDataBuffer[id-1], 32017) / 100,    {name: "", unit: "A"});
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.2_Voltage",         GetI16(globalDataBuffer[id-1], 32018) / 10,     {name: "", unit: "V"});
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.2_Current",         GetI16(globalDataBuffer[id-1], 32019) / 100,    {name: "", unit: "A"});
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.3_Voltage",         GetI16(globalDataBuffer[id-1], 32020) / 10,     {name: "", unit: "V"});
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.3_Current",         GetI16(globalDataBuffer[id-1], 32021) / 100,    {name: "", unit: "A"});
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.4_Voltage",         GetI16(globalDataBuffer[id-1], 32022) / 10,     {name: "", unit: "V"});
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".String.4_Current",         GetI16(globalDataBuffer[id-1], 32023) / 100,    {name: "", unit: "A"});
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".InputPower",               GetI32(globalDataBuffer[id-1], 32064) / 1000,   {name: "", unit: "kW"});
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1-L2_Voltage",       GetU16(globalDataBuffer[id-1], 32066) / 10,     {name: "", unit: "V"});      
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2-L3_Voltage",       GetU16(globalDataBuffer[id-1], 32067) / 10,     {name: "", unit: "V"});
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3-L1_Voltage",       GetU16(globalDataBuffer[id-1], 32068) / 10,     {name: "", unit: "V"});
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1_Voltage",          GetU16(globalDataBuffer[id-1], 32069) / 10,     {name: "", unit: "V"});                              
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2_Voltage",          GetU16(globalDataBuffer[id-1], 32070) / 10,     {name: "", unit: "V"});                                                  
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3_Voltage",          GetU16(globalDataBuffer[id-1], 32071) / 10,     {name: "", unit: "V"});
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1_Current",          GetI32(globalDataBuffer[id-1], 32072) / 1000,   {name: "", unit: "A"});
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2_Current",          GetI32(globalDataBuffer[id-1], 32074) / 1000,   {name: "", unit: "A"});
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3_Current",          GetI32(globalDataBuffer[id-1], 32076) / 1000,   {name: "", unit: "A"});
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".PeakActivePowerDay",       GetI32(globalDataBuffer[id-1], 32078) / 1000,   {name: "", unit: "kW"});
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".ActivePower",              GetI32(globalDataBuffer[id-1], 32080) / 1000,   {name: "", unit: "kW"});
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".ReactivePower",            GetI32(globalDataBuffer[id-1], 32082) / 1000,   {name: "", unit: "kVar"});
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".PowerFactor",              GetI16(globalDataBuffer[id-1], 32084) / 1000,   {name: "", unit: ""});
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".GridFrequency",            GetU16(globalDataBuffer[id-1], 32085) / 100,    {name: "", unit: "Hz"});
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".Efficiency",               GetU16(globalDataBuffer[id-1], 32086) / 100,    {name: "", unit: "%"});
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".InternalTemperature",      GetI16(globalDataBuffer[id-1], 32087) / 10,     {name: "", unit: "°C"});
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".InsulationResistance",     GetU16(globalDataBuffer[id-1], 32088) / 1000,   {name: "", unit: "MOhm"});
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".DeviceStatus",             GetU16(globalDataBuffer[id-1], 32089),          {name: "", unit: ""});
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".FaultCode",                GetU16(globalDataBuffer[id-1], 32090),          {name: "", unit: ""});
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".StartupTime",              String(new Date(GetU32(globalDataBuffer[id-1], 32091)*1000)),          {name: "", unit: ""});
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".ShutdownTime",             String(new Date(GetU32(globalDataBuffer[id-1], 32093)*1000)),          {name: "", unit: ""});
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".AccomulatedEnergyYield",   GetU32(globalDataBuffer[id-1], 32106) / 100,          {name: "", unit: "kWh"});
                                
                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".DailyEnergyYield",         GetU32(globalDataBuffer[id-1], 32114) / 100,          {name: "", unit: "kWh"});
                                
                                }
                                
                                 
                                
                                
                                
                                function ReadRegisterSpace(id, address, length) {
                                
                                    client.setID(modbusID[id-1]);
                                
                                    client.readHoldingRegisters(address, length, function(err, data) {
                                
                                        if (err) {
                                
                                            if (err.modbusCode == null) {
                                
                                                console.warn("Lost connection to client. Trying to reconnect...");
                                
                                                ConnectModbus();
                                
                                            } 
                                
                                            else console.warn("Error received reading address " + address + " from id: " + modbusID[id-1] + " with error: " + err.modbusCode); 
                                
                                        }
                                
                                        else
                                
                                        {   
                                
                                            console.debug("Read data from id/address " + modbusID[id-1] + "/" + address + "\nData is: " + data.data);
                                
                                            for(var i = 0; i < length; i++)  {
                                
                                                globalDataBuffer[id-1][address+i] = data.data[i];
                                
                                            } 
                                
                                        }
                                
                                    });
                                
                                }
                                
                                 
                                
                                function ProcessData() {
                                
                                    //console.log("Processing new data...");
                                
                                    for(var i = 1; i <= modbusID.length; i++) {
                                
                                        ProcessInverterStatus(i);
                                
                                    }    
                                
                                    ProcessPowerMeterStatus();
                                
                                    //console.log("Processing done!");
                                
                                }
                                
                                 
                                
                                 
                                
                                // -------------------------------------------------------------------
                                
                                // This is the main function triggering a  read via modbus-tcp every two seconds.
                                
                                // Processing of data is triggered as soon as one complete set of registers is copied.
                                
                                var triggerprocessing = 0; 
                                
                                var currentinverter = 1;
                                
                                 
                                
                                 
                                
                                setInterval(function() {
                                
                                    if(triggerprocessing == 1) {
                                
                                        triggerprocessing = 0;
                                
                                        ProcessData();        
                                
                                    }      
                                
                                   
                                
                                    //console.log("Triggering read of inverter " + currentinverter + " at address " + registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][0] + " with length " +  registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][1]);
                                
                                    ReadRegisterSpace(currentinverter, registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][0], registerSpacesToReadContinuously[registerSpacesToReadContinuouslyPtr][1]); 
                                
                                    registerSpacesToReadContinuouslyPtr++;               
                                
                                    if(registerSpacesToReadContinuouslyPtr >= registerSpacesToReadContinuously.length) {
                                
                                        registerSpacesToReadContinuouslyPtr = 0;
                                
                                        currentinverter++
                                
                                        if(currentinverter > modbusID.length){
                                
                                            currentinverter = 1;  
                                
                                            triggerprocessing = 1;                    
                                
                                        }
                                
                                    }     
                                
                                }, 3000);
                                
                                

                                Leider kenne ich mich mit dem JS überhaupt nicht aus :disappointed:

                                Gruß Jürgen

                                B Online
                                B Online
                                badsnoopy667
                                schrieb am zuletzt editiert von
                                #81

                                @juggi1962

                                Kommentier die beiden Zeilen wo 37100 und 32000 abgefragt werden doch einfach aus! Also // davorschreiben, so wie das im Script bei anderen Zeilen ja auch schon gemacht wurde.

                                J 1 Antwort Letzte Antwort
                                0
                                • B badsnoopy667

                                  @juggi1962

                                  Kommentier die beiden Zeilen wo 37100 und 32000 abgefragt werden doch einfach aus! Also // davorschreiben, so wie das im Script bei anderen Zeilen ja auch schon gemacht wurde.

                                  J Offline
                                  J Offline
                                  juggi1962
                                  schrieb am zuletzt editiert von
                                  #82

                                  @badsnoopy667
                                  Meinst du diese?

                                  ForceSetState("Solarpower.Huawei.Inverter." + id + ".State1",                   GetU16(globalDataBuffer[id-1], 32000),          {name: "", unit: ""});
                                  ForceSetState("Solarpower.Huawei.Meter.Status",                     GetU16(globalDataBuffer[powerMeterID], 37100),          {name: "", unit: ""});
                                  

                                  Brauch ich die gar nicht?

                                  B 1 Antwort Letzte Antwort
                                  0
                                  • J juggi1962

                                    @badsnoopy667
                                    Meinst du diese?

                                    ForceSetState("Solarpower.Huawei.Inverter." + id + ".State1",                   GetU16(globalDataBuffer[id-1], 32000),          {name: "", unit: ""});
                                    ForceSetState("Solarpower.Huawei.Meter.Status",                     GetU16(globalDataBuffer[powerMeterID], 37100),          {name: "", unit: ""});
                                    

                                    Brauch ich die gar nicht?

                                    B Online
                                    B Online
                                    badsnoopy667
                                    schrieb am zuletzt editiert von
                                    #83

                                    @juggi1962
                                    Ja, das sollten die beiden Zeilen sein. Die brauchst Du nur, wenn du die beiden Register abfragen willst. Aber wie gesagt: Da steht meiner Meinung nach nix wirklich wichtiges drin. Wenn es also nicht klappt, würde ich die einfach nicht abfragen und gut ist.

                                    J 2 Antworten Letzte Antwort
                                    0
                                    • B badsnoopy667

                                      @juggi1962
                                      Ja, das sollten die beiden Zeilen sein. Die brauchst Du nur, wenn du die beiden Register abfragen willst. Aber wie gesagt: Da steht meiner Meinung nach nix wirklich wichtiges drin. Wenn es also nicht klappt, würde ich die einfach nicht abfragen und gut ist.

                                      J Offline
                                      J Offline
                                      juggi1962
                                      schrieb am zuletzt editiert von
                                      #84

                                      @badsnoopy667
                                      Okay Danke, werde ich mal versuchen.
                                      Gruß Jürgen

                                      1 Antwort Letzte Antwort
                                      0
                                      • J Offline
                                        J Offline
                                        juggi1962
                                        schrieb am zuletzt editiert von
                                        #85

                                        @badsnoopy667
                                        kannst du mir vielleicht sagen, was der Unterschid zwischen
                                        AktivePower und InputPower ist?
                                        Was von beiden kommt bei mir im Zählerkasten an?

                                        1 Antwort Letzte Antwort
                                        0
                                        • B badsnoopy667

                                          @juggi1962
                                          Ja, das sollten die beiden Zeilen sein. Die brauchst Du nur, wenn du die beiden Register abfragen willst. Aber wie gesagt: Da steht meiner Meinung nach nix wirklich wichtiges drin. Wenn es also nicht klappt, würde ich die einfach nicht abfragen und gut ist.

                                          J Offline
                                          J Offline
                                          juggi1962
                                          schrieb am zuletzt editiert von
                                          #86

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

                                          @juggi1962
                                          Ja, das sollten die beiden Zeilen sein. Die brauchst Du nur, wenn du die beiden Register abfragen willst. Aber wie gesagt: Da steht meiner Meinung nach nix wirklich wichtiges drin. Wenn es also nicht klappt, würde ich die einfach nicht abfragen und gut ist.

                                          Hmmmmmmmmmmm das ausklammern hat nichts gebracht die Fehlermeldungen kommen trotzdem

                                          javascript.0
                                          2023-03-13 13:18:07.967	warn	script.js.Neu.PV_Anlage.Modbus_Huawei_Sun2000_neu: Error received reading address 32000 from id: 1 with error: undefined
                                          
                                          2023-03-13 13:17:04.965	warn	script.js.Neu.PV_Anlage.Modbus_Huawei_Sun2000_neu: Error received reading address 37100 from id: 1 with error: undefined
                                          
                                          
                                          2023-03-13 13:16:01.958	warn	script.js.Neu.PV_Anlage.Modbus_Huawei_Sun2000_neu: Error received reading address 32000 from id: 1 with error: undefined
                                          

                                          Was nun ?? Gruß Jürgen

                                          B 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

                                          533

                                          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