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

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

Community Forum

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

NEWS

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

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

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

Huawei Sun2000 & ioBroker via JS script funktioniert

Geplant Angeheftet Gesperrt Verschoben ioBroker Allgemein
481 Beiträge 62 Kommentatoren 121.4k Aufrufe 63 Watching
  • Älteste zuerst
  • Neuste zuerst
  • Meiste Stimmen
Antworten
  • In einem neuen Thema antworten
Anmelden zum Antworten
Dieses Thema wurde gelöscht. Nur Nutzer mit entsprechenden Rechten können es sehen.
  • B 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 :)

    bahnuhrB Online
    bahnuhrB Online
    bahnuhr
    Forum Testing Most Active
    schrieb am zuletzt editiert von
    #431

    @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 ?!


    Wenn ich helfen konnte, dann Daumen hoch (Pfeil nach oben)!
    Danke.
    gute Forenbeiträge: https://forum.iobroker.net/topic/51555/hinweise-f%C3%BCr-gute-forenbeitr%C3%A4ge
    ScreenToGif :https://www.screentogif.com/downloads.html

    B 1 Antwort Letzte Antwort
    0
    • bahnuhrB bahnuhr

      @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 Offline
      B Offline
      bishop
      schrieb am zuletzt editiert von
      #432

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

      1 Antwort Letzte Antwort
      0
      • B Offline
        B Offline
        bishop
        schrieb am zuletzt editiert von
        #433

        @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 Antwort Letzte Antwort
        0
        • bahnuhrB bahnuhr

          @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 Offline
          B Offline
          bishop
          schrieb am zuletzt editiert von
          #434

          @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!

          bahnuhrB 1 Antwort Letzte Antwort
          0
          • B bishop

            @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!

            bahnuhrB Online
            bahnuhrB Online
            bahnuhr
            Forum Testing Most Active
            schrieb am zuletzt editiert von
            #435

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

            Klappt dein kleines Script wie gewollt ?


            Wenn ich helfen konnte, dann Daumen hoch (Pfeil nach oben)!
            Danke.
            gute Forenbeiträge: https://forum.iobroker.net/topic/51555/hinweise-f%C3%BCr-gute-forenbeitr%C3%A4ge
            ScreenToGif :https://www.screentogif.com/downloads.html

            1 Antwort Letzte Antwort
            0
            • B bishop

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

              @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 Antwort Letzte Antwort
              0
              • C Chris_B

                @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 Offline
                B Offline
                bishop
                schrieb am zuletzt editiert von
                #437

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

                C 1 Antwort Letzte Antwort
                0
                • B Offline
                  B Offline
                  bolliy
                  Developer
                  schrieb am zuletzt editiert von bolliy
                  #438

                  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 Antworten Letzte Antwort
                  1
                  • B 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 Offline
                    C Offline
                    Chris_B
                    schrieb am zuletzt editiert von
                    #439

                    @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 Antwort Letzte Antwort
                    0
                    • B bishop

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

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

                      @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 Antwort Letzte Antwort
                      3
                      • C Chris_B

                        @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 Offline
                        B Offline
                        bishop
                        schrieb am zuletzt editiert von
                        #441

                        @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 Antwort Letzte Antwort
                        0
                        • B bishop

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

                          @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 Antwort Letzte Antwort
                          0
                          • B 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 Offline
                            C Offline
                            Chris_B
                            schrieb am zuletzt editiert von
                            #443

                            @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 Antwort Letzte Antwort
                            0
                            • B Offline
                              B Offline
                              bolliy
                              Developer
                              schrieb am zuletzt editiert von bolliy
                              #444

                              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 Antwort Letzte Antwort
                              0
                              • B Offline
                                B Offline
                                bolliy
                                Developer
                                schrieb am zuletzt editiert von bolliy
                                #445

                                Ich möchte noch auf die Möglichkeit aufmerksam machen Werte über modbus-tcp zu schreiben. Eine entsprechende funktion mit einem Beispiel werde ich aufzeigen. Also zuerst die async-Funktion, die ohne Callback auskommt und über await wartet bis der Wert vorliegt.

                                //asynchrones Schreiben 
                                async function writeRegistersAsync(id,address,buffer) {
                                    try {
                                      await client.setID(ModBusIDs[id-1]);
                                      await client.writeRegisters(address,buffer);
                                    }  catch (err) {
                                        console.error("Error received writing adress "+ address + " from id: " +  ModBusIDs[id-1] + " with error: " + modbusErrorMessages[err.modbusCode], err);
                                        throw err; //Fehler weiterreichen
                                    }  
                                }
                                

                                Als Beispiel habe ich meine CheckAndPrepare Funktion herangezogen. Die Funktion soll den Wechselrichter bzw. Speicher so vorbereiten, dass dieser über einen einfachen Registerbefehl zum Aufladen des Speichers aus dem öffentlichen Stromnetz gebracht werden kann. Dieses ist bei der Nutzung dynamicher Strompreise (z.B. Tibber) ganz hilfreich. Idee: Wenn Strompreis kleiner als der mittelere Strompreis - 20% ist, soll der Hausspeicher mit günstigem Netzstrom aufgeladen werden. In dem Array wird die "Time of Using charging and discharging periodes (siehe Table 5-6) " gehalten. Diese Beispiel soll nur die Nutzungsmöglich der Funktion "writeRegistersAsync" verdeutlichen.

                                async function checkAndPrepare() {
                                     // Time of Using charging and discharging periodes (siehe Table 5-6) 
                                     // tCDP[3]= 127  => Speicheraufladung aus dem öffentlichen Netz
                                     var tCDP = [1,0,1440,383,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]; //nicht aus dem Netz laden
                                     let data = await readRegisterSpaceAsync(1,47086,4);
                                     /* 
                                      127 - Working mode settings  
                                       2 : Maximise self consumptions (default)
                                       5 : Time Of Use(Luna) - hilfreich bei dynamischem Stromtarif (z.B Tibber)
                                     */  
                                     let workingMode = data[0];         // Working mode settings  2:Maximise self consumptio5=)
                                     let chargeFromGrid = data[1];      // Voraussetzung für Netzbezug in den Speicher (Luna)  
                                     let gridChargeCutOff = data[2]/10; // Ab welcher Schwelle wird der Netzbezug beendet (default 50 %)
                                     let storageModel = data[3];        // Modell/Hersteller des Speichers, 2 : HUAWEI-LUNA2000
                                     try {
                                        if (storageModel == 2) { //wurde nur mit Luna getestet!
                                          if (workingMode != 5 || chargeFromGrid != 1 ) {
                                            console.debug('Row '+data+'  Workingmode '+workingMode+ ' Charge from Grid '+chargeFromGrid+ ' Grid Cut Off '+gridChargeCutOff+'%'); 
                                            await writeRegistersAsync(1,47086,[5,1,500]); //[TOU,chargeFromGrid,50%]
                                            await writeRegistersAsync(1,47255,tCDP);      //Plan:1,StartZeit:00:00,EndZeit: 24:00,Endladen/täglich
                                            /* ggf. sinnvoll 
                                            await writeRegistersAsync(1,47075,[0,5000]); //max. charging power 
                                            await writeRegistersAsync(1,47077,[0,5000]); //max. discharging power 
                                            */
                                          }
                                        }
                                     } catch(err) {
                                       throw err; 
                                     }
                                }
                                

                                Die "checkAndPrepare wird einfach in den "InitProcess" eingehängt.

                                async function InitProcess() {
                                    try {        
                                        await modbusConnect();
                                        await checkAndPrepare();
                                        intervalId = setInterval(ReadInderval,30000);
                                    } catch (err) {
                                        throw err;
                                    } 
                                }
                                

                                Und so würde die Speicheraufladung aus dem Netz gestartet werden. Bei 50% Speicherfüllgrad unterbricht die Speicheraufladung aus dem Netz.

                                var tCDP = [1,0,1440,383,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]; 
                                tCDP[3] = 127; // Laden
                                await writeRegistersAsync(1,47255,tCDP);
                                  
                                

                                LG Stephan

                                1 Antwort Letzte Antwort
                                1
                                • P Offline
                                  P Offline
                                  PsYkoKeV
                                  schrieb am zuletzt editiert von
                                  #446

                                  Hallo und danke an alle, die hier bisher mitgewirkt haben. :blush:

                                  Ich habe mit dem Adapter von daolis (ioBroker.sun2000-modbus) angefangen Daten von meinem Wechselrichter zu sammeln und sinnvoll zu verarbeiten.
                                  Bin jetzt über das Script hier gestolpert und habe es direkt mals ausprobiert.

                                  Vielleicht für alle, die auch mal stolpern, hier meine bisherigen Unterschiede:

                                  • Script hat von Haus auch mehr Infos, es werden mehr Daten abgerufen und gleich umgewandelt -> z.B. Tagesverbräuche
                                  • Der Adapter ist etwas fixer was das aktualisieren von Daten angeht. Dort wird (bei mir) alle ca 7Sek z.b. der aktuelle Verbrauch aktualisiert, das passiert bei Script ca alle 25 Sek.
                                    -> Das ändert sich vielleicht mit der Idee von bolliy?

                                  @Chris_B Kleinen "Schönheitsfehler" den ich gefunden habe: PanelPower ist als W definiert, wird in der berechnung auf kW umgerechnet.

                                  createState(JavaInst + "Solarpower.Derived.PanelPower",         0,  {read: true, write: true, name: "Panel Power (UxI)", unit: "W"});
                                  
                                      // determine raw panel power (multiplying current times voltage)
                                      {
                                          var power = (getState(JavaInst + "Solarpower.Huawei.Inverter.1.String.1_Voltage").val *
                                                       getState(JavaInst + "Solarpower.Huawei.Inverter.1.String.1_Current").val) / 1000;
                                          setState(JavaInst + "Solarpower.Derived.PanelPower", power);
                                  

                                  Und ich denke mal gewollt, dass String 2 deaktiviert ist und nicht in der Berechnung der PanelPower einfließt?!
                                  Ist ja kein Drama das zu aktivieren. Und zur Info habe bei mir String 2 dann natürlich auch zur Berechnung hinzugefügt:

                                      // determine raw panel power (multiplying current times voltage)
                                      {
                                          var power = (getState(JavaInst + "Solarpower.Huawei.Inverter.1.String.1_Voltage").val *
                                                       getState(JavaInst + "Solarpower.Huawei.Inverter.1.String.1_Current").val) +
                                                       (getState(JavaInst + "Solarpower.Huawei.Inverter.1.String.2_Voltage").val *
                                                       getState(JavaInst + "Solarpower.Huawei.Inverter.1.String.2_Current").val);
                                          setState(JavaInst + "Solarpower.Derived.PanelPower", power);
                                  
                                          // determine peak panel power
                                          var PanelMax = getState(JavaInst + "Solarpower.Derived.PeakPanelPower").val;
                                          if (power > PanelMax) setState(JavaInst + "Solarpower.Derived.PeakPanelPower", power);
                                      }
                                  

                                  Bin jetzt noch kein Profi, kann man diese Berechnung dynamisch gestalten? Wenn das Sinn macht natürlich nur...

                                  Grüße
                                  Kevin

                                  M C 2 Antworten Letzte Antwort
                                  0
                                  • P PsYkoKeV

                                    Hallo und danke an alle, die hier bisher mitgewirkt haben. :blush:

                                    Ich habe mit dem Adapter von daolis (ioBroker.sun2000-modbus) angefangen Daten von meinem Wechselrichter zu sammeln und sinnvoll zu verarbeiten.
                                    Bin jetzt über das Script hier gestolpert und habe es direkt mals ausprobiert.

                                    Vielleicht für alle, die auch mal stolpern, hier meine bisherigen Unterschiede:

                                    • Script hat von Haus auch mehr Infos, es werden mehr Daten abgerufen und gleich umgewandelt -> z.B. Tagesverbräuche
                                    • Der Adapter ist etwas fixer was das aktualisieren von Daten angeht. Dort wird (bei mir) alle ca 7Sek z.b. der aktuelle Verbrauch aktualisiert, das passiert bei Script ca alle 25 Sek.
                                      -> Das ändert sich vielleicht mit der Idee von bolliy?

                                    @Chris_B Kleinen "Schönheitsfehler" den ich gefunden habe: PanelPower ist als W definiert, wird in der berechnung auf kW umgerechnet.

                                    createState(JavaInst + "Solarpower.Derived.PanelPower",         0,  {read: true, write: true, name: "Panel Power (UxI)", unit: "W"});
                                    
                                        // determine raw panel power (multiplying current times voltage)
                                        {
                                            var power = (getState(JavaInst + "Solarpower.Huawei.Inverter.1.String.1_Voltage").val *
                                                         getState(JavaInst + "Solarpower.Huawei.Inverter.1.String.1_Current").val) / 1000;
                                            setState(JavaInst + "Solarpower.Derived.PanelPower", power);
                                    

                                    Und ich denke mal gewollt, dass String 2 deaktiviert ist und nicht in der Berechnung der PanelPower einfließt?!
                                    Ist ja kein Drama das zu aktivieren. Und zur Info habe bei mir String 2 dann natürlich auch zur Berechnung hinzugefügt:

                                        // determine raw panel power (multiplying current times voltage)
                                        {
                                            var power = (getState(JavaInst + "Solarpower.Huawei.Inverter.1.String.1_Voltage").val *
                                                         getState(JavaInst + "Solarpower.Huawei.Inverter.1.String.1_Current").val) +
                                                         (getState(JavaInst + "Solarpower.Huawei.Inverter.1.String.2_Voltage").val *
                                                         getState(JavaInst + "Solarpower.Huawei.Inverter.1.String.2_Current").val);
                                            setState(JavaInst + "Solarpower.Derived.PanelPower", power);
                                    
                                            // determine peak panel power
                                            var PanelMax = getState(JavaInst + "Solarpower.Derived.PeakPanelPower").val;
                                            if (power > PanelMax) setState(JavaInst + "Solarpower.Derived.PeakPanelPower", power);
                                        }
                                    

                                    Bin jetzt noch kein Profi, kann man diese Berechnung dynamisch gestalten? Wenn das Sinn macht natürlich nur...

                                    Grüße
                                    Kevin

                                    M Offline
                                    M Offline
                                    meloneA
                                    schrieb am zuletzt editiert von
                                    #447

                                    @psykokev ich vermute mal Chris hat nur einen String :)

                                    ich hoffe das der Adapter nach und nach diverse Infos noch mit einbaut und ggf noch weitere Berechnungen mitbringt (z.B. Autarkie) und langfristig auch andere Bestandteile wie Optimierer einbindet.

                                    1 Antwort Letzte Antwort
                                    0
                                    • P PsYkoKeV

                                      Hallo und danke an alle, die hier bisher mitgewirkt haben. :blush:

                                      Ich habe mit dem Adapter von daolis (ioBroker.sun2000-modbus) angefangen Daten von meinem Wechselrichter zu sammeln und sinnvoll zu verarbeiten.
                                      Bin jetzt über das Script hier gestolpert und habe es direkt mals ausprobiert.

                                      Vielleicht für alle, die auch mal stolpern, hier meine bisherigen Unterschiede:

                                      • Script hat von Haus auch mehr Infos, es werden mehr Daten abgerufen und gleich umgewandelt -> z.B. Tagesverbräuche
                                      • Der Adapter ist etwas fixer was das aktualisieren von Daten angeht. Dort wird (bei mir) alle ca 7Sek z.b. der aktuelle Verbrauch aktualisiert, das passiert bei Script ca alle 25 Sek.
                                        -> Das ändert sich vielleicht mit der Idee von bolliy?

                                      @Chris_B Kleinen "Schönheitsfehler" den ich gefunden habe: PanelPower ist als W definiert, wird in der berechnung auf kW umgerechnet.

                                      createState(JavaInst + "Solarpower.Derived.PanelPower",         0,  {read: true, write: true, name: "Panel Power (UxI)", unit: "W"});
                                      
                                          // determine raw panel power (multiplying current times voltage)
                                          {
                                              var power = (getState(JavaInst + "Solarpower.Huawei.Inverter.1.String.1_Voltage").val *
                                                           getState(JavaInst + "Solarpower.Huawei.Inverter.1.String.1_Current").val) / 1000;
                                              setState(JavaInst + "Solarpower.Derived.PanelPower", power);
                                      

                                      Und ich denke mal gewollt, dass String 2 deaktiviert ist und nicht in der Berechnung der PanelPower einfließt?!
                                      Ist ja kein Drama das zu aktivieren. Und zur Info habe bei mir String 2 dann natürlich auch zur Berechnung hinzugefügt:

                                          // determine raw panel power (multiplying current times voltage)
                                          {
                                              var power = (getState(JavaInst + "Solarpower.Huawei.Inverter.1.String.1_Voltage").val *
                                                           getState(JavaInst + "Solarpower.Huawei.Inverter.1.String.1_Current").val) +
                                                           (getState(JavaInst + "Solarpower.Huawei.Inverter.1.String.2_Voltage").val *
                                                           getState(JavaInst + "Solarpower.Huawei.Inverter.1.String.2_Current").val);
                                              setState(JavaInst + "Solarpower.Derived.PanelPower", power);
                                      
                                              // determine peak panel power
                                              var PanelMax = getState(JavaInst + "Solarpower.Derived.PeakPanelPower").val;
                                              if (power > PanelMax) setState(JavaInst + "Solarpower.Derived.PeakPanelPower", power);
                                          }
                                      

                                      Bin jetzt noch kein Profi, kann man diese Berechnung dynamisch gestalten? Wenn das Sinn macht natürlich nur...

                                      Grüße
                                      Kevin

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

                                      @psykokev Danke für den Hinweis, und ja, meine Anlage hat nur einen String. Die Berechnung kann man natürlich auch, wie Du es nennst 'dynamisch', so machen, dass ein oder zwei Strings für die Berechnung verwendet werden. Die Frage ist dann aber: Will ich diese separat oder zusammen ausgeben? Beides kann sinnvoll sein.
                                      Mir ist bewusst, dass das Skript auf meine Verhältnisse zugeschnitten ist. Ich mache in diesem Skript auch mehrheitlich nur das, was für mich sinnvoll ist. Sorry, das ist vielleicht egoistisch, ich habe habe (leider?) genug Anderes zu tun.
                                      @bolliy Aus genau dem Grund implementiere ich momentan das 'Schreiben' von Werten nicht. Ich brauche und möchte das momentan (noch?) nicht. Sorry. Die Async Methode interessiert mich allerdings...
                                      Ihr könnt gerne von Github einen Fork auf das Projekt machen und diese Dinge realisieren, oder das Skript für Euch selbst abändern...
                                      Gruss

                                      P 1 Antwort Letzte Antwort
                                      0
                                      • B Offline
                                        B Offline
                                        backons
                                        schrieb am zuletzt editiert von backons
                                        #449

                                        Hallo Zusammen,

                                        habe seit knapp einer Woche auch ein Huawei System. Hab mir vor ein paar Tagen das Script geholt und angepasst an meine Konstellation.
                                        2x WR in Kaskade und eine 10KW Luna am WR1.
                                        Soweit funktioniert alles ohne Fehlermeldungen bis auf den Ordner Derived.
                                        Dort wurden die Einträge zwar angelegt aber dort ist überall nur eine 0 zu sehen. Diese Werte werden auch nicht über Nacht aktualisiert. Wo könnte hier der Fehler bei mir sein ?
                                        P.S. Die Werte der WR werden brav aktualisiert und sind auch vorhanden. Habe die neuste Version des Script aus Github in Verwendung

                                        1 Antwort Letzte Antwort
                                        0
                                        • J Offline
                                          J Offline
                                          Julez318
                                          schrieb am zuletzt editiert von
                                          #450

                                          Hallo Zusammen,

                                          ich habe 2 WR (SUN2000-10KTL-M1 als Master ID=16 & SUN2000-8KTL-M1 als slave ID=1) an einem Dongle.
                                          Leider bekomme ich nur die Daten des Master WR.
                                          Kann hier bitte jemand helfen?

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


                                          Support us

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

                                          635

                                          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