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

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

Community Forum

  1. ioBroker Community Home
  2. Deutsch
  3. ioBroker Allgemein
  4. Huawei Sun2000 & ioBroker via JS script funktioniert

NEWS

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

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

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

Huawei Sun2000 & ioBroker via JS script funktioniert

Geplant Angeheftet Gesperrt Verschoben ioBroker Allgemein
481 Beiträge 62 Kommentatoren 121.2k 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.
  • S striegel26

    @alex-warkentin ja mir kam das auch komisch vor mit der ID11 aber schau ...... oder verstehe ich da was falsch? WR mit 16 und 1 mein fehler 16 ist gelöscht natürlich.
    Meter.jpeg
    Log_PV.txt

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

    @striegel26 Ich bin mir da nicht sicher. Bei mir steht dort auch die 11 drin, aber ich habe die 0 von Anfang an stehen gelassen und damit funktioniert es.

    S 1 Antwort Letzte Antwort
    0
    • Alex WarkentinA Alex Warkentin

      @striegel26 Ich bin mir da nicht sicher. Bei mir steht dort auch die 11 drin, aber ich habe die 0 von Anfang an stehen gelassen und damit funktioniert es.

      S Offline
      S Offline
      striegel26
      schrieb am zuletzt editiert von
      #54

      @alex-warkentin Oh man ja die 0 ist es !!! Danke dir 😊 Jetzt funktioniert alles

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

        Hallo an alle Wissenden 🙂
        Funktioniert dieses Skript auch ohne Speicher?
        Ich hab leider keinen Speicher was muss ich dann daran ändern.
        Für mich ist JS Neuland.
        Wäre schön wenn mir jemand helfen könnte.
        Danke im Voraus Gruß Jürgen.

        
        javascript.0
        2023-03-05 09:56:27.826	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 38200 from id: undefined with error: undefined
        
        javascript.0
        2023-03-05 09:56:25.826	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 37800 from id: undefined with error: undefined
        
        javascript.0
        2023-03-05 09:56:23.824	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 37700 from id: undefined with error: undefined
        
        javascript.0
        2023-03-05 09:56:21.826	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 37000 from id: undefined with error: undefined
        
        javascript.0
        2023-03-05 09:56:19.823	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 32000 from id: undefined with error: undefined
        
        javascript.0
        2023-03-05 09:56:17.823	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 37100 from id: undefined with error: undefined
        
        javascript.0
        2023-03-05 09:56:15.823	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 30000 from id: undefined with error: undefined
        
        javascript.0
        2023-03-05 09:56:13.821	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 35300 from id: undefined with error: undefined
        
        javascript.0
        2023-03-05 09:56:11.820	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 38400 from id: undefined with error: undefined
        
        javascript.0
        2023-03-05 09:56:09.820	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 38300 from id: undefined with error: undefined
        
        javascript.0
        2023-03-05 09:56:07.819	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 38200 from id: undefined with error: undefined
        
        javascript.0
        2023-03-05 09:56:05.819	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 37800 from id: undefined with error: undefined
        
        javascript.0
        2023-03-05 09:56:03.820	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 37700 from id: undefined with error: undefined
        
        javascript.0
        2023-03-05 09:56:01.819	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 37000 from id: undefined with error: undefined
        
        javascript.0
        2023-03-05 09:55:59.817	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 32000 from id: undefined with error: undefined
        
        javascript.0
        2023-03-05 09:55:57.817	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 37100 from id: undefined with error: undefined
        
        javascript.0
        2023-03-05 09:55:55.817	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 30000 from id: undefined with error: undefined
        
        javascript.0
        2023-03-05 09:55:53.817	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 35300 from id: undefined with error: undefined
        
        javascript.0
        2023-03-05 09:55:51.818	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 38400 from id: undefined with error: undefined
        
        javascript.0
        2023-03-05 09:55:49.816	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 38300 from id: undefined with error: undefined
        
        javascript.0
        2023-03-05 09:55:47.816	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 38200 from id: undefined with error: undefined
        
        javascript.0
        2023-03-05 09:55:45.815	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 37800 from id: undefined with error: undefined
        
        javascript.0
        2023-03-05 09:55:43.815	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 37700 from id: undefined with error: undefined
        
        javascript.0
        2023-03-05 09:55:41.815	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 37000 from id: undefined with error: undefined
        
        javascript.0
        2023-03-05 09:55:39.815	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 32000 from id: undefined with error: undefined
        
        javascript.0
        2023-03-05 09:55:37.814	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 37100 from id: undefined with error: undefined
        
        javascript.0
        2023-03-05 09:55:35.814	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 30000 from id: undefined with error: undefined
        
        A Alex WarkentinA 2 Antworten Letzte Antwort
        0
        • J juggi1962

          Hallo an alle Wissenden 🙂
          Funktioniert dieses Skript auch ohne Speicher?
          Ich hab leider keinen Speicher was muss ich dann daran ändern.
          Für mich ist JS Neuland.
          Wäre schön wenn mir jemand helfen könnte.
          Danke im Voraus Gruß Jürgen.

          
          javascript.0
          2023-03-05 09:56:27.826	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 38200 from id: undefined with error: undefined
          
          javascript.0
          2023-03-05 09:56:25.826	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 37800 from id: undefined with error: undefined
          
          javascript.0
          2023-03-05 09:56:23.824	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 37700 from id: undefined with error: undefined
          
          javascript.0
          2023-03-05 09:56:21.826	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 37000 from id: undefined with error: undefined
          
          javascript.0
          2023-03-05 09:56:19.823	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 32000 from id: undefined with error: undefined
          
          javascript.0
          2023-03-05 09:56:17.823	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 37100 from id: undefined with error: undefined
          
          javascript.0
          2023-03-05 09:56:15.823	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 30000 from id: undefined with error: undefined
          
          javascript.0
          2023-03-05 09:56:13.821	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 35300 from id: undefined with error: undefined
          
          javascript.0
          2023-03-05 09:56:11.820	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 38400 from id: undefined with error: undefined
          
          javascript.0
          2023-03-05 09:56:09.820	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 38300 from id: undefined with error: undefined
          
          javascript.0
          2023-03-05 09:56:07.819	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 38200 from id: undefined with error: undefined
          
          javascript.0
          2023-03-05 09:56:05.819	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 37800 from id: undefined with error: undefined
          
          javascript.0
          2023-03-05 09:56:03.820	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 37700 from id: undefined with error: undefined
          
          javascript.0
          2023-03-05 09:56:01.819	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 37000 from id: undefined with error: undefined
          
          javascript.0
          2023-03-05 09:55:59.817	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 32000 from id: undefined with error: undefined
          
          javascript.0
          2023-03-05 09:55:57.817	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 37100 from id: undefined with error: undefined
          
          javascript.0
          2023-03-05 09:55:55.817	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 30000 from id: undefined with error: undefined
          
          javascript.0
          2023-03-05 09:55:53.817	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 35300 from id: undefined with error: undefined
          
          javascript.0
          2023-03-05 09:55:51.818	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 38400 from id: undefined with error: undefined
          
          javascript.0
          2023-03-05 09:55:49.816	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 38300 from id: undefined with error: undefined
          
          javascript.0
          2023-03-05 09:55:47.816	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 38200 from id: undefined with error: undefined
          
          javascript.0
          2023-03-05 09:55:45.815	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 37800 from id: undefined with error: undefined
          
          javascript.0
          2023-03-05 09:55:43.815	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 37700 from id: undefined with error: undefined
          
          javascript.0
          2023-03-05 09:55:41.815	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 37000 from id: undefined with error: undefined
          
          javascript.0
          2023-03-05 09:55:39.815	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 32000 from id: undefined with error: undefined
          
          javascript.0
          2023-03-05 09:55:37.814	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 37100 from id: undefined with error: undefined
          
          javascript.0
          2023-03-05 09:55:35.814	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 30000 from id: undefined with error: undefined
          
          A Offline
          A Offline
          ATARI
          schrieb am zuletzt editiert von ATARI
          #56

          @juggi1962

          Bin auch nicht so fit in js..
          ändere mal die Einstellung für den Speicher.

          zum Bsp.:
          const BatteryUnits = [0, 0];

          Gruß
          ATARI

          Edit:
          Deinem Log zufolge bekommst Du keine Daten von der Anlage.
          Hast Du in den Kom.einstellung des Wechselrichters den ModBus
          aktiviert?

          Raspberry Pi 5B (ioB via pi OS_lite(64bit) | Synology NAS (ioB via Docker)

          J 1 Antwort Letzte Antwort
          0
          • K Kachel

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

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

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

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

            der Kachel

            // License: Beerware! Do what ever you like with this, but I'm not liable for anything that you do with it.
            // If you like this code, feel free to buy me a beer ...
            // Have fun with it! der Kachel
            var ModbusRTU = require("modbus-serial");
            var client = new ModbusRTU();
            
            var modbusErrorMessages = [
                "Unknown error",
                "Illegal function (device does not support this read/write function)",
                "Illegal data address (register not supported by device)",
                "Illegal data value (value cannot be written to this register)",
                "Slave device failure (device reports internal error)",
                "Acknowledge (requested data will be available later)",
                "Slave device busy (retry request again later)"
            ];
            
            // open connection to a tcp line
            client.setTimeout(10000);
            
            // Enter your inverter modbus IP and port here:
            client.connectTCP("$$$ADD.YOUR.IP.HERE$$$", { port: 502 });
            // Enter the Modbus-IDs of your Sun2000 inverters here:
            const ModBusIDs = [16, 1];
            // On which Modbus-ID can we reach the power meter? (via Sun2000!)
            const PowerMeterID = 0;
            // Enter your battery stack setup. 2 dimensional array. 
            // e.g. [[3, 2], [3, 0]] means:
            // First inverter has two battery stacks with 3 + 2 battery modules
            // while second inverter has only one battery stack with 3 battery modules
            const BatteryUnits = [[3, 0], [3, 0]];
            
            // These register spaces need to be read:
            const RegisterSpacesToReadContinuously = [[30000, 81], [37100, 114], [32000, 116], [37000, 68],  [37700, 100], [37800, 100], [38200, 100], [38300, 100], [38400, 100], [35300, 40]];
            var RegisterSpacesToReadContinuouslyPtr = 0;
            
            var GlobalDataBuffer = new Array(2);
            for(var i=0; i<ModBusIDs.length; i++) {
                GlobalDataBuffer[i] = new Array(50000); // not optimized....
            }
            
            // ---------------------------------------------------------------
            // Some helper functions:
            function readUnsignedInt16(array) {
                var value = array[0];    
                return value;
            }
            
            function readUnsignedInt32(array) {
                var value = array[0] * 256 * 256 + array[1];    
                return value;
            }
            
            function readSignedInt16(array) {
                var value = 0;
                if (array[0] > 32767)
                    value = array[0] - 65535; 
                else
                    value = array[0];
            
                return value;
            }
            function readSignedInt32(array) {
                var value = 0;
                for (var i = 0; i < 2; i++) {
                    value = (value << 16) | array[i];
                }
                return value;
            }
            function getU16(dataarray, index) {
                var value = readUnsignedInt16(dataarray.slice(index, index+1));
                return value;
            }
            
            function getU32(dataarray, index) {
                var value = readUnsignedInt32(dataarray.slice(index, index+2));
                return value;
            }
            
            function getI16(dataarray, index) {
                var value = readSignedInt16(dataarray.slice(index, index+1));
                return value;
            }
            
            function getI32(dataarray, index) {
                var value = readSignedInt32(dataarray.slice(index, index+2));
                return value;
            }
            
            function getString(dataarray, index, length) {
                var shortarray = dataarray.slice(index, index+length);
                var bytearray = [];
                for(var i = 0; i < length; i++) {
                    bytearray.push(dataarray[index+i] >> 8);
                    bytearray.push(dataarray[index+i] & 0xff);
                }       
                var value =  String.fromCharCode.apply(null, bytearray);    
                return value;
            }
            
            function getZeroTerminatedString(dataarray, index, length) {
                var shortarray = dataarray.slice(index, index+length);
                var bytearray = [];
                for(var i = 0; i < length; i++) {
                    bytearray.push(dataarray[index+i] >> 8);
                    bytearray.push(dataarray[index+i] & 0xff);
                }       
                var value =  String.fromCharCode.apply(null, bytearray);    
                var value2 = new String(value).trim();
                return value2;
            }
            
            function forcesetState(objectname, value, options) {
                if(!existsState(objectname)) {
                    createState(objectname, value, options);        
                }
                else {
                    setState(objectname, value);
                }
            }  
            // ---------------------------------------------------------------
            // Functions to map registers into ioBreaker objects:
            function processOptimizers(id) {
                forcesetState("Solarpower.Huawei.Inverter." + id + ".OptimizerTotalNumber",     getU16(GlobalDataBuffer[id-1], 35200), {name: "", unit: ""});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".OptimizerOnlineNumber",    getU16(GlobalDataBuffer[id-1], 35201), {name: "", unit: ""});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".OptimizerFeatureData",     getU16(GlobalDataBuffer[id-1], 35202), {name: "", unit: ""});
            }
            
            function processInverterPowerAdjustments(id) {
                forcesetState("Solarpower.Huawei.Inverter." + id + ".ActiveAdjustement.ActiveAdjustementMode",     getU16(GlobalDataBuffer[id-1], 35300), {name: "", unit: ""});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".ActiveAdjustement.ActiveAdjustementValue",    getU32(GlobalDataBuffer[id-1], 35301), {name: "", unit: ""}); // Note: This might be an error in the manual. It says register 35302 with quantity 2, but on 35303 is already the next value.
                forcesetState("Solarpower.Huawei.Inverter." + id + ".ActiveAdjustement.ActiveAdjustementCommand",  getU16(GlobalDataBuffer[id-1], 35303), {name: "", unit: ""});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".ActiveAdjustement.ReactiveAdjustementMode",   getU16(GlobalDataBuffer[id-1], 35304), {name: "", unit: ""});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".ActiveAdjustement.ReactiveAdjustementValue",  getU32(GlobalDataBuffer[id-1], 35305), {name: "", unit: ""});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".ActiveAdjustement.ReactiveAdjustementCommand",getU16(GlobalDataBuffer[id-1], 35307), {name: "", unit: ""});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".ActiveAdjustement.PowerMeterActivePower",     getI32(GlobalDataBuffer[id-1], 35313), {name: "", unit: ""});
            }
            
            function processBattery(id) {
                // Battery registers 1-15 (Stack 1 related)
                if(BatteryUnits[id-1][0] > 0) {
                    forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.RunningStatus",          getU16(GlobalDataBuffer[id-1], 37000), {name: "", unit: ""});
                    forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.ChargeAndDischargePower",getI32(GlobalDataBuffer[id-1], 37001), {name: "Charge and Discharge Power", unit: "W"});
                    forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.BusVoltage",             getU16(GlobalDataBuffer[id-1], 37003) / 10, {name: "Busvoltage", unit: "V"});
                    forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.BatterySOC",             getU16(GlobalDataBuffer[id-1], 37004) / 10, {name: "Battery SOC", unit: "%"});
                    forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.WorkingMode",            getU16(GlobalDataBuffer[id-1], 37006), {name: "Working Mode", unit: ""});
                    forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.RatedChargePower",       getU32(GlobalDataBuffer[id-1], 37007), {name: "", unit: "W"});
                    forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.RatedDischargePower",    getU32(GlobalDataBuffer[id-1], 37009), {name: "", unit: "W"});
                    forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.FaultID",                getU16(GlobalDataBuffer[id-1], 37014), {name: "", unit: ""});
                    forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.CurrentDayChargeCapacity",    getU32(GlobalDataBuffer[id-1], 37015) / 100, {name: "", unit: "kWh"});
                    forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.CurrentDayDischargeCapacity", getU32(GlobalDataBuffer[id-1], 37017) / 100, {name: "", unit: "kWh"});
                    forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.BusCurrent",             getI16(GlobalDataBuffer[id-1], 37021) / 10, {name: "Buscurrent", unit: "A"});
                    forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.BatteryTemperature",     getI16(GlobalDataBuffer[id-1], 37022) / 10, {name: "Battery Temperatue", unit: "°C"});
                    forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.RemainingChargeDischargeTime", getU16(GlobalDataBuffer[id-1], 37025), {name: "", unit: "mins"});
                    forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.DCDCversion",            getZeroTerminatedString(GlobalDataBuffer[id-1], 37026, 10), {name: "", unit: ""});
                    forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.BMSversion",             getZeroTerminatedString(GlobalDataBuffer[id-1], 37036, 10), {name: "", unit: ""});
                }
                // Battery registers 16+17 (Storage-related)
                forcesetState("Solarpower.Huawei.Inverter." + id + ".Battery.MaximumChargePower",                getU32(GlobalDataBuffer[id-1], 37046), {name: "", unit: "W"});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".Battery.MaximumDischargePower",             getU32(GlobalDataBuffer[id-1], 37048), {name: "", unit: "W"});
            
                // Battery register 18-20 (Stack 1 related)
                if(BatteryUnits[id-1][0] > 0) {
                forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.SN",                         getZeroTerminatedString(GlobalDataBuffer[id-1], 37052, 10), {name: "Serialnumber", unit: ""});       
                forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.TotalCharge",                getU32(GlobalDataBuffer[id-1], 37066) / 100, {name: "", unit: "kWh"});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.TotalDischarge",             getU32(GlobalDataBuffer[id-1], 37068) / 100, {name: "", unit: "kWh"});
                }
                // Battery register 21-31 (Stack 2 related)
                if(BatteryUnits[id-1][1] > 0) {
                    forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.2.SN",                     getZeroTerminatedString(GlobalDataBuffer[id-1], 37700, 10), {name: "Serialnumber", unit: ""});        
                    forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.2.BatterySOC",             getU16(GlobalDataBuffer[id-1], 37738) / 10, {name: "", unit: "%"});
                    forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.2.RunningStatus",          getU16(GlobalDataBuffer[id-1], 37741), {name: "", unit: ""});
                    forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.2.ChargeAndDischargePower",getI32(GlobalDataBuffer[id-1], 37743), {name: "", unit: "W"});
                    forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.2.CurrentDayChargeCapacity",    getU32(GlobalDataBuffer[id-1], 37746) / 100, {name: "", unit: "kWh"});
                    forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.2.CurrentDayDischargeCapacity", getU32(GlobalDataBuffer[id-1], 37748) / 100, {name: "", unit: "kWh"});
                    forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.2.BusVoltage",             getU16(GlobalDataBuffer[id-1], 37750) / 10, {name: "", unit: "V"});
                    forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.2.BusCurrent",             getI16(GlobalDataBuffer[id-1], 37751) / 10, {name: "", unit: "A"});
                    forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.2.BatteryTemperature",     getI16(GlobalDataBuffer[id-1], 37752) / 10, {name: "", unit: "°C"});
                    forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.2.TotalCharge",                 getU32(GlobalDataBuffer[id-1], 37753) / 100, {name: "", unit: "kWh"});
                    forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.2.TotalDischarge",              getU32(GlobalDataBuffer[id-1], 37755) / 100, {name: "", unit: "kWh"});
                }
                // Battery register 32-41 (Storage related)
                forcesetState("Solarpower.Huawei.Inverter." + id + ".Battery.RatedCapacity", getU32(GlobalDataBuffer[id-1], 37758) / 1, {name: "", unit: "Wh"});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".Battery.SOC", getU16(GlobalDataBuffer[id-1], 37760) / 10, {name: "", unit: "%"});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".Battery.RunningStatus", getU16(GlobalDataBuffer[id-1], 37762) / 1, {name: "", unit: ""});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".Battery.BusVoltage", getU16(GlobalDataBuffer[id-1], 37763) / 10, {name: "", unit: "V"});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".Battery.BusCurrent", getI16(GlobalDataBuffer[id-1], 37764) / 10, {name: "", unit: "A"});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".Battery.ChargeAndDischargePower", getI32(GlobalDataBuffer[id-1], 37765) / 1, {name: "", unit: "W"});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".Battery.TotalCharge", getU32(GlobalDataBuffer[id-1], 37780) / 100, {name: "", unit: "kWh"});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".Battery.TotalDischarge", getU32(GlobalDataBuffer[id-1], 37782) / 100, {name: "", unit: "kWh"});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".Battery.CurrentDayChargeCapacity", getU32(GlobalDataBuffer[id-1], 37784) / 100, {name: "", unit: "kWh"});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".Battery.CurrentDayDischargeCapacity", getU32(GlobalDataBuffer[id-1], 37786) / 100, {name: "Current DayDiscarge ", unit: "kWh"});
            
                // Battery registers 42+43 (Battery stack related)   
                if(BatteryUnits[id-1][1] > 0) {
                    forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.2.SoftwareVersion",    getZeroTerminatedString(GlobalDataBuffer[id-1], 37814, 8), {name: "Softwareversion", unit: ""});
                }
                if(BatteryUnits[id-1][0] > 0) {
                    forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack.1.SoftwareVersion",    getZeroTerminatedString(GlobalDataBuffer[id-1], 37799, 8), {name: "Softwareversion", unit: ""});
                }
            
                // Registers 44 to 98: (Battery pack related)
                for(var i = 1; i <= 2; i++){        
                    if(BatteryUnits[id-1][i-1] >= 0) {            
                        for(var j = 1; j <= BatteryUnits[id-1][i-1]; j++) {
                            //[[38200, 38242, 38284] [38326, 38368, 38410]]; (+42 for each battery pack, +126 for each stack)
                            forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".SN",                getZeroTerminatedString(GlobalDataBuffer[id-1], 38200+(i-1)*126+(j-1)*42, 6), {name: "", unit: ""});
                            forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".FirmwareVersion",   getZeroTerminatedString(GlobalDataBuffer[id-1], 38210+(i-1)*126+(j-1)*42, 8), {name: "", unit: ""});
                            forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".WorkingStatus",     getU16(GlobalDataBuffer[id-1], 38228+(i-1)*126+(j-1)*42), {name: "", unit: ""});
                            forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".BatterySOC",        getU16(GlobalDataBuffer[id-1], 38229+(i-1)*126+(j-1)*42) / 10, {name: "", unit: "%"});
                            forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".ChargeAndDischargePower", getI32(GlobalDataBuffer[id-1], 38233+(i-1)*126+(j-1)*42) / 1000, {name: "", unit: "kW"});
                            forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".Voltage",           getU16(GlobalDataBuffer[id-1], 38235+(i-1)*126+(j-1)*42) / 10, {name: "", unit: "V"});
                            forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".Current",           getI16(GlobalDataBuffer[id-1], 38236+(i-1)*126+(j-1)*42) / 10, {name: "", unit: "A"});
                            forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".TotalCharge",       getU32(GlobalDataBuffer[id-1], 38238+(i-1)*126+(j-1)*42) / 100, {name: "", unit: "kWh"});
                            forcesetState("Solarpower.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".TotalDischarge",    getU32(GlobalDataBuffer[id-1], 38240+(i-1)*126+(j-1)*42) / 100, {name: "", unit: "kWh"});
            
                            // [[38452, 38454, 38456][38458, 38460, 38462]] ( +2 for each pack, +6 for each stack)
                            createState("Solarpower.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".MaxTemperature", getI16(GlobalDataBuffer[id-1], 38452+(i-1)*6+(j-1)*2) / 10, {name: "", unit: "°C"});
                            createState("Solarpower.Huawei.Inverter." + id + ".Batterystack." + i + ".Battery" + j + ".MinTemperature", getI16(GlobalDataBuffer[id-1], 38453+(i-1)*6+(j-1)*2) / 10, {name: "", unit: "°C"});
                        }
                    }        
                }
            
                // Battery registers 110-141 are not supported by this script yet!
            }
            
            function ProcessPowerMeterStatus() {       
                forcesetState("Solarpower.Huawei.Meter.Status",          getU16(GlobalDataBuffer[PowerMeterID], 37100), {name: "", unit: ""});
                forcesetState("Solarpower.Huawei.Meter.VoltageL1",        getI32(GlobalDataBuffer[PowerMeterID], 37101)  / 10, {name: "", unit: "V"});
                forcesetState("Solarpower.Huawei.Meter.VoltageL2",        getI32(GlobalDataBuffer[PowerMeterID], 37103)  / 10, {name: "", unit: "V"});
                forcesetState("Solarpower.Huawei.Meter.VoltageL3",        getI32(GlobalDataBuffer[PowerMeterID], 37105)  / 10, {name: "", unit: "V"});
                forcesetState("Solarpower.Huawei.Meter.CurrentL1",        getI32(GlobalDataBuffer[PowerMeterID], 37107)  / 100, {name: "", unit: "A"});
                forcesetState("Solarpower.Huawei.Meter.CurrentL2",        getI32(GlobalDataBuffer[PowerMeterID], 37109)  / 100, {name: "", unit: "A"});
                forcesetState("Solarpower.Huawei.Meter.CurrentL3",        getI32(GlobalDataBuffer[PowerMeterID], 37111) / 100, {name: "", unit: "A"});
                forcesetState("Solarpower.Huawei.Meter.ActivePower",     getI32(GlobalDataBuffer[PowerMeterID], 37113) / 1, {name: "", unit: "W"});
                forcesetState("Solarpower.Huawei.Meter.ReactivePower",   getI32(GlobalDataBuffer[PowerMeterID], 37115) / 1, {name: "", unit: "Var"});
                forcesetState("Solarpower.Huawei.Meter.PowerFactor",     getI16(GlobalDataBuffer[PowerMeterID], 37117) / 1000, {name: "", unit: ""});
                forcesetState("Solarpower.Huawei.Meter.GridFrequency",   getI16(GlobalDataBuffer[PowerMeterID], 37118) / 100, {name: "", unit: "Hz"});
                forcesetState("Solarpower.Huawei.Meter.PositiveActiveEnergy",     getI32(GlobalDataBuffer[PowerMeterID], 37119) / 100, {name: "", unit: "kWh"});
                forcesetState("Solarpower.Huawei.Meter.ReverseActiveEnergy",      getI32(GlobalDataBuffer[PowerMeterID], 37121) / 100, {name: "", unit: "kWh"});
                forcesetState("Solarpower.Huawei.Meter.AccumulatedReactivePower", getI32(GlobalDataBuffer[PowerMeterID], 37123) / 100, {name: "", unit: "kVarh"});
                forcesetState("Solarpower.Huawei.Meter.MeterType",       getU16(GlobalDataBuffer[PowerMeterID], 37125), {name: "", unit: ""});
                forcesetState("Solarpower.Huawei.Meter.VoltageL1-L2",       getI32(GlobalDataBuffer[PowerMeterID], 37126) / 10, {name: "", unit: "V"});
                forcesetState("Solarpower.Huawei.Meter.VoltageL2-L3",       getI32(GlobalDataBuffer[PowerMeterID], 37128) / 10, {name: "", unit: "V"});
                forcesetState("Solarpower.Huawei.Meter.VoltageL3-L1",       getI32(GlobalDataBuffer[PowerMeterID], 37130) / 10, {name: "", unit: "V"});
                forcesetState("Solarpower.Huawei.Meter.ActivePowerL1",    getI32(GlobalDataBuffer[PowerMeterID], 37132) / 1, {name: "", unit: "W"});
                forcesetState("Solarpower.Huawei.Meter.ActivePowerL2",    getI32(GlobalDataBuffer[PowerMeterID], 37134) / 1, {name: "", unit: "W"});
                forcesetState("Solarpower.Huawei.Meter.ActivePowerL3",    getI32(GlobalDataBuffer[PowerMeterID], 37136) / 1, {name: "", unit: "W"});
                forcesetState("Solarpower.Huawei.Meter.MeterModel",      getU16(GlobalDataBuffer[PowerMeterID], 37138), {name: "", unit: ""});
            }
            
            function processInverterStatus(id) {
                forcesetState("Solarpower.Huawei.Inverter." + id + ".State1", getU16(GlobalDataBuffer[id-1], 32000), {name: "", unit: ""});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".State2", getU16(GlobalDataBuffer[id-1], 32001), {name: "", unit: ""});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".State3", getU16(GlobalDataBuffer[id-1], 32002), {name: "", unit: ""});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".Alarm1", getU16(GlobalDataBuffer[id-1], 32008), {name: "", unit: ""});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".Alarm2", getU16(GlobalDataBuffer[id-1], 32009), {name: "", unit: ""});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".Alarm3", getU16(GlobalDataBuffer[id-1], 32010), {name: "", unit: ""});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".String.1_Voltage",       getI16(GlobalDataBuffer[id-1], 32016) / 10  , {name: "", unit: "V"});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".String.1_Current",       getI16(GlobalDataBuffer[id-1], 32017) / 100 , {name: "", unit: "A"});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".String.2_Voltage",       getI16(GlobalDataBuffer[id-1], 32018) / 10  , {name: "", unit: "V"});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".String.2_Current",       getI16(GlobalDataBuffer[id-1], 32019) / 100 , {name: "", unit: "A"});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".InputPower",             getI32(GlobalDataBuffer[id-1], 32064) / 1000, {name: "", unit: "kW"});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1-L2_Voltage",           getU16(GlobalDataBuffer[id-1], 32066) / 10  , {name: "", unit: "V"});      
                forcesetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2-L3_Voltage",           getU16(GlobalDataBuffer[id-1], 32067) / 10  , {name: "", unit: "V"});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3-L1_Voltage",           getU16(GlobalDataBuffer[id-1], 32068) / 10  , {name: "", unit: "V"});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1_Voltage",            getU16(GlobalDataBuffer[id-1], 32069) / 10  , {name: "", unit: "V"});                              
                forcesetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2_Voltage",            getU16(GlobalDataBuffer[id-1], 32070) / 10  , {name: "", unit: "V"});                                                  
                forcesetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3_Voltage",            getU16(GlobalDataBuffer[id-1], 32071) / 10  , {name: "", unit: "V"});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".Grid.L1_Current",         getI32(GlobalDataBuffer[id-1], 32072) / 1000, {name: "", unit: "A"});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".Grid.L2_Current",         getI32(GlobalDataBuffer[id-1], 32074) / 1000, {name: "", unit: "A"});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".Grid.L3_Current",         getI32(GlobalDataBuffer[id-1], 32076) / 1000, {name: "", unit: "A"});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".PeakActivePowerDay",     getI32(GlobalDataBuffer[id-1], 32078) / 1000, {name: "", unit: "kW"});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".ActivePower",            getI32(GlobalDataBuffer[id-1], 32080) / 1000, {name: "", unit: "kW"});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".ReactivePower",          getI32(GlobalDataBuffer[id-1], 32082) / 1000, {name: "", unit: "kVar"});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".PowerFactor",            getI16(GlobalDataBuffer[id-1], 32084) / 1000, {name: "", unit: ""});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".GridFrequency",          getU16(GlobalDataBuffer[id-1], 32085) / 100 , {name: "", unit: "Hz"});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".Efficiency",             getU16(GlobalDataBuffer[id-1], 32086) / 100 , {name: "", unit: "%"});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".InternalTemperature",    getI16(GlobalDataBuffer[id-1], 32087) / 10  , {name: "", unit: "°C"});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".InsulationResistance",   getU16(GlobalDataBuffer[id-1], 32088) / 1000, {name: "", unit: "MOhm"});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".DeviceStatus",              getU16(GlobalDataBuffer[id-1], 32089), {name: "", unit: ""});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".FaultCode",                 getU16(GlobalDataBuffer[id-1], 32090), {name: "", unit: ""});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".StartupTime",               getU16(GlobalDataBuffer[id-1], 32091), {name: "", unit: ""});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".ShutdownTime",              getU16(GlobalDataBuffer[id-1], 32093), {name: "", unit: ""});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".AccomulatedEnergyYield",    getU16(GlobalDataBuffer[id-1], 32106), {name: "", unit: "kWh"});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".DailyEnergyYield",          getU16(GlobalDataBuffer[id-1], 32114), {name: "", unit: "kWh"});
            }
            
            function ProcessDeviceInfo(id) {      
                // Note: Manual says its quantitiy is 15, but that is the number (+1) of 8bit characters
                forcesetState("Solarpower.Huawei.Inverter." + id + ".Model",  getZeroTerminatedString(GlobalDataBuffer[id-1], 30000, 8), {name: "", unit: ""}); 
                forcesetState("Solarpower.Huawei.Inverter." + id + ".SN",     getZeroTerminatedString(GlobalDataBuffer[id-1], 30015, 6), {name: "", unit: ""});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".PN",     getZeroTerminatedString(GlobalDataBuffer[id-1], 30025, 6), {name: "", unit: ""});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".ModelID",           getU16(GlobalDataBuffer[id-1], 30070), {name: "", unit: ""});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".PVStrings",         getU16(GlobalDataBuffer[id-1], 30071), {name: "", unit: ""});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".MPPTrackers",       getU16(GlobalDataBuffer[id-1], 30072), {name: "", unit: ""});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".MaxRatedPower",     getU32(GlobalDataBuffer[id-1], 30073) / 1000, {name: "", unit: "kW"});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".MaxActivePower",    getU32(GlobalDataBuffer[id-1], 30075) / 1000, {name: "", unit: "kW"});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".MaxApparentPower",  getU32(GlobalDataBuffer[id-1], 30077) / 1000, {name: "", unit: "kVA"});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".MaxReactivePowerToGrid",        getI32(GlobalDataBuffer[id-1], 30079) / 1000, {name: "", unit: "kVAr"});
                forcesetState("Solarpower.Huawei.Inverter." + id + ".MaxReactivePowerFromGrid",      getI32(GlobalDataBuffer[id-1], 30081) / 1000, {name: "", unit: "kVAr"});
            }
            
            function readRegisterSpace(id, address, length) {
                client.setID(ModBusIDs[id-1]);
                client.readHoldingRegisters(address, length, function(err, data) {
                    if (err) {
                        console.warn("Error received reading address " + address + " from id: " + ModBusIDs[id-1] + " with error: " + modbusErrorMessages[err.modbusCode]);            
                    }
                    else
                    {   
                        console.debug("Read data from id/address " + ModBusIDs[id-1] + "/" + address + "\nData is: " + data.data);
                        for(var i = 0; i < length; i++)  {
                            GlobalDataBuffer[id-1][address+i] = data.data[i];
                        } 
                    }
                });
            }
            
            function processData() {
                console.log("Processing new data...");
                for(var i = 1; i <= ModBusIDs.length; i++) {
                    ProcessDeviceInfo(i);
                    processInverterStatus(i);
                    processBattery(i);
                    processInverterPowerAdjustments(i);
                    processOptimizers(i); 
                }    
                ProcessPowerMeterStatus();
                console.log("Processing done!");
            }
            
            
            // -------------------------------------------------------------------
            // This is the main function triggering a  read via modbus-tcp every two seconds.
            // Processing of data is triggered as soon as one complete set of registers is copied.
            var triggerprocessing = 0; 
            var currentinverter = 1;
            
            
            setInterval(function() {
                if(triggerprocessing == 1) {
                    triggerprocessing = 0;
                    processData();        
                }      
               
                console.log("Triggering read of inverter " + currentinverter + " at address " + RegisterSpacesToReadContinuously[RegisterSpacesToReadContinuouslyPtr][0] + " with length " +  RegisterSpacesToReadContinuously[RegisterSpacesToReadContinuouslyPtr][1]);
                readRegisterSpace(currentinverter, RegisterSpacesToReadContinuously[RegisterSpacesToReadContinuouslyPtr][0], RegisterSpacesToReadContinuously[RegisterSpacesToReadContinuouslyPtr][1]); 
                RegisterSpacesToReadContinuouslyPtr++;               
                if(RegisterSpacesToReadContinuouslyPtr >= RegisterSpacesToReadContinuously.length) {
                    RegisterSpacesToReadContinuouslyPtr = 0;
                    currentinverter++
                    if(currentinverter > ModBusIDs.length){
                        currentinverter = 1;  
                        triggerprocessing = 1;                    
                    }
                }     
            }, 2000);
            
            A Offline
            A Offline
            ATARI
            schrieb am zuletzt editiert von ATARI
            #57

            @kachel

            Vielen Dank für das Script und Deine Arbeit !

            Wie kann ich den Abfrage Intervall nach einem Durchlauf verzögern
            oder nur einmal pro Minute oder alle 5 Minuten starten lassen?
            Ein Timer mit: von Uhrzeit bis Uhrzeit alle x Minuten wäre auch super.

            Momentan bekommt das Script irgendwann im Laufe des Tages keine
            Daten mehr und erzeugt nur noch Fehlermeldungen.
            In diesem Fall hilft nur: das Script stoppen und nach einigen Minuten
            wieder starten.

            Gruß
            ATARI

            Edit:
            Würde Dir für Deine Arbeit 'nen Kaffee oder 'n Bier spendieren.

            Raspberry Pi 5B (ioB via pi OS_lite(64bit) | Synology NAS (ioB via Docker)

            Alex WarkentinA J H 3 Antworten Letzte Antwort
            0
            • J juggi1962

              Hallo an alle Wissenden 🙂
              Funktioniert dieses Skript auch ohne Speicher?
              Ich hab leider keinen Speicher was muss ich dann daran ändern.
              Für mich ist JS Neuland.
              Wäre schön wenn mir jemand helfen könnte.
              Danke im Voraus Gruß Jürgen.

              
              javascript.0
              2023-03-05 09:56:27.826	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 38200 from id: undefined with error: undefined
              
              javascript.0
              2023-03-05 09:56:25.826	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 37800 from id: undefined with error: undefined
              
              javascript.0
              2023-03-05 09:56:23.824	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 37700 from id: undefined with error: undefined
              
              javascript.0
              2023-03-05 09:56:21.826	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 37000 from id: undefined with error: undefined
              
              javascript.0
              2023-03-05 09:56:19.823	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 32000 from id: undefined with error: undefined
              
              javascript.0
              2023-03-05 09:56:17.823	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 37100 from id: undefined with error: undefined
              
              javascript.0
              2023-03-05 09:56:15.823	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 30000 from id: undefined with error: undefined
              
              javascript.0
              2023-03-05 09:56:13.821	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 35300 from id: undefined with error: undefined
              
              javascript.0
              2023-03-05 09:56:11.820	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 38400 from id: undefined with error: undefined
              
              javascript.0
              2023-03-05 09:56:09.820	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 38300 from id: undefined with error: undefined
              
              javascript.0
              2023-03-05 09:56:07.819	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 38200 from id: undefined with error: undefined
              
              javascript.0
              2023-03-05 09:56:05.819	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 37800 from id: undefined with error: undefined
              
              javascript.0
              2023-03-05 09:56:03.820	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 37700 from id: undefined with error: undefined
              
              javascript.0
              2023-03-05 09:56:01.819	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 37000 from id: undefined with error: undefined
              
              javascript.0
              2023-03-05 09:55:59.817	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 32000 from id: undefined with error: undefined
              
              javascript.0
              2023-03-05 09:55:57.817	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 37100 from id: undefined with error: undefined
              
              javascript.0
              2023-03-05 09:55:55.817	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 30000 from id: undefined with error: undefined
              
              javascript.0
              2023-03-05 09:55:53.817	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 35300 from id: undefined with error: undefined
              
              javascript.0
              2023-03-05 09:55:51.818	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 38400 from id: undefined with error: undefined
              
              javascript.0
              2023-03-05 09:55:49.816	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 38300 from id: undefined with error: undefined
              
              javascript.0
              2023-03-05 09:55:47.816	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 38200 from id: undefined with error: undefined
              
              javascript.0
              2023-03-05 09:55:45.815	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 37800 from id: undefined with error: undefined
              
              javascript.0
              2023-03-05 09:55:43.815	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 37700 from id: undefined with error: undefined
              
              javascript.0
              2023-03-05 09:55:41.815	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 37000 from id: undefined with error: undefined
              
              javascript.0
              2023-03-05 09:55:39.815	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 32000 from id: undefined with error: undefined
              
              javascript.0
              2023-03-05 09:55:37.814	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 37100 from id: undefined with error: undefined
              
              javascript.0
              2023-03-05 09:55:35.814	warn	script.js.Test.Modbus_Huawei_Sun_2000: Error received reading address 30000 from id: undefined with error: undefined
              
              Alex WarkentinA Offline
              Alex WarkentinA Offline
              Alex Warkentin
              schrieb am zuletzt editiert von
              #58

              @juggi1962
              Der Fehler besagt, dass deine ID für den Wechselrichter "undefined" ist. Welche ID hast du im Script eingestellt und hast du sie mit deinen aktuellen Einstellungen abgeglichen?

              J 1 Antwort Letzte Antwort
              0
              • A ATARI

                @kachel

                Vielen Dank für das Script und Deine Arbeit !

                Wie kann ich den Abfrage Intervall nach einem Durchlauf verzögern
                oder nur einmal pro Minute oder alle 5 Minuten starten lassen?
                Ein Timer mit: von Uhrzeit bis Uhrzeit alle x Minuten wäre auch super.

                Momentan bekommt das Script irgendwann im Laufe des Tages keine
                Daten mehr und erzeugt nur noch Fehlermeldungen.
                In diesem Fall hilft nur: das Script stoppen und nach einigen Minuten
                wieder starten.

                Gruß
                ATARI

                Edit:
                Würde Dir für Deine Arbeit 'nen Kaffee oder 'n Bier spendieren.

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

                @atari
                Das Abfrageintervall kannst du in der letzten Zeile des Scripts in ms einstellen. Dein Problem liegt wohl aber weniger am Intervall (dann kommt zwischendurch eine Warnung, dass das Gerät beschäftigt ist), sondern, dass das Script beim Verlust der Modbus-Verbindung diese nicht wieder automatisch aufbaut.

                J A 2 Antworten Letzte Antwort
                0
                • Alex WarkentinA Alex Warkentin

                  @juggi1962
                  Der Fehler besagt, dass deine ID für den Wechselrichter "undefined" ist. Welche ID hast du im Script eingestellt und hast du sie mit deinen aktuellen Einstellungen abgeglichen?

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

                  @alex-warkentin
                  Danke für deine Antwort. Soweit funktioniert jetzt alles.
                  Gibt es eigentlich eine Möglichkeit die Infos auszuschalten denn so sehe ich im Log ja nur mehr diese von dem Skript.
                  Danke für eure Hilfe

                  Alex WarkentinA 1 Antwort Letzte Antwort
                  0
                  • A ATARI

                    @juggi1962

                    Bin auch nicht so fit in js..
                    ändere mal die Einstellung für den Speicher.

                    zum Bsp.:
                    const BatteryUnits = [0, 0];

                    Gruß
                    ATARI

                    Edit:
                    Deinem Log zufolge bekommst Du keine Daten von der Anlage.
                    Hast Du in den Kom.einstellung des Wechselrichters den ModBus
                    aktiviert?

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

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

                    @juggi1962

                    Bin auch nicht so fit in js..
                    ändere mal die Einstellung für den Speicher.

                    zum Bsp.:
                    const BatteryUnits = [0, 0];

                    Gruß
                    ATARI

                    Edit:
                    Deinem Log zufolge bekommst Du keine Daten von der Anlage.
                    Hast Du in den Kom.einstellung des Wechselrichters den ModBus
                    aktiviert?

                    Danke für deine Antwort. Soweit läuft jetzt alles

                    1 Antwort Letzte Antwort
                    0
                    • J juggi1962

                      @alex-warkentin
                      Danke für deine Antwort. Soweit funktioniert jetzt alles.
                      Gibt es eigentlich eine Möglichkeit die Infos auszuschalten denn so sehe ich im Log ja nur mehr diese von dem Skript.
                      Danke für eure Hilfe

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

                      @juggi1962
                      Suche mal im Script mit STRG + F nach "console.log" und setze überall, wo dich die Information nicht interessiert "//" vor die Zeile.

                      J 1 Antwort Letzte Antwort
                      0
                      • Alex WarkentinA Alex Warkentin

                        @juggi1962
                        Suche mal im Script mit STRG + F nach "console.log" und setze überall, wo dich die Information nicht interessiert "//" vor die Zeile.

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

                        @alex-warkentin
                        Super Danke, werde ich gleich probieren

                        1 Antwort Letzte Antwort
                        0
                        • A ATARI

                          @kachel

                          Vielen Dank für das Script und Deine Arbeit !

                          Wie kann ich den Abfrage Intervall nach einem Durchlauf verzögern
                          oder nur einmal pro Minute oder alle 5 Minuten starten lassen?
                          Ein Timer mit: von Uhrzeit bis Uhrzeit alle x Minuten wäre auch super.

                          Momentan bekommt das Script irgendwann im Laufe des Tages keine
                          Daten mehr und erzeugt nur noch Fehlermeldungen.
                          In diesem Fall hilft nur: das Script stoppen und nach einigen Minuten
                          wieder starten.

                          Gruß
                          ATARI

                          Edit:
                          Würde Dir für Deine Arbeit 'nen Kaffee oder 'n Bier spendieren.

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

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

                          @kachel

                          Vielen Dank für das Script und Deine Arbeit !

                          Wie kann ich den Abfrage Intervall nach einem Durchlauf verzögern
                          oder nur einmal pro Minute oder alle 5 Minuten starten lassen?
                          Ein Timer mit: von Uhrzeit bis Uhrzeit alle x Minuten wäre auch super.

                          Momentan bekommt das Script irgendwann im Laufe des Tages keine
                          Daten mehr und erzeugt nur noch Fehlermeldungen.
                          In diesem Fall hilft nur: das Script stoppen und nach einigen Minuten
                          wieder starten.

                          Gruß
                          ATARI

                          Edit:
                          Würde Dir für Deine Arbeit 'nen Kaffee oder 'n Bier spendieren.

                          Ich habe leider das selbe Problem. Eine Weile läuft alles bestens und dann nur mehr Fehler.
                          Neustart und es läuft wieder ein Weilchen.

                          1 Antwort Letzte Antwort
                          0
                          • Alex WarkentinA Alex Warkentin

                            @atari
                            Das Abfrageintervall kannst du in der letzten Zeile des Scripts in ms einstellen. Dein Problem liegt wohl aber weniger am Intervall (dann kommt zwischendurch eine Warnung, dass das Gerät beschäftigt ist), sondern, dass das Script beim Verlust der Modbus-Verbindung diese nicht wieder automatisch aufbaut.

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

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

                            @atari
                            Das Abfrageintervall kannst du in der letzten Zeile des Scripts in ms einstellen. Dein Problem liegt wohl aber weniger am Intervall (dann kommt zwischendurch eine Warnung, dass das Gerät beschäftigt ist), sondern, dass das Script beim Verlust der Modbus-Verbindung diese nicht wieder automatisch aufbaut.

                            Ich habe das selbe Problem.
                            Ich habe eine LAN Verbindung also sollte fie Verbindung bleiben, oder verstehe ich da was falsch? was kann man da machen

                            Alex WarkentinA 1 Antwort Letzte Antwort
                            0
                            • J juggi1962

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

                              @atari
                              Das Abfrageintervall kannst du in der letzten Zeile des Scripts in ms einstellen. Dein Problem liegt wohl aber weniger am Intervall (dann kommt zwischendurch eine Warnung, dass das Gerät beschäftigt ist), sondern, dass das Script beim Verlust der Modbus-Verbindung diese nicht wieder automatisch aufbaut.

                              Ich habe das selbe Problem.
                              Ich habe eine LAN Verbindung also sollte fie Verbindung bleiben, oder verstehe ich da was falsch? was kann man da machen

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

                              @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 H 3 Antworten 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
                                #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 👍
                                        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 👍
                                          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
                                          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

                                          631

                                          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