Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. ioBroker Allgemein
    4. Huawei Sun2000 & ioBroker via JS script funktioniert

    NEWS

    • Neuer Blog: Fotos und Eindrücke aus Solingen

    • ioBroker@Smart Living Forum Solingen, 14.06. - Agenda added

    • ioBroker goes Matter ... Matter Adapter in Stable

    Huawei Sun2000 & ioBroker via JS script funktioniert

    This topic has been deleted. Only users with topic management privileges can see it.
    • bahnuhr
      bahnuhr Forum Testing Most Active @dragst3r last edited by

      @dragst3r

      was ist frigate ?
      war ist camx ?

      Bist du im richtigen thread ?

      D 1 Reply Last reply Reply Quote 0
      • D
        dragst3r @bahnuhr last edited by

        @bahnuhr
        OMG, sorry. Ich hatte nach dem Login ein 503 fehler und bin daher zum falschen Thread gekommen. Beitrag bitte löschen wenn es geht.

        bahnuhr 1 Reply Last reply Reply Quote 0
        • bahnuhr
          bahnuhr Forum Testing Most Active @dragst3r last edited by

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

          Beitrag bitte löschen

          geht nicht.

          1 Reply Last reply Reply Quote 0
          • B
            bishop last edited by bishop

            ich bin kein Script Experte aber ich benötige manche DP als bestätigt also
            ack = true

            habe das nun so gelöst

            // perform createState() only if variable does not yet exist, and perform the check via existsState() only once for each processing round
            {   if (testCreateState == 0)
                {   if (!existsState(JavaInst + objectname)) { createState(objectname, value, options); }
                    else                                            { setState(objectname, value, true); }
                } else
                {   setState(objectname, value, true);
                }
            }  
            

            also nach dem value "wert" mache ich noch ein true.
            Ist das so korrekt, kann man das so machen oder ist das falsch? Jetzt sind die ganzen Datenpunkte auch nicht mehr rot 🙂

            bahnuhr 1 Reply Last reply Reply Quote 0
            • bahnuhr
              bahnuhr Forum Testing Most Active @bishop last edited by

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

              benötige manche DP als bestätigt also
              ack = true

              Bitte mal Rückinfo warum man dies braucht ?

              B 2 Replies Last reply Reply Quote 0
              • B
                bishop @bahnuhr last edited by bishop

                @bahnuhr

                z.b. bei dem awtrix-light Adapter werden die Werte an der Uhr nicht aktualisiert wenn sie nicht bestätigt sind.
                Und die rote Farbe mag ich nicht 🙂

                bahnuhr 1 Reply Last reply Reply Quote 0
                • bahnuhr
                  bahnuhr Forum Testing Most Active @bishop last edited by

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

                  awtrix-light Adapter

                  kenn ich nicht.

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

                  Und die Rote Farbe mag ich nicht

                  Hat mich noch nie gestört.
                  Und hat bisher auch alles mit "roter Farbe" geklappt.

                  Aber ja, bei Aktoren z.B. Homematic ist es schon wichtig dass der Wert auch bestätigt wird.
                  Aber bei Daten vom Huawei Wechselrichter ?!

                  B 1 Reply Last reply Reply Quote 0
                  • B
                    bishop @bahnuhr last edited by

                    @bahnuhr
                    muss ja nicht geändert werden. Finde es halt somit abgeschlossen.

                    1 Reply Last reply Reply Quote 0
                    • B
                      bishop last edited by

                      @Chris_B
                      ist es evtl. möglich das Script um ein paar Infos zu erweitern?
                      Ich habe die Datenpunkte bei z.b.

                      {
                        "common": {
                          "name": "Solarpower.Huawei.Inverter.1.Battery.RunningStatus",
                          "unit": "",
                          "role": "state",
                          "type": "mixed",
                          "states": {
                            "0": "offline",
                            "1": "stand by",
                            "2": "running",
                            "3": "fault",
                            "4": "sleep mode"
                          }
                        },
                      

                      oder

                      {
                        "common": {
                          "name": "Solarpower.Huawei.Meter.Status",
                          "unit": "",
                          "role": "state",
                          "type": "mixed",
                          "states": {
                            "0": "offline",
                            "1": "normal"
                          }
                        },
                      

                      erweitert da ich nur mit der Zahl nichts anfangen kann.
                      Ist es möglich das in deinem Script zu integrieren?

                      C 1 Reply Last reply Reply Quote 0
                      • B
                        bishop @bahnuhr last edited by

                        @bahnuhr
                        hier z.b.

                        
                        awtrix-light.0
                        2023-10-31 19:25:50.383	info	[initCustomApps] State value of custom app "verbrauch" (javascript.0.Solarpower.Derived.HouseConsumption) is not acknowledged (ack: false) - waiting for new value
                        

                        brauch ich den Wert als bestätigt!

                        bahnuhr 1 Reply Last reply Reply Quote 0
                        • bahnuhr
                          bahnuhr Forum Testing Most Active @bishop last edited by

                          @bishop
                          Is ja nen Ding.
                          Hab ich noch nicht gesehen sowas.

                          Klappt dein kleines Script wie gewollt ?

                          1 Reply Last reply Reply Quote 0
                          • C
                            Chris_B @bishop last edited by

                            @bishop Danke für die Frage.
                            ich habe mich sehr lange nicht gemeldet. Ich habe genau das, und noch etwas mehr umgesetzt. Die Status von Inverter und Battery werden als Text ausgegeben. Zusätzlich werden gewisse Variable, welche im Standby der Battery nicht mehr zur Verfügung stehen entsprechend gesetzt, sodass diese dann in den Status 'standby' wechseln. Ich konnte das erst jetzt gut testen, da meine Anlage erst jetzt regelmässig in diesen Modus wechselt.
                            Ich werde das so erweiterte Skript am Wochenende zur Verfügung stellen. Ich aknn nicht früher, zu viel zu tun...

                            B 1 Reply Last reply Reply Quote 0
                            • B
                              bishop @Chris_B last edited by

                              @chris_b
                              Das hört sich doch super an! Kein Stress ich kann warten 🙂

                              C 1 Reply Last reply Reply Quote 0
                              • B
                                bolliy Developer last edited by bolliy

                                Hallo Zusammen, ich habe mein Huawai Wechselrichter dank des JS script von @chrisB gut im Griff. Nun ist mir allerdings aufgefallen, dass die Funktion/Methode "readHoldingRegisters" mit einem Callback aufgerufen wird. Der Callback führt zu einem asynchronem Programmablauf. Deshalb muss die Abfrage der Register zeitverzögert erfolgen, da die die Modbus-Schnittstelle nur seriell angsprochen werden kann. Es kann also die nächste Abfrage erst nach dem Modbus-Response erfolgen.

                                Die Funktion readHoldingRegisters gibt aber auch ein Promise zurück - also ein Versprechen auf einen Wert, der später kommt.
                                Die Lösung: async/await! Unter der Haube arbeitet ein Promise, aber wir werden von den ganzen Unannehmlichkeiten befreit. Nun habe ich die Funkion "readRegisterSpace" umgebaut. Der Programmablauf ist nun synchron. Der Aufruf "await client.readHoldingRegisters" wartet bis das Ergebnis vorliegt ohne zu blockieren!

                                async function readRegisterSpaceAsync(id, address, length) {  
                                    try {
                                      //console.log('ReadRegisters 1');  
                                      await client.setID(ModBusIDs[id-1]);
                                      //console.log('ReadRegisters 1');
                                      let data = await client.readHoldingRegisters(address, length);
                                      //console.log('ReadRegisters 2');
                                      return data.data;    
                                    } catch (err) {
                                       //console.error("Error received writing adress "+ address + " from id: " +  ModBusIDs[id-1] + " with error: " + modbusErrorMessages[err.modbusCode], err);
                                       //return -1;
                                       throw err; //Fehler weiterreichen
                                    }
                                    
                                }
                                

                                Mein readRegisters kann nun als synchroner Programmablauf - recht schnell - die Register auslesen.

                                async function ReadRegister(Reg) {
                                    for (let id = 1; id <= ModBusIDs.length; id++) {
                                        for (let i = 0; i < Reg.length; i++) {
                                            let address = Reg[i][0];
                                            let length = Reg[i][1];
                                            try { 
                                              console.debug("Try to read data from id/address " + ModBusIDs[id-1] + "/" + address);
                                              let data = await readRegisterSpaceAsync(id, address, length);
                                              console.debug("Read data from id/address " + ModBusIDs[id-1] + "/" + address + "\nData is: " + data);
                                              for (var y = 0; y < length; y++) Buffer[id-1][address + y - BufOffset] = data[y]; 
                                            } catch(err) {
                                                // if error, handle them here (it should not)
                                                if (err.modbusCode == null) {
                                                  console.warn("Lost connection to client. ");
                                                }  else { 
                                                  console.error("Error received writing adress "+ address + " from id: " +  ModBusIDs[id-1] + " with error: " + modbusErrorMessages[err.modbusCode], err);
                                                }  
                                                return -1;           
                                            } 
                                           
                                        }      
                                    }     
                                
                                }
                                

                                Hier eine gute Erklärung zum Thema asynchroner Code: link text

                                Lg Stephan

                                C 2 Replies Last reply Reply Quote 1
                                • C
                                  Chris_B @bolliy last edited by

                                  @bolliy INteressanter Input. Muss ich mir anschauen. Ich veröffentliche gleich eine neue Version des Skripts (endlich, nach längerer Abwesenheit). Diese Version übersetzt nun Meldungen in verständliche Strings (bspw. den Zustand des Inverters). Deine Überlegungen sind allerdings da noch nicht eingebaut. Schau ich mir noch an und baue das ein - sofern ich es verstehe...
                                  Gruss

                                  1 Reply Last reply Reply Quote 0
                                  • C
                                    Chris_B @bishop last edited by

                                    @bishop Hallo zusammen. Nach längerer Abwesenheit endlich eine neue Version des Skripts. Das beinhaltet (endlich) einen Übersetzung von vielen Zuständen in lesbaren Text. So ist bspw. der Inverterzustand jetz nicht mehr eine Zahl, sondern ein lesbarer Text, bspw. "On-grid" oder "Standby: no irradiation". Das gleiche ist für die Batterie- und die Batterystack Zustände umgesetzt.

                                    Der Kommentar von @bolliy habe ich noch nicht umgesetzt, schaue ich mir noch an.

                                    Das Ganze findet sich, inklusive erweiterter Beschreibung auf Github:
                                    Github Sun2000
                                    Gruss, Christian

                                    B 1 Reply Last reply Reply Quote 3
                                    • B
                                      bishop @Chris_B last edited by

                                      @chris_b

                                      vielen Dank hab gleich mal geupdated 🙂
                                      auf den ersten blick was ich bräuchte sind die DP als bestätigt.

                                      Macht man das in JavaScript generell nicht?

                                      {   if (testCreateState == 0)
                                          {   if (!existsState(JavaInst + objectname)) { createState(objectname, value, options); }
                                              else                                            { setState(objectname, value, true); }
                                          } else
                                          {   setState(objectname, value, true);
                                          }
                                      }  
                                      

                                      hab das so hinbekommen.
                                      Aber leider hab ich zu wenig Ahnung wie man das auch

                                      javascript.0.Solarpower.Derived
                                      

                                      hier macht.

                                      C 1 Reply Last reply Reply Quote 0
                                      • C
                                        Chris_B @bishop last edited by

                                        @bishop Sorry, aber ich verstehe die Frage nicht. Ich bin kein Javascript Experte, aber im Skript selbst brauche ich das nicht. Für was brauchst Du das? Die Werte (Du nennst sie Datenpunkte) kann man Problemlos in Vis verwenden...
                                        Gruss

                                        1 Reply Last reply Reply Quote 0
                                        • C
                                          Chris_B @bolliy last edited by

                                          @bolliy Hallo Stephan.
                                          Ich habe versucht Deinen Vorschlag zu verstehen, ist mir leider nicht vollständig gelungen - bis jetzt. Also: readRegisterSpace wird durch ReadRegisterSpaceAsync ersetzt. Aber wie / wo wird ReadRegister(reg) im Skript verwendet, sorry ich steh auf dem Schlauch. Ich würde gerne das Skript entsprechend anpassen, aber ohne zu verstehen geht das nicht...
                                          Gruss

                                          1 Reply Last reply Reply Quote 0
                                          • B
                                            bolliy Developer last edited by bolliy

                                            Hallo @Chris_B, es sind natürlich noch mehr Änderungen notwendig. Wollte diese aber nicht gleich alle hier ausbreiten. Mir ging es im ersten Step darum zu zeigen, dass die Abfrage eleganter und ohne Wartezeiten zwichen den readRegisterSpaceAsync() auskommen. Im Forum wird darüber berichtet, dass die modbus Implementation von Huawai sich nicht an die Standards hält. In diesem Zusammenhang ist mir nur eine notwendige Wartezeit von 5 Sekunden nach dem Verbindungsaufbau aufgefallen. So jetzt habe ich meine anderen entscheidenden Änderungen hier zusammengefasst. Über setinterval wird nun alle 30 Sekunden die komplette Abfrage der Register in "ReadInterval" durchgeführt. Die gesamte Abfrage dauert bei mir ca. 12 Sekunden. Den "InitProcess" hat in meiner Implementation noch weiter Aufgaben, die ich hier einfachheitshalber rausgeschnitten habe. Wird das Script in "onStop" gestoppt, schließt die Clientverbindung und der Interval beendet. Sollte also gerade noch die Abfrageschleife laufen, wird diese sofort mit einem Fehler abgebrochen. Ansonsten würde die Abfragen noch im Hintergrund weiterlaufen. Man sieht nun, dass fast der gesamte asynchrone IO-Operationen über async/await gekabselt besser organisiert und lesbarer wird.

                                            Ich hoffe, dass ich ein bisschen unterstützen kann.
                                            Lg Stephan

                                            async function modbusConnect() {
                                                var loopOK = true;
                                                while (loopOK) {   
                                                        try {
                                                            await client.setTimeout(5000);
                                                            await client.connectTCP(ModBusHost, { port: ModBusPort} );
                                                            console.log(`Connected Modbus IP: ${ModBusHost} /PORT ${ModBusPort}`)
                                                            await new Promise(resolve => setTimeout(resolve, 5000)); //Huawai spezifisch ;) warten
                                                            loopOK = false;
                                                        } catch(err) {
                                                            console.error(err.message);
                                                            await new Promise(resolve => setTimeout(resolve, 10000));                  
                                                        }
                                                }
                                            }
                                            
                                            async function ReadInterval() { 
                                                console.debug('Start the Interval...');
                                                try {
                                                    await readRegisters(RegToRead);
                                                    ProcessData();        
                                                } catch (err) {
                                                    if (err.modbusCode == null) {
                                                            console.warn("Lost connection to client!");
                                                    }  else  { 
                                                        console.error(" Stop with error: " + modbusErrorMessages[err.modbusCode], err); 
                                                    }  
                                                }      
                                                console.debug('Stop the Interval');
                                            }
                                            
                                            
                                            async function InitProcess() {
                                                try {
                                                    await modbusConnect();        
                                                    intervalId = setInterval(ReadInterval,30000);
                                                } catch (err) {
                                                    throw err;
                                                } 
                                            }
                                            
                                            onStop ( (callback) => {
                                               if (intervalId) clearInterval(intervalId);
                                               client.close();
                                               
                                               callback();
                                            },2000);
                                            
                                            InitProcess();
                                            
                                            
                                            
                                            
                                            1 Reply Last reply Reply Quote 0
                                            • First post
                                              Last post

                                            Support us

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

                                            818
                                            Online

                                            31.8k
                                            Users

                                            80.0k
                                            Topics

                                            1.3m
                                            Posts

                                            60
                                            477
                                            87868
                                            Loading More Posts
                                            • Oldest to Newest
                                            • Newest to Oldest
                                            • Most Votes
                                            Reply
                                            • Reply as topic
                                            Log in to reply
                                            Community
                                            Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
                                            The ioBroker Community 2014-2023
                                            logo