Weiter zum Inhalt
  • Home
  • Aktuell
  • Tags
  • 0 Ungelesen 0
  • Kategorien
  • Unreplied
  • Beliebt
  • GitHub
  • Docu
  • Hilfe
Skins
  • Hell
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dunkel
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

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

Community Forum

donate donate
  1. ioBroker Community Home
  2. Deutsch
  3. Skripten / Logik
  4. JavaScript
  5. Zendure SmartMode:1 SolarFlow2400 AC SolarFlow800 ( u. Pro)

NEWS

  • Monatsrückblick Januar/Februar 2026 ist online!
    BluefoxB
    Bluefox
    18
    1
    680

  • Jahresrückblick 2025 – unser neuer Blogbeitrag ist online! ✨
    BluefoxB
    Bluefox
    18
    1
    5.7k

  • Neuer Blogbeitrag: Monatsrückblick - Dezember 2025 🎄
    BluefoxB
    Bluefox
    13
    1
    1.5k

Zendure SmartMode:1 SolarFlow2400 AC SolarFlow800 ( u. Pro)

Geplant Angeheftet Gesperrt Verschoben JavaScript
232 Beiträge 10 Kommentatoren 16.0k Aufrufe 10 Beobachtet
  • Ä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 Offline
    B Offline
    Berny-K
    schrieb am zuletzt editiert von
    #214

    Hallo,
    Ich haben mir einen Solarflow 800 pro zugelegt und auf der Suche nach einer Möglichkeit diesen über iobroker auszuwerten und zu steuern hier gelandet.
    Hoffe ich bin mit meinen Fragen hier überhaupt richtig?
    Ich bin dabei mein vorhandenes BKW etwas auszubauen und würde gerne meinen IR-Lesekopf mit Tasmota weiter nutzen und auf Basis dieser verfügbaren Daten im iobroker den Solarflow 800 Pro ansteuern um eine Null-Einspeisung zu realisieren.
    Das Script habe ich schon Mal im iobroker am laufen und sehe auch entsprechende Daten.
    Ich habe aber bisher noch keine Hinweise gefunden wie ich meinen Plan realisieren könnte.
    Könnte mir dazu vielleicht jemand auf die Sprünge helfen oder geht das auf diese Weise gar nicht?

    S 1 Antwort Letzte Antwort
    0
    • B Berny-K

      Hallo,
      Ich haben mir einen Solarflow 800 pro zugelegt und auf der Suche nach einer Möglichkeit diesen über iobroker auszuwerten und zu steuern hier gelandet.
      Hoffe ich bin mit meinen Fragen hier überhaupt richtig?
      Ich bin dabei mein vorhandenes BKW etwas auszubauen und würde gerne meinen IR-Lesekopf mit Tasmota weiter nutzen und auf Basis dieser verfügbaren Daten im iobroker den Solarflow 800 Pro ansteuern um eine Null-Einspeisung zu realisieren.
      Das Script habe ich schon Mal im iobroker am laufen und sehe auch entsprechende Daten.
      Ich habe aber bisher noch keine Hinweise gefunden wie ich meinen Plan realisieren könnte.
      Könnte mir dazu vielleicht jemand auf die Sprünge helfen oder geht das auf diese Weise gar nicht?

      S Online
      S Online
      Schimi
      schrieb am zuletzt editiert von
      #215

      @Berny-K schaue dir mal das Script an, vielleicjt erledigt das schon alles was du möchtest 😉

      https://forum.iobroker.net/topic/82723/typeskript-zendure-solarflow-2400-ac-evcc-steuerung

      B 1 Antwort Letzte Antwort
      0
      • S Schimi

        @Berny-K schaue dir mal das Script an, vielleicjt erledigt das schon alles was du möchtest 😉

        https://forum.iobroker.net/topic/82723/typeskript-zendure-solarflow-2400-ac-evcc-steuerung

        B Offline
        B Offline
        Berny-K
        schrieb am zuletzt editiert von
        #216

        @Schimi Vielen Dank für den Tipp, das schaue ich mir an. Den Script hier werde ich trotzdem auch brauchen um die Daten auszulesen, oder?

        1 Antwort Letzte Antwort
        0
        • S Online
          S Online
          Schimi
          schrieb am zuletzt editiert von
          #217

          ich nutze das Skript hier, damit der SmartMode gesetzt wird... habe es nie kontrolliert ob es wirklich nötig ist.....

          Aber das funktioniert alles sehr gut parallel

          B 1 Antwort Letzte Antwort
          0
          • S Schimi

            ich nutze das Skript hier, damit der SmartMode gesetzt wird... habe es nie kontrolliert ob es wirklich nötig ist.....

            Aber das funktioniert alles sehr gut parallel

            B Offline
            B Offline
            Berny-K
            schrieb am zuletzt editiert von
            #218

            @Schimi Danke, gut zu wissen, mal sehen ob ich das hin bekomme

            1 Antwort Letzte Antwort
            0
            • D Offline
              D Offline
              Daniel 8
              schrieb am zuletzt editiert von
              #219

              Es ist sehr ruhig hier geworden. Nochmals vielen Dank Für das Script. Im Moment bin ich noch am Script umbauen, da ja das neue Firmware Update meint, wenn es den minSoc unterschreitet vom Netz laden zu müssen

              Solarflow 800 Pro mit 1,3 Kwp / Iobroker / Homematic / Shellys / Mediola / Intertechno

              maxclaudiM 1 Antwort Letzte Antwort
              0
              • D Daniel 8

                Es ist sehr ruhig hier geworden. Nochmals vielen Dank Für das Script. Im Moment bin ich noch am Script umbauen, da ja das neue Firmware Update meint, wenn es den minSoc unterschreitet vom Netz laden zu müssen

                maxclaudiM Offline
                maxclaudiM Offline
                maxclaudi
                schrieb am zuletzt editiert von maxclaudi
                #220

                @Daniel-8 sagte in Zendure SmartMode:1 SolarFlow2400 AC SolarFlow800 ( u. Pro):

                ...Im Moment bin ich noch am Script umbauen, da ja das neue Firmware Update meint, wenn es den minSoc unterschreitet vom Netz laden zu müssen

                Hallo Daniel, freut mich von Dir mal wieder zu lesen, wie geht's Dir?

                Ja Zendure macht gerade viel ....
                Es wird immer mehr reglementiert. Vieles meiner Meinung nach unnötig und wahrscheinlich zum (Eigen-)Schutz.
                Persönlich würde ich abwarten und neue Firmware nicht sofort aktualisieren.
                Setze doch MinSoc sehr tief und baue einen Entladeschutz ein.
                Der verhindert dann rechtzeitig, dass Batterien weiter entladen werden noch bevor minSoc erreicht wird.

                Beispiel Ausschnitt einer Steuerung von mir:
                8f148a02-f02b-4f23-a03b-81edf9e089f1-image.png

                Ich schreibe meistens sehr direkt – bitte nicht falsch verstehen, es ist nie böse gemeint. Das ist einfach mein Stil und niemals abwertend gemeint.

                1 Antwort Letzte Antwort
                0
                • D Offline
                  D Offline
                  Daniel 8
                  schrieb am zuletzt editiert von
                  #221

                  Mir geht es soweit sehr gut. Und bei dir auch alles in Ordnung?

                  Ja das ist auch eine Idee mit dem Entladeachutz. Das könnte ich ja auch mit soc triggern. Du machst das ganze ja mit volt. Bin nur noch nicht ganz schlau geworden was du mit deinen internen Variablen da alles abfragst. Ich denke du triggerst auf Volt oder?
                  Dann müsste ich nur mein ganzes Script umbauen, da ich überall mir soc getrickert habe wann er aufhören soll zu entladen und starten soll. Sollte aber nicht das große Problem sein.

                  Solarflow 800 Pro mit 1,3 Kwp / Iobroker / Homematic / Shellys / Mediola / Intertechno

                  1 Antwort Letzte Antwort
                  0
                  • D Offline
                    D Offline
                    Daniel 8
                    schrieb am zuletzt editiert von Daniel 8
                    #222

                    So script ist umgebaut. War ja eigentlich ganz einfach. Ich habe einfach alle minsoc wo ich bis jetzt von mqtt bezogen habe durch eine in Objekte erstellten Variable ersetzt. Somit kann ich mit der den unteren soc steuern. Muss nur mal sehen wie sich der Speicher dann verhält ob er auch in standby dann geht wenn er den unteren soc nicht in Wirklichkeit erreicht oder ob dann der standbyverbrauch sich erhöht.

                    Er zeigt zumindest mal standby an wenn ich Ausgabe 0 mache.

                    Solarflow 800 Pro mit 1,3 Kwp / Iobroker / Homematic / Shellys / Mediola / Intertechno

                    1 Antwort Letzte Antwort
                    0
                    • D Offline
                      D Offline
                      Daniel 8
                      schrieb am zuletzt editiert von
                      #223

                      Ergebnis war positiv heute Nacht. Er hat wie sonst auch ca. 2% verloren.

                      Die Änderung am Script war doch nicht so einfach, weil er am unteren soc nicht abgeschaltet hat. Habe es bisschen geändert und hoffe das es so läuft.

                      Solarflow 800 Pro mit 1,3 Kwp / Iobroker / Homematic / Shellys / Mediola / Intertechno

                      maxclaudiM 2 Antworten Letzte Antwort
                      0
                      • D Daniel 8

                        Ergebnis war positiv heute Nacht. Er hat wie sonst auch ca. 2% verloren.

                        Die Änderung am Script war doch nicht so einfach, weil er am unteren soc nicht abgeschaltet hat. Habe es bisschen geändert und hoffe das es so läuft.

                        maxclaudiM Offline
                        maxclaudiM Offline
                        maxclaudi
                        schrieb am zuletzt editiert von maxclaudi
                        #224

                        @Daniel-8 sagte in Zendure SmartMode:1 SolarFlow2400 AC SolarFlow800 ( u. Pro):

                        Die Änderung am Script war doch nicht so einfach, weil er am unteren soc nicht abgeschaltet hat. Habe es bisschen geändert und hoffe das es so läuft.

                        Am unteren SOC nicht abgeschaltet?
                        Wie meinst Du das?

                        Du hast minSoc z. B. auf 10 %, dann eine Entladesperre bei z. B. 15 % eingebaut und die wurde nicht beachtet und es wurde weiter entladen?

                        Mein Tipp:
                        Eine Entladesperre nur nach minVolt der Batterien setzen.
                        Spannung ist ein direkter Messwert, SOC bleibt immer ein berechneter Zustand und setzt regelmäßiges Kalibrieren voraus.

                        Edit / PS: Wenn längere Zeit nicht vollständig geladen oder entladen wird, driftet der SOC zwangsläufig.
                        Ohne Kalibrierung kann SOC mehrere Prozent danebenliegen.

                        Sieht man schön, wenn man sich minVol, maxVol und SOC-Werte visuell anzeigen lässt und diese immer wieder mal vergleicht.

                        Ich schreibe meistens sehr direkt – bitte nicht falsch verstehen, es ist nie böse gemeint. Das ist einfach mein Stil und niemals abwertend gemeint.

                        1 Antwort Letzte Antwort
                        0
                        • D Offline
                          D Offline
                          Daniel 8
                          schrieb am zuletzt editiert von Daniel 8
                          #225

                          Ich bringe den Speicher jetzt im Sommer regelmäßig voll. Somit ist er auch kalibriert.
                          Ja das war noch ein ScriptProblem, da ich mehrere gleiche abfragen in dem Block habe. Ist bisschen schwierig mit dem ganzen bypass Zeug noch. Aber jetzt schaltet er ab sobald er 0,5 unter meiner soc entladesperre ist. Damit kann ich leben.
                          Die liegt bei 10% aktuell. Den soc im zendure habe ich auf die minimalen 5% gestellt. Wenn er die 2 Prozent über Nacht verliert, dann sollte es aufgehen.

                          Solarflow 800 Pro mit 1,3 Kwp / Iobroker / Homematic / Shellys / Mediola / Intertechno

                          1 Antwort Letzte Antwort
                          1
                          • D Offline
                            D Offline
                            Daniel 8
                            schrieb am zuletzt editiert von
                            #226

                            Es.war bzw. Ist nicht ganz so einfach wie gedacht. Jetzt geht der 800Pro nicht mehr in den Bypass und somit lädt er immer bisschen in den Akku und entlädt dann wieder bis zum man soc der variable. Durch das was der pro eben denkt er darf weiter entladen weil der soc ja viel niedriger eingestellt ist. Somit schaltet er nicht in bypass

                            Solarflow 800 Pro mit 1,3 Kwp / Iobroker / Homematic / Shellys / Mediola / Intertechno

                            1 Antwort Letzte Antwort
                            0
                            • C Offline
                              C Offline
                              cbrocker
                              schrieb am zuletzt editiert von
                              #227

                              Hallo,
                              ich lese hier hin und wieder mit und habe mir auch den Adapter von nograx mal heruntergeladen, aber noch nicht wirklich eingerichtet. Bisher lese ich ein paar Daten vom SF800 per http request aus.

                              Ich habe mal mit KI ein Script erstellen lassen, das mir den Tagesertrag anhand der laufenden PV-Produktion berechnet, aber der Wert stimmt nicht ganz mit dem in der App überein.

                              Frage: werden im Adapter von nograx die PV-Daten (Erträge für Tag, Monat, Jahr usw.) ausgelesen oder berechnet?

                              Danke

                              Proxmox Cluster mit ioBroker, Wireguard, HomeAssistant (Testsystem), paperlessNGX, MariaDB, PiHole, Grafana, InfluxDB, 1 x BKW 600 Wp, 2 x BKW 400 Wp, 2 x SolarFlow 800 Pro mit 11,52 kWh Akku und 3,48 kWp, OpenDTU, AhoyDTU, HmIP, Shellys, AVM LAN/WLAN

                              maxclaudiM 2 Antworten Letzte Antwort
                              0
                              • C cbrocker

                                Hallo,
                                ich lese hier hin und wieder mit und habe mir auch den Adapter von nograx mal heruntergeladen, aber noch nicht wirklich eingerichtet. Bisher lese ich ein paar Daten vom SF800 per http request aus.

                                Ich habe mal mit KI ein Script erstellen lassen, das mir den Tagesertrag anhand der laufenden PV-Produktion berechnet, aber der Wert stimmt nicht ganz mit dem in der App überein.

                                Frage: werden im Adapter von nograx die PV-Daten (Erträge für Tag, Monat, Jahr usw.) ausgelesen oder berechnet?

                                Danke

                                maxclaudiM Offline
                                maxclaudiM Offline
                                maxclaudi
                                schrieb am zuletzt editiert von maxclaudi
                                #228

                                @cbrocker sagte in Zendure SmartMode:1 SolarFlow2400 AC SolarFlow800 ( u. Pro):

                                Hallo,
                                ich lese hier hin und wieder mit und habe mir auch den Adapter von nograx mal heruntergeladen, aber noch nicht wirklich eingerichtet. Bisher lese ich ein paar Daten vom SF800 per http request aus.

                                Ich habe mal mit KI ein Script erstellen lassen, das mir den Tagesertrag anhand der laufenden PV-Produktion berechnet, aber der Wert stimmt nicht ganz mit dem in der App überein.

                                Frage: werden im Adapter von nograx die PV-Daten (Erträge für Tag, Monat, Jahr usw.) ausgelesen oder berechnet?

                                Danke

                                @cbrocker, zu Detailfragen zum Adapter wendest du dich am besten direkt an den Entwickler im entsprechenden Thread.

                                Ich nutze den Adapter selbst nicht mehr, seit die Funktion setDeviceAutomationInOutLimit eingeführt wurde, und bin daher bei den aktuellen Versionen nicht mehr im Thema.
                                In meinem zenSDK-Ansatz hier geht es primär um die direkte Steuerung ohne solche kombinierten Datenpunkte.

                                Zu deiner Frage bzgl. der Ertragsdaten:
                                Zendure liefert über MQTT oft nur die Momentanwerte (Watt).
                                Die App-Statistiken (Tag/Monat) werden meist in der Cloud berechnet.
                                Wenn der Adapter diese Werte anzeigt, kommen sie entweder per Cloud-API-Abfrage (langsam) oder der Adapter berechnet sie lokal per Integral-Funktion (was bei Übertragungslücken ungenau ist). Das erklärt auch, warum KI-Skripte evtl. oft anders sind bzw. andere Werte liefern.

                                Ich schreibe meistens sehr direkt – bitte nicht falsch verstehen, es ist nie böse gemeint. Das ist einfach mein Stil und niemals abwertend gemeint.

                                1 Antwort Letzte Antwort
                                0
                                • C Offline
                                  C Offline
                                  cbrocker
                                  schrieb am zuletzt editiert von
                                  #229

                                  @maxclaudi
                                  danke für die Infos.
                                  ich lese die Daten bisher auch per http request aus (zenSDK).
                                  Was macht die Funktion setDeviceAutomationInOutLimit genau? Die Funktion ist aber nur im Adapter? Also nicht von Zendure selber?

                                  Ich möchte auch ohne Adapter und ohne MQTT aus kommen. MQTT ist ja mittlerweile sehr langsam, wie der Dev von Zendure mitgeteilt hat.

                                  Ok, dann legst du gar nicht so viel Wert auf die Ertragsdaten, sondern steuerst nur mit deinem Skripten?

                                  Proxmox Cluster mit ioBroker, Wireguard, HomeAssistant (Testsystem), paperlessNGX, MariaDB, PiHole, Grafana, InfluxDB, 1 x BKW 600 Wp, 2 x BKW 400 Wp, 2 x SolarFlow 800 Pro mit 11,52 kWh Akku und 3,48 kWp, OpenDTU, AhoyDTU, HmIP, Shellys, AVM LAN/WLAN

                                  maxclaudiM 1 Antwort Letzte Antwort
                                  0
                                  • C cbrocker

                                    @maxclaudi
                                    danke für die Infos.
                                    ich lese die Daten bisher auch per http request aus (zenSDK).
                                    Was macht die Funktion setDeviceAutomationInOutLimit genau? Die Funktion ist aber nur im Adapter? Also nicht von Zendure selber?

                                    Ich möchte auch ohne Adapter und ohne MQTT aus kommen. MQTT ist ja mittlerweile sehr langsam, wie der Dev von Zendure mitgeteilt hat.

                                    Ok, dann legst du gar nicht so viel Wert auf die Ertragsdaten, sondern steuerst nur mit deinem Skripten?

                                    maxclaudiM Offline
                                    maxclaudiM Offline
                                    maxclaudi
                                    schrieb am zuletzt editiert von
                                    #230

                                    @cbrocker
                                    Guten Morgen!

                                    Zu deinen Fragen: Mein Hauptskript (nicht veröffentlicht) regelt die Zendure-Geräte basierend auf dem aktuellen Zählerwert meines Hausanschlusses.

                                    Mein Setup zur Datenerfassung:
                                    Ich triggere die Regelung alle 5 Sekunden über einen UART-IR-Lesekopf am Zähler (per LAN/WT32-ETH01 angebunden).
                                    Als Backup dient ein Shelly 3 pro EM – sollte der Lesekopf keine plausiblen Werte liefern, schaltet das Skript automatisch auf den Shelly um (Failover).

                                    Statt bunter Grafiken erfasse ich die harten Fakten direkt in einer CSV-Datei und logge nur das Nötigste (Gesamtverbrauch, Einspeisung, Zählerstände).

                                    Das reicht mir völlig, um die Unversehrtheit des Systems und die realen IST-Zustände zu überwachen.
                                    Zudem bietet das CSV-file den Vorteil, dass man daraus bei Bedarf jederzeit visuelle Grafiken (z. B. mit Grafana oder Excel) erzeugen kann.

                                    Mir ist ein funktionierendes System und der reale Zählerwert wichtiger als tägliche Diagramme.
                                    Interessanter ist am Ende, was auf der Stromrechnung steht – das ist für mich KISS (Keep It Simple, Stupid).

                                    Zu MQTT & zenSDK:
                                    Du hast recht: Das von Zendure offiziell angebotene lokale MQTT ist mit Aktualisierungsraten von bis zu 90 Sekunden leider sehr langsam.

                                    Deshalb habe ich hier mein Skript für das zenSDK (HTTP) bereitgestellt.
                                    Es ist aktuell der beste Weg: Man bleibt bei der offiziellen Schnittstelle, kann App und Cloud weiterhin nutzen und ist dennoch deutlich schneller als das gedrosselte lokale MQTT.
                                    Schneller ist nur das Umbiegen der Cloud-URL (DNS-Umleitung auf lokale IP).
                                    Dann verliert man aber App und natürlich auch die Cloud, was die meisten nicht möchten.

                                    Zu setDeviceAutomationInOutLimit:
                                    Das ist eine adapterinterne Komfortfunktion und kein offizieller Bestandteil des Zendure-Systems.
                                    Soll Bedienung vereinfachen, löst aber im Hintergrund Befehlsketten aus, die für den Nutzer nicht direkt ersichtlich sind.

                                    Ich bevorzuge die volle, eigenverantwortliche Kontrolle über jeden einzelnen Befehl, basierend auf dem offiziellen Zendure-Protokoll.
                                    So weiß ich genau, was wann gesendet wird und vermeide unvorhergesehene Nebeneffekte oder unnötige Schreibvorgänge im Flash-Speicher.

                                    Jeder soll für sich entscheiden, wie viel Abstraktion oder Kontrolle er in seinem System möchte.
                                    Mehr möchte ich dazu eigentlich nicht sagen.

                                    Ich schreibe meistens sehr direkt – bitte nicht falsch verstehen, es ist nie böse gemeint. Das ist einfach mein Stil und niemals abwertend gemeint.

                                    1 Antwort Letzte Antwort
                                    0
                                    • C cbrocker

                                      Hallo,
                                      ich lese hier hin und wieder mit und habe mir auch den Adapter von nograx mal heruntergeladen, aber noch nicht wirklich eingerichtet. Bisher lese ich ein paar Daten vom SF800 per http request aus.

                                      Ich habe mal mit KI ein Script erstellen lassen, das mir den Tagesertrag anhand der laufenden PV-Produktion berechnet, aber der Wert stimmt nicht ganz mit dem in der App überein.

                                      Frage: werden im Adapter von nograx die PV-Daten (Erträge für Tag, Monat, Jahr usw.) ausgelesen oder berechnet?

                                      Danke

                                      maxclaudiM Offline
                                      maxclaudiM Offline
                                      maxclaudi
                                      schrieb am zuletzt editiert von
                                      #231

                                      @cbrocker sagte in Zendure SmartMode:1 SolarFlow2400 AC SolarFlow800 ( u. Pro):

                                      Ich habe mal mit KI ein Script erstellen lassen, das mir den Tagesertrag anhand der laufenden PV-Produktion berechnet, aber der Wert stimmt nicht ganz mit dem in der App überein.

                                      Nachtrag:
                                      Du kannst davon ausgehen, dass Dein Script genauer ist als die App-Anzeige.
                                      Anders macht das Zendure auch nicht.

                                      Es gibt mehrere keys: xxx_PowerXCycle mit entsprechenden Werten.
                                      u. a. auch für aktuelle PV-Leistung
                                      z.B.: solarPower1Cycle mit xW für MPPT1 etc.

                                      Der Mittel-Wert solarPower1Cycle dient der Aggregation von Daten für Statistiken und Diagramme

                                      Während solarPower1 (ca. Echtzeitwert) für offizielle, lokale Anbindung übertragen wird, wird solarPower1Cycle (Zykluswert/Mittelwert) ca alle 60 sek aktualisiert und nur zur Cloud übertragen.
                                      (Solange Wert-Änderungen kommen, habe ich Intervalle von 58~61 sek. geloggt.)
                                      solarPower1Cycle ist also der gemittelte oder kumulierte Wert über 60 sek.

                                      Die Zendure-Cloud nutzt diese Cycle-Werte, um die Datenbanklast zu reduzieren.
                                      Statt tausende Einzelwerte pro Tag zu speichern, werden diese 1-Minuten-Pakete genutzt, um Tages-, Monats- und Jahreserträge zu berechnen und in den App-Diagrammen darzustellen.

                                      solarPower1Cycle und andere Cycle-Werte werden (bisher) nicht bei offizieller lokaler Anbindung in properties übertragen.
                                      Nur wenn man Cloud-DNS auf lokale IP umprogrammiert oder umleitet.

                                      Ich schreibe meistens sehr direkt – bitte nicht falsch verstehen, es ist nie böse gemeint. Das ist einfach mein Stil und niemals abwertend gemeint.

                                      1 Antwort Letzte Antwort
                                      0
                                      • D Daniel 8

                                        Ergebnis war positiv heute Nacht. Er hat wie sonst auch ca. 2% verloren.

                                        Die Änderung am Script war doch nicht so einfach, weil er am unteren soc nicht abgeschaltet hat. Habe es bisschen geändert und hoffe das es so läuft.

                                        maxclaudiM Offline
                                        maxclaudiM Offline
                                        maxclaudi
                                        schrieb am zuletzt editiert von maxclaudi
                                        #232

                                        @Daniel-8 und @mabbi und Alle
                                        habe nun endlich ein neues Gerät zum testen erhalten.

                                        Dabei fiel mir gleich in meinem bisherigen Script die unübersichtliche Struktur auf.

                                        Auch beim Start gab es Warnungen, wenn erstmals neue Verzeichnisse angelegt wurden.
                                        Hat mir niemand geschrieben.

                                        Korrigiert und optimiert.

                                        Das Script ist ein vollwertiger Adpater-Ersatz.

                                        Das -1 setzen wurde entfernt.
                                        Beim setzen eines Control-State wird der Wert gesendet und gleich mit dem bestätigten Wert aktualisiert.

                                        Intervall von 8 s (für die State-Abfrage/Report) läuft mit diesem Script problemlos (Queue Sicherung), wenn Netzwerkverbindung Zendure <> WLAN-Router ok ist.

                                        MQTT (lokal) ist per Slider (boolean default deaktiviert).
                                        Wenn deaktiviert, ist die MQTT-Script-Funktion komplett ausgeschaltet:

                                        • MQTT-Intervall wird nicht ausgeführt
                                        • dadurch keine MQTT-Statusabfrage
                                        • kein Ein-/Auschalten von lokalem MQTT möglich
                                        • MQTT- Datenfelder im Kofig-Block sind dann bedeutungslos.

                                        Keine Fehler bei Start. Fehlende Verzeichnisse und Datenpunkte werden automatisch erstellt.

                                        Sollten neue Datenpunkte hinzukommen (durch Frimwareupdate) werden sie als Datenpunkte automatisch erstellt.

                                        Neue Struktur.
                                        Haupt-Verzeichnis kann im Konfigblock leicht auf einen sinnvollen, eigenen Namen geändert werden.
                                        Hinweis: wenn man auf

                                        + SN;
                                        

                                        dort verzichtet, dann ist der Verzeichnis-Name auch ohne Seriennummer des Geräts zur Unterscheidung.
                                        Die Seriennummer muss hier nicht verwendet werden, der Verzeichnis-Name muss bei mehreren Geräten aber unterschiedlich sein.

                                        Script ist erprobt. Einige keys, die mir bekannt sind, wurden unter control nicht aufgenommen, weil sie Geräte-spezifisch sind, Gefahren darstellen und/oder (noch?) nicht offiziell unterstützt werden.... wie auch immer.

                                        Bin etwas entäuscht von zenSDK.
                                        Manche keys werden von dem Zendure-Gerät-Webserver nicht oder unregelmäßig aktualisiert.

                                        Neue Struktur des Scripts:
                                        script.png

                                        minTimeBreakForSetDpSec = 5;
                                        Ist einstellbar. 5 sek. haben sich bei mir bewährt.
                                        Nach dem setzen eines Befehls müssen mindestens x sek. vergangen sein um einen neuen zu senden.

                                        Es sind mehrere Sicherungen eingebaut.
                                        Kommentare im Konfig-Bereich bitte lesen.

                                        Script ist ein Adapter-Ersatz.
                                        In meinen Augen der ehrlichste.
                                        Es werden keine Befehle und keine Befehlsketten gesendet, von denen man nichts weiß.
                                        Volle Verantwortung bei dem user.
                                        Auch smartMode wird nicht automatisch geschaltet.

                                        // ioBroker JavaScript: Zendure zenSDK Adapter-Ersatz
                                        // für alle Geräte ab 2025 die zenSDK unterstützen wie
                                        // SF800, SF800 PLUS, 800Pro, 1600AC, SF2400AC usw.
                                        // by maxclaudi 2026.03.30_19.10h for ioBroker Forum
                                        //------------------------------------------------------------------------------------
                                        // konfiguration
                                        //
                                        // Hinweis bei mehreren Zendure-Geräten:
                                        // - Für jedes Gerät ein eigenes Script mit individueller Konfiguration verwenden!
                                        //   -> IP-Adresse
                                        //   -> Seriennummer (SN)
                                        //   -> MQTT-Daten (Broker, Port, Benutzer, Passwort)
                                        //   -> maxInputLimit / maxOutputLimit (abhängig vom Gerätetyp)
                                        // - Intervalle (Standard): intervalGet = 10s, intervalMqtt = 300s – können gleich bleiben
                                        //
                                        // Empfehlung:
                                        //   • 3 Geräte: völlig unkritisch
                                        //   • 4 Geräte: problemlos möglich
                                        //   • mehr als 4: nicht empfohlen
                                        //
                                        // MQTT-Abfrage ist per default false=disabled. Lokales, offizielles MQTT ist mit bis zu 90sek Aktualisierungsrate zu langsam.
                                        // Empfehle zenSDK zu verwenden oder DNS auf lokalen Betrieb umzubiegen.
                                        // Wer offizielles, lokale MQTT dennoch benutzen möchte und überwachen möchte kann den Datenpunkt mit dem Slider einschalten.
                                        // Satndardist bei script-Start MQTT-Abfrage ausgeschaltet und wird dann vom script komplett deaktiviert.
                                        // Auch kein Intervall und keine Aktualisierung erfolgt dann.
                                        //
                                        // Damit neue Datenpunkte automatisch aus dem JSON erstellt werden:
                                        // -> Instanzen -> javascript-Adapter -> Allgemeine Einstellungen -> Enable command"setObject“ aktivieren!
                                        //
                                        // Datenpunkte bei set werden automatisch aktualisiert und nicht auf -1 zurück gesetzt.
                                        //------------------------------------------------------------------------------------
                                        
                                        //------------------------------------------------------------------------------------
                                        // CONFIG
                                        //------------------------------------------------------------------------------------
                                        // Intervalle für Abfragen (Sekunden)
                                        const intervalGet = 8;                  // sek Intervall für GET report (default: 8, nicht <8) intervalGet MUSS größer sein als timeoutHttp !!
                                        const intervalMqtt = 300;                // sek MQTT-Status (default: 300 sek, > intervalGet) wird nur ausgeführt wenn Abfrage über SetMqttEnable eingeschaltet wird.
                                        
                                        // IP und Seriennummer Zendure Gerät
                                        const IP = "192.168.40.20";              // IP des Zendure Geräts
                                        const SN = "Exxxxxxxxxxx007";            // Seriennummer
                                                     
                                        // MQTT Broker Konfiguration
                                        const mqttBrokerIp = "192.168.40.200";  // IP MQTT Broker und in App eingestellt 
                                        const mqttPort = 1883;                  // PORT MQTT Broker und in App eingestellt           
                                        const mqttUsername = "Daisy";           // MQTT Username
                                        const mqttPassword = "coco";            // MQTT Passwort
                                        
                                        //maximum inputLimit SF800 800W / SF800 PRO: 1000W / 1600AC: 1600 / SF2400AC: 2400W
                                        const maxInputLimit = 1000;
                                        
                                        //maximum outputLimit SF800 800W / SF800 PRO: 800W / 1600AC: 1600 / SF2400AC: 2400W
                                        const maxOutputLimit = 800;
                                        
                                        // Pause (Wert in Sekunden) die vergangen sein muss bevor ein neuer Befehl gesendet werden kann.
                                        const minTimeBreakForSetDpSec = 5; // 5 s hat sich bei mir bewährt, minimal 2s!
                                        
                                        // Haupt-Verzeichnis für das Zendure-Gerät
                                        // hier kann der Name für das Hauptverzeichnis für das Gerät verändert werden.
                                        // Standard wird die Seriennummer verwendet. Es kann aber durch einen beliebigen Namen ersetzt werden.
                                        // Beispiel:
                                        //const folderZendureApi = '0_userdata.0.zendure.' + "SolarFlow_800_1_Dachboden_links";
                                        const folderZendureApi = '0_userdata.0.zendure.' + SN;
                                        //
                                        // Timout Handler HTTP GET /POST
                                        // timeoutHttp MUSS kleiner sein als intervalGet!! Besser nicht ändern. Standard: 2000ms
                                        const timeoutHttp = 2000; // Timeout in ms für alle HTTP-Anfragen (Zendure)
                                        //------------------------------------------------------------------------------------
                                        // End of config
                                        //------------------------------------------------------------------------------------
                                        
                                        const mqttStateAskingDefault = false; // nicht verändern! Kann bei laufendem script ein- oder ausgeschaltet werden
                                        let lastMqttSet = 0;
                                        let mqttInterval = null;
                                        
                                        //------------------------------------------------------------------------------------
                                        // dp
                                        //------------------------------------------------------------------------------------
                                        
                                        const dpSetSmartMode        = folderZendureApi + ".control.setSmartMode";
                                        const dpSetAcMode           = folderZendureApi + ".control.setAcMode";
                                        const dpSetInputLimit       = folderZendureApi + ".control.setInputLimit";
                                        const dpSetOutputLimit      = folderZendureApi + ".control.setOutputLimit";
                                        const dpSetSocSet           = folderZendureApi + ".control.setSocSet";
                                        const dpSetMinSoc           = folderZendureApi + ".control.setMinSoc";
                                        const dpSetGridReverse      = folderZendureApi + ".control.setGridReverse";
                                        const dpSetGridStandard     = folderZendureApi + ".control.setGridStandard";
                                        const dpSetInverseMaxPower  = folderZendureApi + ".control.setInverseMaxPower";
                                        const dpSetChargeMaxLimit   = folderZendureApi + ".control.setChargeMaxLimit";
                                        const dpSetGridOffMode      = folderZendureApi + ".control.setGridOffMode";
                                        
                                        const dpSetMqttEnable       = folderZendureApi + ".control.localMqtt.EnableScriptControlLocalMqtt";
                                        const dpSetMqttConnect      = folderZendureApi + ".control.localMqtt.SetConnectlocalMqtt";
                                        const dpMqttConnectInfo     = folderZendureApi + ".control.localMqtt.InfoLocalMqttConnected";
                                        
                                        const dpTimestamp           = folderZendureApi + ".timestamp";
                                        
                                        //------------------------------------------------------------------------------------
                                        // mapping
                                        //------------------------------------------------------------------------------------
                                        const dpMap = {
                                            [dpSetSmartMode]:       { key: "smartMode", min: 0, max: 1 },
                                            [dpSetAcMode]:          { key: "acMode", min: 1, max: 2 },
                                            [dpSetInputLimit]:      { key: "inputLimit", min: 0, max: maxInputLimit },
                                            [dpSetOutputLimit]:     { key: "outputLimit", min: 0, max: maxOutputLimit },
                                            [dpSetSocSet]:          { key: "socSet", transform: v => v*10, min: 70, max: 100 },
                                            [dpSetMinSoc]:          { key: "minSoc", transform: v => v*10, min: 5, max: 50 },
                                            [dpSetGridReverse]:     { key: "gridReverse", min: 0, max: 2 },
                                            [dpSetGridStandard]:    { key: "gridStandard", min: 0, max: 2 },
                                            [dpSetInverseMaxPower]: { key: "inverseMaxPower", min: 600, max: maxOutputLimit },
                                            [dpSetChargeMaxLimit]:  { key: "chargeMaxLimit", min: 0, max: maxInputLimit },
                                        	//[dpSetbatCalTime]:     { key: "chargeMaxLimit", min: 0, max: maxInputLimit },
                                        	//[dpSetFanmode]:         { key: "fanSwitch", min: 0, max: 1 },
                                        	//[dpSetFanspeed]:        { key: "fanSpeed", min: 0, max: 2 },
                                        	[dpSetGridOffMode]:     { key: "gridOffMode", min: 0, max: 2 }
                                        };
                                        
                                        //------------------------------------------------------------------------------------
                                        // QUEUE
                                        //------------------------------------------------------------------------------------
                                        const curlQueue = [];
                                        let curlRunning = false;
                                        
                                        function runQueue() {
                                            if (curlRunning || curlQueue.length === 0) return;
                                            const task = curlQueue.shift();
                                            curlRunning = true;
                                            task.fn(() => {
                                                curlRunning = false;
                                                runQueue();
                                            });
                                        }
                                        
                                        //------------------------------------------------------------------------------------
                                        // helper
                                        //------------------------------------------------------------------------------------
                                        function delay(ms) {
                                            return new Promise(resolve => setTimeout(resolve, ms));
                                        }
                                        
                                        function formatTime(ts) {
                                            const d = new Date(ts * 1000);
                                            const pad = n => n.toString().padStart(2, "0");
                                            return `${pad(d.getDate())}.${pad(d.getMonth()+1)}.${d.getFullYear().toString().slice(-2)} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
                                        }
                                        
                                        function handleHttpError(context, err, options) {
                                        	const transient = [
                                                "EHOSTUNREACH", "ECONNRESET", "ECONNREFUSED", "ETIMEDOUT",
                                                "socket hang up", "ENETUNREACH", "EAI_AGAIN", "ENOTFOUND"
                                            ];
                                        	
                                        	const msg = err && err.message ? err.message : String(err);
                                            const isTransient = transient.some(code => msg.includes(code));
                                         
                                            //info_error
                                        	//log(`${context}: ${isTransient ? "war vorübergehend im Intervall nicht erfolgreich:" : "Warnung"} (${msg})`, isTransient ? "info" : "warn");
                                            log(`${context}: ${isTransient ? "war vorübergehend im Intervall nicht erfolgreich:" : "Warnung"} (${msg})`, "info");
                                         
                                            // set Timestamp
                                            if (options && options.timestamp) {
                                                setState(options.timestamp, formatTime(Math.floor(Date.now() / 1000)), true);
                                            }
                                        }
                                        
                                        //------------------------------------------------------------------------------------
                                        // CREATE STATES
                                        //------------------------------------------------------------------------------------
                                        const dataPoints = [
                                            { id: dpSetSmartMode, val: 0, common: { name: "Smart Mode 0:FLASH 1:RAM",desc: "Flash write behavior", type: "number", role: "state", min: 0, max: 1 } },
                                            { id: dpSetAcMode, val: 1, common: { name: "AC Mode 1:charge mode 2:discharge mode", type: "number", role: "state", min: 1, max: 2 } },
                                            { id: dpSetInputLimit, val: 0, common: { name: "Input Limit AC charge limit", type: "number", role: "state", min: 0, max: maxInputLimit, unit: 'W' } },
                                            { id: dpSetOutputLimit, val: 0, common: { name: "Output Limit", type: "number", role: "state", min: 0, max: maxOutputLimit, unit: 'W' } },
                                            { id: dpSetSocSet, val: 70, common: { name: "SOC Set (Target SOC 70%-100%)", type: "number", role: "state", min: 70, max: 100, unit: '%' } },
                                            { id: dpSetMinSoc, val: 5, common: { name: "Min SOC (Minimum SOC 5%-50%)", type: "number", role: "state", min: 5, max: 50, unit: '%' } },
                                            { id: dpSetGridReverse, val: 0, common: { name: "Reverse flow control (0/1/2)", type: "number", role: "state", min: 0, max: 2 } },
                                            { id: dpSetGridStandard, val: 0, common: { name: "Grid Standard (0: Germany 1: France 2: Austria...)", desc: "(3: Switzerland 4: Netherlands 5: Spain 6: Belgium 7: Greece 8: Denmark 9: Italy)", type: "number", role: "state", min: 0, max: 9 } },
                                            { id: dpSetInverseMaxPower, val: 600, common: { name: "Max inverter output Power", type: "number", role: "state", min: 600, max: maxOutputLimit, unit: 'W' } },
                                            { id: dpSetChargeMaxLimit, val: 0, common: { name: "Charge Max Limit", type: "number", role: "state", min: 0, max: maxInputLimit, unit: 'W' } },
                                        	{ id: dpSetGridOffMode, val: 0, common: { name: "Grid Off Mode 0: Standard Mode  1: Economic Mode  2: Closure", type: "number", role: "state", min: 0, max: 2 } },
                                        	{ id: dpSetMqttEnable, val: mqttStateAskingDefault, common: { name: "Enable Script-Control of Local Mqtt: Off ON", type: "boolean", role: "state", read: true, write: true } },
                                            { id: dpSetMqttConnect, val: 0, common: { name: "Set Connect localMqtt -> only if EnableScriptControlLocalMqtt: on", type: "number", role: "indicator", read: true, write: true } },
                                            { id: dpMqttConnectInfo, val: 0, common: { name: "Info Local Mqtt Connected 0:off 1:on -> only if EnableScriptControlLocalMqtt: on", type: "number", role: "indicator", read: true, write: false } },
                                            { id: dpTimestamp, val: "", common: { name: "Timestamp", type: "string", role: "state", read: true, write: false } }
                                        ];
                                        
                                        async function startScript() {
                                            console.log("Erstelle Datenpunkte...");
                                            for (const dp of dataPoints) {
                                                await createStateAsync(dp.id, dp.val, dp.common);
                                            }
                                            
                                            setState(dpSetMqttEnable, mqttStateAskingDefault, true);
                                            console.log("Datenpunkte bereit. Starte Abfragen...");
                                            setInterval(getReport, intervalGet * 1000);
                                            getReport(); 
                                        }
                                        
                                        startScript();
                                        
                                        
                                        //------------------------------------------------------------------------------------
                                        // TRIGGERS (SET)
                                        //------------------------------------------------------------------------------------
                                        Object.keys(dpMap).forEach(id => {
                                            let lastSetTime = 0;
                                        
                                            on({ id: id, ack: false }, obj => {
                                                const val = obj.state.val;
                                                const { min, max } = dpMap[id];
                                        
                                                if (val >= min && val <= max) {
                                                    const now = Date.now();
                                                    if (now - lastSetTime >= minTimeBreakForSetDpSec * 1000) {
                                                        lastSetTime = now;
                                                        setControlDP(id, val);
                                                    }
                                                }
                                            });
                                        });
                                        
                                        // MQTT POST nur wenn enable=true + rate limit
                                        on({ id: dpSetMqttConnect, ack: false }, obj => {
                                        
                                            if (!getState(dpSetMqttEnable).val) return;
                                        
                                            const now = Date.now();
                                            if (now - lastMqttSet < minTimeBreakForSetDpSec * 1000) return;
                                        
                                            lastMqttSet = now;
                                        
                                            const val = parseInt(obj.state.val, 10);
                                            if (val === 0 || val === 1) setMqttConnect(val);
                                        });
                                        
                                        //------------------------------------------------------------------------------------
                                        // HTTP
                                        //------------------------------------------------------------------------------------
                                        const http = require("http");
                                        
                                        function setControlDP(id, val) {
                                            const { key, transform } = dpMap[id];
                                            const value = transform ? transform(val) : val;
                                        
                                            curlQueue.push({
                                                fn: done => {
                                                    const payload = JSON.stringify({ sn: SN, properties: { [key]: value } });
                                        
                                                    const req = http.request({
                                                        hostname: IP,
                                                        port: 80,
                                                        path: "/properties/write",
                                                        method: "POST",
                                                        headers: { 
                                                            "Content-Type": "application/json", 
                                                            "Content-Length": Buffer.byteLength(payload) 
                                                        }
                                                    }, res => {
                                                        res.on("data", () => {});
                                                        res.on("end", () => {
                                                            // nach Schreiben sofort anfordern
                                                            curlQueue.unshift({ fn: d => getReportInternal(d) });
                                                            done(); // freigeben
                                                        });
                                                    });
                                        
                                                    // Timeout
                                                    req.setTimeout(timeoutHttp, () => {
                                                        req.destroy(); // Verbindung hart abbrechen
                                                        handleHttpError("POST Timeout", "Gerät antwortet nicht", { timestamp: dpTimestamp });
                                                        done(); // WICHTIG: Queue freigeben, damit nächste Befehle folgen können
                                                    });
                                        
                                                    // Fehler
                                                    req.on("error", err => { 
                                                        handleHttpError("POST Error", err, { timestamp: dpTimestamp }); 
                                                        done();
                                                    });
                                        
                                                    req.write(payload);
                                                    req.end();
                                                }
                                            });
                                        
                                            runQueue();
                                        }
                                        
                                        
                                        function getReport() {
                                            curlQueue.push({ fn: done => getReportInternal(done) });
                                            runQueue();
                                        }
                                        
                                        function getReportInternal(done) {
                                            const req = http.request({
                                                hostname: IP,
                                                port: 80,
                                                path: "/properties/report",
                                                method: "GET"
                                            }, res => {
                                                let data = "";
                                                res.on("data", chunk => data += chunk);
                                                res.on("end", async () => {
                                                    try {
                                                        const json = JSON.parse(data);
                                                        if (json.properties) {
                                                            Object.keys(dpMap).forEach(dp => {
                                                                const { key } = dpMap[dp];
                                                                if (json.properties[key] !== undefined) {
                                                                    setState(dp, json.properties[key], true);
                                                                }
                                                            });
                                                        }
                                                        setState(dpTimestamp, formatTime(Math.floor(Date.now()/1000)), true);
                                                        await processJson(json);
                                                    } catch (e) {
                                                        log("GET parse error: " + e, "info");
                                                    }
                                                    done(); // WICHTIG: Queue freigeben nach Erfolg
                                                });
                                            });
                                        
                                            
                                            // Fehler
                                            req.on("error", err => { 
                                                handleHttpError("GET Error", err, { timestamp: dpTimestamp }); 
                                                done(); // WICHTIG: Queue freigeben bei Fehler
                                            });
                                        
                                            // Timeout
                                            req.setTimeout(timeoutHttp, () => {
                                                req.destroy(); // Verbindung abbrechen
                                                handleHttpError("GET Timeout", "Gerät antwortet nicht", { timestamp: dpTimestamp });
                                                done(); // WICHTIG: Queue freigeben bei Zeitüberschreitung
                                            });
                                            req.end();
                                        }
                                        
                                        //------------------------------------------------------------------------------------
                                        // MQTT
                                        //------------------------------------------------------------------------------------
                                        
                                        // Enable-Schalter nur Steuerung, kein POST
                                        on({ id: dpSetMqttEnable, ack: false }, obj => {
                                        
                                            const enable = !!obj.state.val;
                                            setState(dpSetMqttEnable, enable, true);
                                        
                                            if (enable) {
                                        
                                                // sofort GET
                                                curlQueue.push({ fn: d => getMqttStatusInternal(d) });
                                                runQueue();
                                        
                                                // Intervall start
                                                if (!mqttInterval) {
                                                    mqttInterval = setInterval(() => {
                                                        curlQueue.push({ fn: d => getMqttStatusInternal(d) });
                                                        runQueue();
                                                    }, intervalMqtt * 1000);
                                                }
                                        
                                            } else {
                                        
                                                if (mqttInterval) {
                                                    clearInterval(mqttInterval);
                                                    mqttInterval = null;
                                                }
                                            }
                                        });
                                        
                                        function getMqttStatusInternal(done) {
                                        
                                            const req = http.request({
                                                hostname: IP,
                                                port: 80,
                                                path: "/rpc?method=HA.Mqtt.GetStatus",
                                                method: "GET"
                                            }, res => {
                                        
                                                let data = "";
                                        
                                                res.on("data", chunk => data += chunk);
                                        
                                                res.on("end", () => {
                                        
                                                    try {
                                                        const json = JSON.parse(data);
                                                        const state = json.connected ? 1 : 0;
                                        
                                                        // readonly
                                                        setState(dpMqttConnectInfo, state, true);
                                        
                                                        // sync setDP (OHNE trigger)
                                                        setState(dpSetMqttConnect, state, true);
                                        
                                                    } catch (e) {
                                                        log("MQTT parse error: " + e, "info");
                                                    }
                                        
                                                    done();
                                                });
                                            });
                                        
                                            req.on("error", err => { handleHttpError("MQTT GET", err, { timestamp: dpTimestamp }); done(); });
                                        
                                            req.end();
                                        }
                                        
                                        function setMqttConnect(enable) {
                                        
                                            const payload = JSON.stringify({
                                                sn: SN,
                                                method: "HA.Mqtt.SetConfig",
                                                params: {
                                                    config: {
                                                        enable: !!enable,
                                                        server: mqttBrokerIp,
                                                        port: mqttPort,
                                                        protocol: "mqtt",
                                                        username: mqttUsername,
                                                        password: mqttPassword
                                                    }
                                                }
                                            });
                                        
                                            curlQueue.push({
                                                fn: done => {
                                        
                                                    const req = http.request({
                                                        hostname: IP,
                                                        port: 80,
                                                        path: "/rpc",
                                                        method: "POST",
                                                        headers: { "Content-Type": "application/json", "Content-Length": Buffer.byteLength(payload) }
                                                    }, res => {
                                                        res.on("data", () => {});
                                                        res.on("end", () => done());
                                                    });
                                        
                                                    req.on("error", err => { handleHttpError("MQTT POST", err, { timestamp: dpTimestamp }); done(); });
                                        
                                                    req.write(payload);
                                                    req.end();
                                                }
                                            });
                                        
                                            runQueue();
                                        }
                                        
                                        //------------------------------------------------------------------------------------
                                        // JSON
                                        //------------------------------------------------------------------------------------
                                        async function processJson(obj) {
                                            try {
                                                if (!obj || !obj.product) return;
                                         
                                                const product = obj.product;
                                                const basePath = `${folderZendureApi}.${product}`;
                                         
                                                // create product folder if not exist
                                                if (!existsObject(basePath)) {
                                                    setObject(basePath, {
                                                        type: 'folder',
                                                        common: { name: product },
                                                        native: {},
                                                    });
                                                }
                                         
                                                // create main keys
                                                const mainKeys = ['timestamp', 'messageId', 'sn', 'version', 'product'];
                                                for (const key of mainKeys) {
                                                    if (obj[key] !== undefined) {
                                                        const statePath = `${basePath}.${key}`;
                                                        if (existsState(statePath)) {
                                                            setState(statePath, obj[key], true);
                                                        } else {
                                                            createState(statePath, obj[key], {
                                                                name: key,
                                                                type: typeof obj[key],
                                                                role: 'info',
                                                                read: true,
                                                                write: false,
                                                            });
                                                        }
                                                    }
                                                }
                                         
                                                // properties
                                                if (obj.properties) {
                                                    await iter(`${basePath}.properties`, obj.properties);
                                                }
                                         
                                                // PackData
                                                if (obj.packData && Array.isArray(obj.packData)) {
                                                    await iter(`${basePath}`, { packData: obj.packData, timestamp: obj.timestamp });
                                                }
                                            } catch (e) {
                                                log(`Error processing JSON: ${e}`, 'info');
                                            }
                                        }
                                         
                                        //------------------------------------------------------------------------------------
                                        // Battery
                                        //------------------------------------------------------------------------------------
                                        function getBatteryType(sn, model) {
                                          let batType = '';
                                          if (sn?.startsWith('A')) batType = 'AB1000';
                                          else if (sn?.startsWith('B')) batType = 'AB1000S';
                                          else if (sn?.startsWith('C')) batType = sn[3] === 'F' ? 'AB2000S' : sn[3] === 'E' ? 'AB2000X' : 'AB2000';
                                          else if (sn?.startsWith('F')) batType = 'AB3000X';
                                          if (model?.trim()) batType = model.trim();
                                          return batType || 'unknown';
                                        } 
                                         
                                        //------------------------------------------------------------------------------------
                                        // helper Iteration
                                        //------------------------------------------------------------------------------------
                                        async function iter(id, obj) {
                                            try {
                                        		if (!obj || typeof obj !== "object") {
                                                   //log("iter: Ungültiges oder leeres Objekt übersprungen", "info");
                                                   return;
                                                   }
                                        		for (let i in obj) {
                                                    if (i === 'packData' && Array.isArray(obj[i])) {
                                                        const ts = obj.timestamp ? obj.timestamp * 1000 : Date.now();
                                                        for (const pack of obj[i]) {
                                                            if (!pack.sn) continue;
                                                            const sn = pack.sn;
                                                            const path = `${id}.packData.${sn}`;
                                         
                                                            if (!existsObject(path)) {
                                                                setObject(path, {
                                                                    type: 'folder',
                                                                    common: { name: sn },
                                                                    native: {},
                                                                });
                                                            }
                                         
                                                            for (let [key, val] of Object.entries(pack)) {
                                                                const statePath = `${path}.${key}`;
                                                                switch (key) {
                                                                    case 'batcur':
                                                                        val = (val << 16 >> 16) / 10;
                                                                        if (existsState(statePath)) {
                                                                            setState(statePath, val, true);;
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                                name: 'Battery Current',
                                                                                type: 'number',
                                                                                desc: 'battery current',
                                                                                role: 'value',
                                                                                read: true,
                                                                                write: false,
                                                                                unit: 'A',
                                                                            });
                                                                        }
                                                                        break;
                                        							case 'heatState':
                                                                        if (existsState(statePath)) {
                                                                            setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                                name: 'Heat State, 0: Not heating, 1: heating',
                                                                                type: 'number',
                                                                                role: 'value',
                                                                                read: true,
                                                                                write: false,
                                                                            });
                                                                        }
                                                                        break;		
                                        							case 'maxTemp':
                                                                        val = (val - 2731) / 10;
                                                                        if (existsState(statePath)) {
                                                                            setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                                name: 'Highest Akku Temperature',
                                                                                type: 'number',
                                                                                desc: 'maximum temperature',
                                                                                role: 'value',
                                                                                read: true,
                                                                                write: false,
                                                                                unit: '°C',
                                                                            });
                                                                        }
                                                                        break;
                                                                    case 'maxVol':
                                                                        val = val / 100;
                                                                        if (existsState(statePath)) {
                                                                            setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                                name: 'Highest Cell Voltage',
                                                                                type: 'number',
                                                                                desc: 'highest cell voltage',
                                                                                role: 'value',
                                                                                read: true,
                                                                                write: false,
                                                                                unit: 'V',
                                                                            });
                                                                        }
                                                                        break;
                                                                    case 'minVol':
                                                                        val = val / 100;
                                                                        if (existsState(statePath)) {
                                                                            setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                                name: 'Lowest Cell Voltage',
                                                                                type: 'number',
                                                                                desc: 'lowest cell voltage',
                                                                                role: 'value',
                                                                                read: true,
                                                                                write: false,
                                                                                unit: 'V',
                                                                            });
                                                                        }
                                                                        break;
                                        							case 'packType':
                                                                        if (existsState(statePath)) {
                                                                            setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                                name: 'packType',
                                                                                type: 'number',
                                                                                role: 'value',
                                                                                read: true,
                                                                                write: false,
                                                                            });
                                                                        }
                                                                        break;
                                        							case 'power':
                                                                        if (existsState(statePath)) {
                                                                            setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                                name: 'Battery Power',
                                                                                type: 'number',
                                                                                role: 'value',
                                                                                read: true,
                                                                                write: false,
                                                                                unit: 'W',
                                                                            });
                                                                        }
                                        								break;
                                        							case 'sn':
                                                                    const batType = getBatteryType(val, pack.model);
                                                                    // Modelltyp als Datenpunkt setzen/erstellen
                                                                    const modelPath = `${path}.model`;
                                                                    if (existsState(modelPath)) {
                                        								setState(modelPath, batType, true);
                                                                        } else {
                                                                            createState(modelPath, batType, {
                                                                            name: 'Battery Model',
                                                                            type: 'string',
                                                                            role: 'text',
                                                                            read: true,
                                                                            write: false,
                                                                            });
                                                                           }
                                                                        break;
                                        							case 'socLevel':
                                                                        if (existsState(statePath)) {
                                                                            setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                                name: 'Battery SoC Level',
                                                                                type: 'number',
                                                                                role: 'value',
                                                                                read: true,
                                                                                write: false,
                                                                                unit: '%',
                                                                            });
                                                                        }
                                        								break;
                                        							case 'softVersion':
                                                                        if (existsState(statePath)) {
                                                                            setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                                name: 'Battery Software Version',
                                                                                type: 'number',
                                                                                role: 'value',
                                                                                read: true,
                                                                                write: false,
                                                                            });
                                                                        }
                                        								break;
                                        							case 'state':
                                                                        if (existsState(statePath)) {
                                                                            setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                                name: 'Battery, 0: Standby, 1: Charging, 2: Discharging',
                                                                                type: 'number',
                                                                                role: 'value',
                                                                                read: true,
                                                                                write: false,
                                                                            });
                                                                        }
                                        								break;	
                                                                    case 'totalVol':
                                                                        val = val / 100;
                                                                        if (existsState(statePath)) {
                                                                            setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                                name: 'Total Voltage',
                                                                                type: 'number',
                                                                                desc: 'total voltage',
                                                                                role: 'value',
                                                                                read: true,
                                                                                write: false,
                                                                                unit: 'V',
                                                                            });
                                                                        }
                                                                        break;
                                                                    default:
                                                                        if (existsState(statePath)) {
                                                                            setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                                name: key,
                                                                                type: typeof val,
                                                                                role: 'value',
                                                                                read: true,
                                                                                write: false,
                                                                            });
                                                                        }
                                                                        break;
                                                                }
                                                            }
                                                        }
                                                    } else {
                                                        const ts = Date.now();
                                                        const statePath = `${id}.${i}`;
                                                        let val = obj[i];
                                         
                                                        switch (i) {
                                                            case 'BatVolt':
                                                                val = val / 100;
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                } else {
                                                                    createState(statePath, val, {
                                                                        name: 'Battery Voltage',
                                                                        type: 'number',
                                                                        desc: 'battery voltage',
                                                                        role: 'value',
                                                                        read: true,
                                                                        write: false,
                                                                        unit: 'V',
                                                                    });
                                                                }
                                                                break;
                                        					case 'chargeMaxLimit':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                } else {
                                                                    createState(statePath, val, {
                                                                        name: 'maximum Charge Power Limit',
                                                                        type: 'number',
                                                                        desc: 'Maximum permissible charging power',
                                                                        role: 'value',
                                                                        read: true,
                                                                        write: false,
                                                                        unit: 'W',
                                                                    });
                                                                }
                                                                break;
                                                            case 'acMode':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                } else {
                                                                    createState(statePath, val, {
                                                                        name: 'acMode, 1: input mode / 2: output mode',
                                                                        type: 'number',
                                                                        desc: '1: charging / 2: discharging',
                                                                        role: 'value',
                                                                        read: true,
                                                                        write: false,
                                                                    });
                                                                }
                                                                break;
                                        					case 'dataReady':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                } else {
                                                                    createState(statePath, val, {
                                                                        name: 'Data Ready, 0: Not ready, 1: Ready',
                                                                        type: 'number',
                                                                        role: 'value',
                                                                        read: true,
                                                                        write: false,
                                                                    });
                                                                }
                                                                break;	
                                        					case 'dcStatus':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                } else {
                                                                    createState(statePath, val, {
                                                                        name: 'dcStatus, 0: Stopped, 1: Battery input, 2: Battery output',
                                                                        type: 'number',
                                                                        role: 'value',
                                                                        read: true,
                                                                        write: false,
                                                                    });
                                                                }
                                                                break;						
                                        					case 'electricLevel':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                } else {
                                                                    createState(statePath, val, {
                                                                        name: 'Total Battery Charge Level',
                                                                        type: 'number',
                                                                        desc: 'SoC',
                                                                        role: 'value',
                                                                        read: true,
                                                                        write: false,
                                                                        unit: '%',
                                                                    });
                                                                }
                                                                break;
                                        					case 'FMVolt':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                } else {
                                                                    createState(statePath, val, {
                                                                        name: 'Voltage activation value',
                                                                        type: 'number',
                                                                        desc: 'SoC',
                                                                        role: 'value',
                                                                        read: true,
                                                                        write: false,
                                                                        unit: 'V',
                                                                    });
                                                                }
                                                                break;
                                                            case 'gridInputPower':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                } else {
                                                                    createState(statePath, val, {
                                                                        name: 'Grid Input Power to Battery',
                                                                        type: 'number',
                                                                        role: 'value',
                                                                        read: true,
                                                                        write: false,
                                                                        unit: 'W',
                                                                    });
                                                                }
                                                                break;
                                                            case 'gridReverse':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                } else {
                                                                    createState(statePath, val, {
                                                                        name: '0: Disabled, 1: Allowed reverse flow, 2: Forbidden reverse flow',
                                                                        type: 'number',
                                                                        role: 'value',
                                                                        read: true,
                                                                        write: false,
                                                                    });
                                                                }
                                                                break;
                                                            case 'gridStandard':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                } else {
                                                                    createState(statePath, val, {
                                                                        name: 'Grid connection standard 0: Germany 1: France 2: Austria',
                                                                        type: 'number',
                                                                        role: 'value',
                                                                        read: true,
                                                                        write: false,
                                                                    });
                                                                }
                                                                break;
                                                            case 'gridState':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                } else {
                                                                    createState(statePath, val, {
                                                                        name: 'Grid connection state, 0: Not connected, 1: Connected',
                                                                        type: 'number',
                                                                        role: 'value',
                                                                        read: true,
                                                                        write: false,
                                                                    });
                                                                }
                                                                break;									
                                                            case 'heatState':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                } else {
                                                                    createState(statePath, val, {
                                                                        name: 'Heat State, 0: Not heating, 1: heating',
                                                                        type: 'number',
                                                                        role: 'value',
                                                                        read: true,
                                                                        write: false,
                                                                    });
                                                                }
                                                                break;		
                                        					case 'hyperTmp':
                                                                val = (val - 2731) / 10.0;
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                            name: 'Enclosure Temperature',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                                                            unit: '°C',
                                                                            });
                                                                        }
                                                                break;
                                        					case 'inputLimit':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                            name: 'AC charging power limit to Battery',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                                                            unit: 'W',
                                                                            });
                                                                        }
                                                                break;
                                        					case 'inverseMaxPower': 
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                            name: 'Max inverter output Power Limit',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                                                            unit: 'W',
                                                                            });
                                                                        }
                                                                break;
                                        					case 'minSoc':
                                                                val = val / 10;
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                            name: 'min SoC',
                                                                            type: 'number',
                                                                            desc: 'minimum Battery SoCset',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                                                            unit: '%',
                                                                            });
                                                                        }
                                                                break;
                                        					case 'outputHomePower':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                        									createState(statePath, val, {
                                                                            name: 'outputHomePower',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                        							        unit: 'W',
                                                                            });
                                        								}
                                                                break;
                                        					case 'outputLimit':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                        									createState(statePath, val, {
                                                                            name: 'Output power limit',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                        							        unit: 'W',
                                                                            });
                                        								}
                                                                break;
                                        					case 'outputPackPower':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                        									createState(statePath, val, {
                                                                            name: 'Output power to battery pack (charging)',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                        							        unit: 'W',
                                                                            });
                                        								}
                                                                break;
                                        					case 'packInputPower':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                        									createState(statePath, val, {
                                                                            name: 'Battery pack input power (discharging)',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                        							        unit: 'W',
                                                                            });
                                        								}
                                                                break;
                                        					case 'packNum':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                        									createState(statePath, val, {
                                                                            name: 'Number of battery packs',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                                                            });
                                        								}
                                                                break;
                                        					case 'packState':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                        									createState(statePath, val, {
                                                                            name: 'Battery State, 0: Standby, 1: Charging, 2: Discharging',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                                                            });
                                        								}
                                                                break;
                                        					case 'pass':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                        									createState(statePath, val, {
                                                                            name: 'Bypass, 0: No, 1: Yes',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                                                            });
                                        								}
                                                                break;
                                        					case 'pvStatus':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                        									createState(statePath, val, {
                                                                            name: 'PV State producing, 0: Stopped, 1: Running',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                                                            });
                                        								}
                                                                break;
                                                            case 'acStatus':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                        									createState(statePath, val, {
                                                                            name: 'AC state 0-2',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                                                            });
                                        								}
                                                                break;							
                                        					case 'remainOutTime':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                        									createState(statePath, val, {
                                                                            name: 'Estimated discharge time in minutes, if not predictable: 59940',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                        									unit: 'min',
                                                                            });
                                        								}
                                                                break;		
                                        					case 'reverseState':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                        									createState(statePath, val, {
                                                                            name: 'Reverse flow, 0: No, 1: Reverse flow',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                                                            });
                                        								}
                                                                break;			
                                        					case 'rssi':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                        									createState(statePath, val, {
                                                                            name: 'Received Signal Strength Indicator',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                        									unit: 'dBm',
                                                                            });
                                        								}
                                                                break;
                                        					case 'gridOffPower':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                            name: 'Off-grid power',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                        									unit: 'W',
                                                                            });
                                                                        }
                                                                break;
                                        					case 'lampSwitch':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                            name: 'Lamp state 0:off 1:on',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                                                            });
                                                                        }
                                                                break;
                                        					case 'gridOffMode':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                            name: 'Off-grid mode',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                                                            });
                                                                        }
                                                                break;
                                        					case 'IOTState':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                            name: 'IoT connection',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                                                            });
                                                                        }
                                                                break;
                                        					case 'fanSwitch':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                            name: 'Fan state 0:off 1:on',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                                                            });
                                                                        }
                                                                break;
                                        					case 'fanSpeed':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                            name: 'Fan level',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                                                            });
                                                                        }
                                                                break;
                                        					case 'faultLevel':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                            name: 'Fault severity',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                                                            });
                                                                        }
                                                                break;
                                        					case 'bindstate':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                            name: 'Bind state',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                                                            });
                                                                        }
                                                                break;
                                        					case 'VoltWakeup':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                            name: 'Voltage wake-up',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                                                            });
                                                                        }
                                                                break;
                                        					case 'OldMode':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                            name: 'Legacy mode',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                                                            });
                                                                        }
                                                                break;
                                        					case 'OTAState':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                            name: 'OTA state',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                                                            });
                                                                        }
                                                                break;
                                        					case 'LCNState':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                            name: 'LCN state',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                                                            });
                                                                        }
                                                                break;
                                        					case 'factoryModeState':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                            name: 'Phase switch',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                                                            });
                                                                        }
                                                                break;
                                        					case 'phaseSwitch':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                            name: 'Factory mode',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                                                            });
                                                                        }
                                                                break;
                                        					case 'is_error':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                            name: 'Error flag 0: no Error  1: Error',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                                                            });
                                                                        }
                                                                break;
                                        					case 'smartMode':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                        									createState(statePath, val, {
                                                                            name: '1: parameter written to RAM / 0: parameter is written to flash.',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                                                            });
                                        								}
                                                                break;		
                                        					case 'socLimit':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                            name: 'socLimit-Info 0: normal, 1: Charge limit reached, 2: Discharge limit reached',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                                                            });
                                                                        }
                                                                break;
                                        					case 'socSet':
                                                                val = val / 10;
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                            name: 'max SoC',
                                                                            type: 'number',
                                                                            desc: 'maximum Battery SoCset',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                                                            unit: '%',
                                                                            });
                                                                        }
                                                                break;
                                        					case 'socStatus':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                            name: 'Info of Calibrating, 0: No / 1: Calibrating',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                                                            });
                                                                        }
                                                                break;
                                        					case 'solarInputPower':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                            name: 'Total Solar Input Power',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                        									unit: 'W',
                                                                            });
                                                                        }
                                                                break;
                                                            case 'solarPower1':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                            name: 'Solar line 1 input power',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                        									unit: 'W',
                                                                            });
                                                                        }
                                                                break;
                                                            case 'solarPower2':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                            name: 'Solar line 2 input power',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                        									unit: 'W',
                                                                            });
                                                                        }
                                                                break;
                                                            case 'solarPower3':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                            name: 'Solar line 3 input power',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                        									unit: 'W',
                                                                            });
                                                                        }
                                                                break;
                                                            case 'solarPower4':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                            name: 'Solar line 4 input power',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                        									unit: 'W',
                                                                            });
                                                                        }
                                                                break;
                                                            case 'solarPower5':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                            name: 'Solar line 5 input power',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                        									unit: 'W',
                                                                            });
                                                                        }
                                                                break;
                                                            case 'solarPower6':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                            name: 'Solar line 6 input power',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                        									unit: 'W',
                                                                            });
                                                                        }
                                                                break;
                                        					case 'timeZone':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                            name: 'Timezone',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                                                            });
                                                                        }
                                                                break;
                                        					case 'tsZone':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                            name: 'Timezone offset',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                                                            });
                                                                        }
                                                                break;
                                        					case 'acCouplingState':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                        									name: 'AC Coupling State',
                                        									type: 'number',
                                        									role: 'value',
                                        									read: true,
                                        									write: false
                                        									});
                                                                        }
                                        						let states = [];
                                        						if (val & (1 << 0)) states.push("AC-coupled input present");
                                        						if (val & (1 << 1)) states.push("AC input present flag");
                                        						if (val & (1 << 2)) states.push("AC-coupled overload");
                                        						if (val & (1 << 3)) states.push("Excess AC input power");
                                        						const statusText = states.length > 0 ? states.join(", ") : "Normal / No Flags";
                                        						const stringPath = statePath + "_String"; // acCouplingState_String
                                        						if (existsState(stringPath)) {
                                        						setState(stringPath, statusText, true);
                                        						} else {
                                        							createState(stringPath, statusText, { name: 'AC Coupling State Info', type: 'string', role: 'text', read: true, write: false });
                                        						}
                                        					break;
                                        					case 'dryNodeState':
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                        } else {
                                                                            createState(statePath, val, {
                                                                            name: 'Dry contact status 1: Connected 0: Connected(May be reversed depending on actual wiring)',
                                                                            type: 'number',
                                                                            role: 'value',
                                                                            read: true,
                                                                            write: false,
                                                                            });
                                                                        }
                                                                break;
                                                            case 'timestamp':
                                                                const timestampVal = obj[i];
                                                                const timestampFormatted = formatTime(timestampVal);
                                                                if (existsState(statePath)) setState(statePath, timestampVal, true);
                                                                else createState(statePath, timestampVal, {
                                                                    name: 'System timestamp',
                                                                    type: 'number',
                                                                    desc: 'unix timestamp in Seconds since Jan 01 1970 (UTC)',
                                                                    role: 'value',
                                                                    read: true,
                                                                    write: false,
                                                                });
                                                                if (existsState(id + '.timeUpdateTimestamp')) setState(id + '.timeUpdateTimestamp', timestampFormatted, true);
                                                                else createState(id + '.timeUpdateTimestamp', timestampFormatted, {
                                                                    name: 'TimeUpdate (timestamp)',
                                                                    type: 'string',
                                                                    desc: 'unix timestamp in readable Format (timestamp)',
                                                                    read: true,
                                                                    write: false,
                                                                });
                                                                break;
                                                            case 'ts':
                                                                const tsVal = obj[i];
                                                                const tsFormatted = formatTime(tsVal);
                                                                if (existsState(statePath)) setState(statePath, tsVal, true);
                                                                else createState(statePath, tsVal, {
                                                                    name: 'Unix timestamp (ts)',
                                                                    type: 'number',
                                                                    desc: 'unix timestamp in Seconds since Jan 01 1970 (UTC)',
                                                                    role: 'value',
                                                                    read: true,
                                                                    write: false,
                                                                });
                                                                if (existsState(id + '.timeUpdateTs')) setState(id + '.timeUpdateTs', tsFormatted, true);
                                                                else createState(id + '.timeUpdateTs', tsFormatted, {
                                                                    name: 'TimeUpdate (ts)',
                                                                    type: 'string',
                                                                    desc: 'unix timestamp in readable Format (ts)',
                                                                    read: true,
                                                                    write: false,
                                                                });
                                                                break;			
                                                            default:
                                                                if (existsState(statePath)) {
                                                                    setState(statePath, val, true);
                                                                } else {
                                                                    createState(statePath, val, {
                                                                        name: i,
                                                                        type: typeof val,
                                                                        role: 'value',
                                                                        read: true,
                                                                        write: false,
                                                                    });
                                                                }
                                                                break;
                                                        }
                                                    }
                                                }
                                            } catch (e) {
                                                log(`Error in iter: ${e}`, 'info');
                                            }
                                        }
                                        
                                        

                                        Euch allen viel Sonne und weiterhin viel Freude

                                        Ich schreibe meistens sehr direkt – bitte nicht falsch verstehen, es ist nie böse gemeint. Das ist einfach mein Stil und niemals abwertend gemeint.

                                        1 Antwort Letzte Antwort
                                        0

                                        Hey! Du scheinst an dieser Unterhaltung interessiert zu sein, hast aber noch kein Konto.

                                        Hast du es satt, bei jedem Besuch durch die gleichen Beiträge zu scrollen? Wenn du dich für ein Konto anmeldest, kommst du immer genau dorthin zurück, wo du zuvor warst, und kannst dich über neue Antworten benachrichtigen lassen (entweder per E-Mail oder Push-Benachrichtigung). Du kannst auch Lesezeichen speichern und Beiträge positiv bewerten, um anderen Community-Mitgliedern deine Wertschätzung zu zeigen.

                                        Mit deinem Input könnte dieser Beitrag noch besser werden 💗

                                        Registrieren Anmelden
                                        Antworten
                                        • In einem neuen Thema antworten
                                        Anmelden zum Antworten
                                        • Älteste zuerst
                                        • Neuste zuerst
                                        • Meiste Stimmen


                                        Support us

                                        ioBroker
                                        Community Adapters
                                        Donate

                                        238

                                        Online

                                        32.7k

                                        Benutzer

                                        82.6k

                                        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