Weiter zum Inhalt
  • Home
  • Aktuell
  • 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. Einsteigerfragen
  4. Einbindung von Geräten
  5. Hilfe: Adapter Fronius-Wattpilot kann nur mehr lesen

NEWS

  • Monatsrückblick Juli / August 2026 ist online!
    BluefoxB
    Bluefox
    9
    1
    439

  • Der neue Monatsrückblick für Mai und Juni 2026 ist online!
    BluefoxB
    Bluefox
    8
    1
    1.3k

  • wichtiges UPDATE für controller 7.2.2 im stable
    HomoranH
    Homoran
    10
    1
    3.8k

Hilfe: Adapter Fronius-Wattpilot kann nur mehr lesen

Geplant Angeheftet Gesperrt Verschoben Einbindung von Geräten
22 Beiträge 5 Kommentatoren 214 Aufrufe 3 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.
  • fuzzy1955F Online
    fuzzy1955F Online
    fuzzy1955
    schrieb am zuletzt editiert von
    #1

    Hallo Experten,

    ich habe einen Fronius Wattpilot GO 11 kW (Österreich), der mit dem IOB-Adapter "fronius-wattpilot" bisher gut gelesen und gesteuert werden konnte. Seit der Firmware 42.5 kann der Adapter nur mehr lesen, aber nicht mehr steuern (set_state = 'frc;0' etc.). Ein Firmware-Upgrade auf 41.x ist offenbar nicht mehr möglich. Mit der App kann ich jedoch wie bisher steuern. Fronius hat (laut Copilot-KI) offenbar die lokale Steuerung bewusst entfernt. Was mache ich da jetzt bloß?

    Vorweg danke für eure Unterstützung! Gruß, Fuzzy

    990af93b-e5fd-46be-a7aa-c7016394661f-image.jpeg

    Smart-Home-Automation unter IOB auf RASPI5, 16GB RAM, 50GB SSD, MariaSQL, VIS-2.
    Anfang 2025 war ich Newbie in Sachen RaspBerry, Linux und IOB.
    Jetzt läuft alles konstant gut und ich gebe gern meine Erfahrungen und mein Wissen an die Forums-User/Innen weiter.
    Großes Danke an alle tatkräftigen Helfer im Forum!

    HomoranH ste_gleiS 2 Antworten Letzte Antwort
    0
    • fuzzy1955F fuzzy1955

      Hallo Experten,

      ich habe einen Fronius Wattpilot GO 11 kW (Österreich), der mit dem IOB-Adapter "fronius-wattpilot" bisher gut gelesen und gesteuert werden konnte. Seit der Firmware 42.5 kann der Adapter nur mehr lesen, aber nicht mehr steuern (set_state = 'frc;0' etc.). Ein Firmware-Upgrade auf 41.x ist offenbar nicht mehr möglich. Mit der App kann ich jedoch wie bisher steuern. Fronius hat (laut Copilot-KI) offenbar die lokale Steuerung bewusst entfernt. Was mache ich da jetzt bloß?

      Vorweg danke für eure Unterstützung! Gruß, Fuzzy

      990af93b-e5fd-46be-a7aa-c7016394661f-image.jpeg

      HomoranH Nicht stören
      HomoranH Nicht stören
      Homoran
      schrieb am zuletzt editiert von
      #2

      @fuzzy1955 meines Wissens ist der Wattpilot ein umgelabelter go-e charger.
      (Mit anderer Firmware)

      Ob und wie man die go-e Firmware draufbekommen kann weiss ich nicht. Ist ja nur ein ESP drin.

      Dort ist alles noch offen.
      https://github.com/goecharger

      Allerdings wird der Wattpilot wahrscheinlich noch zusätzliche Fronius spezifische Funktionen haben, die mit einem Flash dann verloren gingen.

      kein Support per PN! - Fragen im Forum stellen - Benutzt das Voting rechts unten im Beitrag wenn er euch geholfen hat.
      Das Forum freut sich über eine Spende. Benutzt dazu den Spendenbutton oben rechts. Danke!
      der Installationsfixer: curl -fsL https://iobroker.net/fix.sh | bash -

      fuzzy1955F 1 Antwort Letzte Antwort
      0
      • HomoranH Homoran

        @fuzzy1955 meines Wissens ist der Wattpilot ein umgelabelter go-e charger.
        (Mit anderer Firmware)

        Ob und wie man die go-e Firmware draufbekommen kann weiss ich nicht. Ist ja nur ein ESP drin.

        Dort ist alles noch offen.
        https://github.com/goecharger

        Allerdings wird der Wattpilot wahrscheinlich noch zusätzliche Fronius spezifische Funktionen haben, die mit einem Flash dann verloren gingen.

        fuzzy1955F Online
        fuzzy1955F Online
        fuzzy1955
        schrieb am zuletzt editiert von
        #3

        @Homoran sagte:

        Allerdings wird der Wattpilot wahrscheinlich noch zusätzliche Fronius spezifische Funktionen haben, die mit einem Flash dann verloren gingen

        Danke, Homoran!

        Smart-Home-Automation unter IOB auf RASPI5, 16GB RAM, 50GB SSD, MariaSQL, VIS-2.
        Anfang 2025 war ich Newbie in Sachen RaspBerry, Linux und IOB.
        Jetzt läuft alles konstant gut und ich gebe gern meine Erfahrungen und mein Wissen an die Forums-User/Innen weiter.
        Großes Danke an alle tatkräftigen Helfer im Forum!

        1 Antwort Letzte Antwort
        0
        • fuzzy1955F fuzzy1955

          Hallo Experten,

          ich habe einen Fronius Wattpilot GO 11 kW (Österreich), der mit dem IOB-Adapter "fronius-wattpilot" bisher gut gelesen und gesteuert werden konnte. Seit der Firmware 42.5 kann der Adapter nur mehr lesen, aber nicht mehr steuern (set_state = 'frc;0' etc.). Ein Firmware-Upgrade auf 41.x ist offenbar nicht mehr möglich. Mit der App kann ich jedoch wie bisher steuern. Fronius hat (laut Copilot-KI) offenbar die lokale Steuerung bewusst entfernt. Was mache ich da jetzt bloß?

          Vorweg danke für eure Unterstützung! Gruß, Fuzzy

          990af93b-e5fd-46be-a7aa-c7016394661f-image.jpeg

          ste_gleiS Offline
          ste_gleiS Offline
          ste_glei
          schrieb am zuletzt editiert von
          #4

          @fuzzy1955

          Ich habe zwar den Flex Pro mit Firmware 43.4 und dort funktiniert alles.

          Zu deiner KI Frage, hier sagt Gemini genau das Gegenteil.
          69d38665-1104-4f6f-bdb6-f95af091d608-image.jpeg

          Als schnelle Lösung könntest du den OCCP Adapter (OCCP im Wattpilot aktivieren) verwenden.

          fuzzy1955F 1 Antwort Letzte Antwort
          0
          • ste_gleiS ste_glei

            @fuzzy1955

            Ich habe zwar den Flex Pro mit Firmware 43.4 und dort funktiniert alles.

            Zu deiner KI Frage, hier sagt Gemini genau das Gegenteil.
            69d38665-1104-4f6f-bdb6-f95af091d608-image.jpeg

            Als schnelle Lösung könntest du den OCCP Adapter (OCCP im Wattpilot aktivieren) verwenden.

            fuzzy1955F Online
            fuzzy1955F Online
            fuzzy1955
            schrieb am zuletzt editiert von fuzzy1955
            #5

            @ste_glei sagte:

            Als schnelle Lösung könntest du den OCCP Adapter (OCCP im Wattpilot aktivieren) verwenden

            Danke! OCCP funktioniert aber nur mit Internet und das habe ich aus Sicherheitsgründen gesperrt. möchte ich nicht.

            Smart-Home-Automation unter IOB auf RASPI5, 16GB RAM, 50GB SSD, MariaSQL, VIS-2.
            Anfang 2025 war ich Newbie in Sachen RaspBerry, Linux und IOB.
            Jetzt läuft alles konstant gut und ich gebe gern meine Erfahrungen und mein Wissen an die Forums-User/Innen weiter.
            Großes Danke an alle tatkräftigen Helfer im Forum!

            Meister MopperM 1 Antwort Letzte Antwort
            0
            • fuzzy1955F Online
              fuzzy1955F Online
              fuzzy1955
              schrieb am zuletzt editiert von
              #6

              Hallo Experten,

              hat jemand einen Tipp für mein Problem, dass der Fronius-Wattpilot-Adapter seit der Firmware 42.5 nur mehr lesen, aber nicht mehr steuern kann? Ich habe die Wallbox inzwischen komplett resettet, das Passwort geändert, den IOB-Adapter v4.6.0 installiert, aber das hilft alles nichts. Ich kann doch die Wallbox nicht wegschmeißen (verkaufen)? Gottseidank habe ich noch die Keba P30, die kann ich mit IOB super steuern.

              06016a07-2122-4387-8542-d3ad6a1a44ff-image.jpeg

              Smart-Home-Automation unter IOB auf RASPI5, 16GB RAM, 50GB SSD, MariaSQL, VIS-2.
              Anfang 2025 war ich Newbie in Sachen RaspBerry, Linux und IOB.
              Jetzt läuft alles konstant gut und ich gebe gern meine Erfahrungen und mein Wissen an die Forums-User/Innen weiter.
              Großes Danke an alle tatkräftigen Helfer im Forum!

              1 Antwort Letzte Antwort
              0
              • mickemupM Offline
                mickemupM Offline
                mickemup
                schrieb am zuletzt editiert von mickemup
                #7

                Also ich habe den Wattpilot Home 11kW mit SW 42.5 und kann meine DPs noch ganz normal beschreiben.
                Gerade getestet mit den DPs: set_mode und amp...

                Nachtrag: Adapter 4.8.0 installiert
                die 4.6.0 ist doch uralt..(vom 2023)

                Nachtrag2: Hier noch der Changelog für die 42.5 aus der App. Da steht nichts von "read-only" oder ähnlichem...

                417954b4-06ba-49dd-8b8d-ec57518f33d3-Screenshot_20260827_162135_Solarwattpilot.jpg

                fuzzy1955F 1 Antwort Letzte Antwort
                0
                • mickemupM mickemup

                  Also ich habe den Wattpilot Home 11kW mit SW 42.5 und kann meine DPs noch ganz normal beschreiben.
                  Gerade getestet mit den DPs: set_mode und amp...

                  Nachtrag: Adapter 4.8.0 installiert
                  die 4.6.0 ist doch uralt..(vom 2023)

                  Nachtrag2: Hier noch der Changelog für die 42.5 aus der App. Da steht nichts von "read-only" oder ähnlichem...

                  417954b4-06ba-49dd-8b8d-ec57518f33d3-Screenshot_20260827_162135_Solarwattpilot.jpg

                  fuzzy1955F Online
                  fuzzy1955F Online
                  fuzzy1955
                  schrieb am zuletzt editiert von
                  #8

                  @mickemup sagte:

                  die 4.6.0 ist doch uralt

                  Danke, mickemup! Das war nur testweise. Normal habe ich den Adapter v4.8.0 installiert. Komisch, warum das Beschreiben bei meinem Adapter nicht mehr funktioniert. Ich stehe mit meiner Weisheit an :-(

                  Smart-Home-Automation unter IOB auf RASPI5, 16GB RAM, 50GB SSD, MariaSQL, VIS-2.
                  Anfang 2025 war ich Newbie in Sachen RaspBerry, Linux und IOB.
                  Jetzt läuft alles konstant gut und ich gebe gern meine Erfahrungen und mein Wissen an die Forums-User/Innen weiter.
                  Großes Danke an alle tatkräftigen Helfer im Forum!

                  1 Antwort Letzte Antwort
                  0
                  • mickemupM Offline
                    mickemupM Offline
                    mickemup
                    schrieb am zuletzt editiert von
                    #9

                    Hmm, und wenn du den Adapter auf Debug stellst und einen Wert schreibst, kommt dann irgendeine (Fehler)-Meldung?

                    fuzzy1955F 1 Antwort Letzte Antwort
                    0
                    • mickemupM mickemup

                      Hmm, und wenn du den Adapter auf Debug stellst und einen Wert schreibst, kommt dann irgendeine (Fehler)-Meldung?

                      fuzzy1955F Online
                      fuzzy1955F Online
                      fuzzy1955
                      schrieb am zuletzt editiert von
                      #10

                      @mickemup sagte:

                      Adapter auf Debug stellst und einen Wert schreibst

                      Protokoll beim Laden = ein:


                      fronius-wattpilot.0
                      2026-08-28 13:58:22.450 debug Received message: {"type":"deltaStatus","status":{"ehs":265212,"efh":117360,"efh32":117360,"efh8":86536,"utc":"2026-08-28T11:58:20.653","loc":"2026-08-28T13:58:20.654 +02:00","rbt":105136696,"nrg":[225.9900055,226.6100006,226.6100006,2.170000076,0,0,0,0,0,0,0,0,0,0,0,0],"fhz":55.01200104}}

                      fronius-wattpilot.0
                      2026-08-28 13:58:21.454 debug Received message: {"type":"deltaStatus","status":{"utc":"2026-08-28T11:58:19.655","loc":"2026-08-28T13:58:19.656 +02:00","rbt":105135700,"nrg":[226.9199982,227.2299957,226.3000031,2.170000076,0,0,0,0,0,0,0,0,0,0,0,0],"fhz":55.01300049}}

                      fronius-wattpilot.0
                      2026-08-28 13:58:20.454 debug Received message: {"type":"deltaStatus","status":{"ehs":265148,"efh":117100,"efh32":117100,"efh8":86276,"utc":"2026-08-28T11:58:18.655","loc":"2026-08-28T13:58:18.656 +02:00","rbt":105134698,"nrg":[226.3000031,226.3000031,226.9199982,2.170000076,0,0,0,0,0,0,0,0,0,0,0,0],"fhz":55.01200104}}

                      fronius-wattpilot.0
                      2026-08-28 13:58:19.453 debug Received message: {"type":"deltaStatus","status":{"ehs":265212,"efh":117364,"efh32":117364,"efh8":86540,"emhb":73716,"utc":"2026-08-28T11:58:17.655","loc":"2026-08-28T13:58:17.656 +02:00","rbt":105133700,"nrg":[226.3000031,226.9199982,226.3000031,2.170000076,0,0,0,0,0,0,0,0,0,0,0,0],"fhz":55.01100159}}

                      fronius-wattpilot.0
                      2026-08-28 13:58:18.508 debug Command successful: {"amp":12}

                      fronius-wattpilot.0
                      2026-08-28 13:58:18.508 debug Received message: {"type":"response","requestId":"7","success":true,"status":{"amp":12}}

                      fronius-wattpilot.0
                      2026-08-28 13:58:18.493 debug Received message: {"type":"deltaStatus","status":{"ehs":265196,"efh":113248,"efh32":113248,"efh8":82424,"emhb":69620,"utc":"2026-08-28T11:58:16.695","loc":"2026-08-28T13:58:16.696 +02:00","rbt":105132738,"nrg":[225.9900055,226.6100006,226.6100006,2.170000076,0,0,0,0,0,0,0,0,0,0,0,0]}}

                      fronius-wattpilot.0
                      2026-08-28 13:58:18.379 debug Sending secure command: {"type":"securedMsg","data":"{"type":"setValue","requestId":7,"key":"amp","value":12}","requestId":"7sm","hmac":"442557278d87f3377abb9db26e3a35019b4ae236a2b063cc387003e1d0d8fd6b"}

                      fronius-wattpilot.0
                      2026-08-28 13:58:18.378 debug State change command received for fronius-wattpilot.0.set_power: {"val":12,"ack":false,"ts":1787918298374,"q":0,"c":"script.js.common._Tests.Fronius_Wallbox","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1787917944709}

                      javascript.1
                      2026-08-28 13:58:18.374 info script.js.common._Tests.Fronius_Wallbox: Status = true, Modus = 3, LeistungIst=0 kW, StromIst=0.0 A

                      Protokoll beim Laden = aus:

                      fronius-wattpilot.0
                      2026-08-28 14:02:07.451 debug Received message: {"type":"deltaStatus","status":{"utc":"2026-08-28T12:02:05.651","loc":"2026-08-28T14:02:05.652 +02:00","rbt":105361696,"nrg":[225.9900055,226.3000031,226.9199982,2.170000076,0,0,0,0,0,0,0,0,0,0,0,0]}}

                      fronius-wattpilot.0
                      2026-08-28 14:02:06.463 debug Received message: {"type":"deltaStatus","status":{"efh":117096,"efh32":117096,"efh8":86272,"utc":"2026-08-28T12:02:04.661","loc":"2026-08-28T14:02:04.663 +02:00","rbt":105360705,"nrg":[226.6100006,227.2299957,225.9900055,2.170000076,0,0,0,0,0,0,0,0,0,0,0,0],"fhz":55.01200104}}

                      fronius-wattpilot.0
                      2026-08-28 14:02:05.464 debug Received message: {"type":"deltaStatus","status":{"ehs":265140,"efh":117084,"efh32":117084,"efh8":86260,"utc":"2026-08-28T12:02:03.665","loc":"2026-08-28T14:02:03.666 +02:00","rbt":105359708,"nrg":[226.6100006,226.3000031,226.9199982,2.170000076,0,0,0,0,0,0,0,0,0,0,0,0],"fhz":55.01100159}}

                      fronius-wattpilot.0
                      2026-08-28 14:02:04.465 debug Received message: {"type":"deltaStatus","status":{"utc":"2026-08-28T12:02:02.665","loc":"2026-08-28T14:02:02.667 +02:00","rbt":105358709,"tma":[37.5],"nrg":[225.9900055,226.9199982,226.3000031,2.170000076,0,0,0,0,0,0,0,0,0,0,0,0],"fhz":55.01200104}}

                      fronius-wattpilot.0
                      2026-08-28 14:02:03.466 debug Received message: {"type":"deltaStatus","status":{"ehs":265196,"efh":117328,"efh32":117328,"efh8":86504,"utc":"2026-08-28T12:02:01.667","loc":"2026-08-28T14:02:01.668 +02:00","rbt":105357710,"tma":[38],"nrg":[226.9199982,226.9199982,226.6100006,2.170000076,0,0,0,0,0,0,0,0,0,0,0,0],"fhz":55.01300049}}

                      fronius-wattpilot.0
                      2026-08-28 14:02:03.321 debug Command successful: {"amp":12}

                      fronius-wattpilot.0
                      2026-08-28 14:02:03.321 debug Received message: {"type":"response","requestId":"1","success":true,"status":{"amp":12}}

                      fronius-wattpilot.0
                      2026-08-28 14:02:03.272 debug Sending secure command: {"type":"securedMsg","data":"{"type":"setValue","requestId":1,"key":"amp","value":12}","requestId":"1sm","hmac":"e83cec0268b1bea004d1c760203329e4123347b1233beef8c5aeb3168f0b0d1d"}

                      fronius-wattpilot.0
                      2026-08-28 14:02:03.272 debug State change command received for fronius-wattpilot.0.set_power: {"val":12,"ack":false,"ts":1787918523267,"q":0,"c":"script.js.common._Tests.Fronius_Wallbox","from":"system.adapter.javascript.1","user":"system.user.admin","lc":1787917944709}

                      javascript.1
                      2026-08-28 14:02:03.267 info script.js.common._Tests.Fronius_Wallbox: Status = Wait, Modus = 0, LeistungIst=0 kW, StromIst=0.0 A

                      Siehst du etwas auffälliges?

                      Smart-Home-Automation unter IOB auf RASPI5, 16GB RAM, 50GB SSD, MariaSQL, VIS-2.
                      Anfang 2025 war ich Newbie in Sachen RaspBerry, Linux und IOB.
                      Jetzt läuft alles konstant gut und ich gebe gern meine Erfahrungen und mein Wissen an die Forums-User/Innen weiter.
                      Großes Danke an alle tatkräftigen Helfer im Forum!

                      1 Antwort Letzte Antwort
                      0
                      • mickemupM Offline
                        mickemupM Offline
                        mickemup
                        schrieb am zuletzt editiert von
                        #11

                        Bin da nicht der Experte: aber das sieht nicht soo verkehrt aus:

                        fronius-wattpilot.0
                        2026-08-28 14:02:03.321 debug Command successful: {"amp":12}
                        
                        fronius-wattpilot.0
                        2026-08-28 14:02:03.321 debug Received message: {"type":"response","requestId":"1","success":true,"status":{"amp":12}}
                        

                        Und in der APP ändert sich nichts an der Ampere Zahl?
                        Oder umgekehrt: Wenn du die Ampere-Zahl in der APP änderst, ändert sich der DP im Adapter?

                        fuzzy1955F 1 Antwort Letzte Antwort
                        0
                        • mickemupM mickemup

                          Bin da nicht der Experte: aber das sieht nicht soo verkehrt aus:

                          fronius-wattpilot.0
                          2026-08-28 14:02:03.321 debug Command successful: {"amp":12}
                          
                          fronius-wattpilot.0
                          2026-08-28 14:02:03.321 debug Received message: {"type":"response","requestId":"1","success":true,"status":{"amp":12}}
                          

                          Und in der APP ändert sich nichts an der Ampere Zahl?
                          Oder umgekehrt: Wenn du die Ampere-Zahl in der APP änderst, ändert sich der DP im Adapter?

                          fuzzy1955F Online
                          fuzzy1955F Online
                          fuzzy1955
                          schrieb am zuletzt editiert von
                          #12

                          @mickemup sagte:

                          Und in der APP ändert sich nichts an der Ampere Zahl

                          Nein, der Datenpunkt wird gesetzt, aber in der App bleibt alles gleich.

                          Oder umgekehrt: Wenn du die Ampere-Zahl in der APP änderst, ändert sich der DP im Adapter

                          Ja, der Datenpunkt im IOB ändert sich, wenn ich die Ampere-Zahl in der APP ändere (ist ja nur lesend).

                          Smart-Home-Automation unter IOB auf RASPI5, 16GB RAM, 50GB SSD, MariaSQL, VIS-2.
                          Anfang 2025 war ich Newbie in Sachen RaspBerry, Linux und IOB.
                          Jetzt läuft alles konstant gut und ich gebe gern meine Erfahrungen und mein Wissen an die Forums-User/Innen weiter.
                          Großes Danke an alle tatkräftigen Helfer im Forum!

                          1 Antwort Letzte Antwort
                          0
                          • fuzzy1955F fuzzy1955

                            @ste_glei sagte:

                            Als schnelle Lösung könntest du den OCCP Adapter (OCCP im Wattpilot aktivieren) verwenden

                            Danke! OCCP funktioniert aber nur mit Internet und das habe ich aus Sicherheitsgründen gesperrt. möchte ich nicht.

                            Meister MopperM Online
                            Meister MopperM Online
                            Meister Mopper
                            Most Active
                            schrieb am zuletzt editiert von Meister Mopper
                            #13

                            @fuzzy1955 sagte:

                            @ste_glei sagte:

                            Als schnelle Lösung könntest du den OCCP Adapter (OCCP im Wattpilot aktivieren) verwenden

                            Danke! OCCP funktioniert aber nur mit Internet und das habe ich aus Sicherheitsgründen gesperrt. möchte ich nicht.

                            Meine Wallbox läuft mit dem OCPP-Adapter. Internet benötige ich dafür nicht.

                            Proxmox und HA ...
                            Ich schreibe den Code nicht mehr selbst – ich schimpfe mit der KI, bis es funktioniert.

                            fuzzy1955F 1 Antwort Letzte Antwort
                            0
                            • Meister MopperM Meister Mopper

                              @fuzzy1955 sagte:

                              @ste_glei sagte:

                              Als schnelle Lösung könntest du den OCCP Adapter (OCCP im Wattpilot aktivieren) verwenden

                              Danke! OCCP funktioniert aber nur mit Internet und das habe ich aus Sicherheitsgründen gesperrt. möchte ich nicht.

                              Meine Wallbox läuft mit dem OCPP-Adapter. Internet benötige ich dafür nicht.

                              fuzzy1955F Online
                              fuzzy1955F Online
                              fuzzy1955
                              schrieb am zuletzt editiert von
                              #14

                              @Meister-Mopper sagte:

                              Internet benötige ich dafür nicht

                              Aah, danke! Welchen OCPP-Provider (Host, Pfad) verwendest du da?

                              Smart-Home-Automation unter IOB auf RASPI5, 16GB RAM, 50GB SSD, MariaSQL, VIS-2.
                              Anfang 2025 war ich Newbie in Sachen RaspBerry, Linux und IOB.
                              Jetzt läuft alles konstant gut und ich gebe gern meine Erfahrungen und mein Wissen an die Forums-User/Innen weiter.
                              Großes Danke an alle tatkräftigen Helfer im Forum!

                              Meister MopperM 1 Antwort Letzte Antwort
                              0
                              • fuzzy1955F fuzzy1955

                                @Meister-Mopper sagte:

                                Internet benötige ich dafür nicht

                                Aah, danke! Welchen OCPP-Provider (Host, Pfad) verwendest du da?

                                Meister MopperM Online
                                Meister MopperM Online
                                Meister Mopper
                                Most Active
                                schrieb am zuletzt editiert von
                                #15

                                @fuzzy1955 sagte:

                                @Meister-Mopper sagte:

                                Internet benötige ich dafür nicht

                                Aah, danke! Welchen OCPP-Provider (Host, Pfad) verwendest du da?

                                Da benötige ich keinen Provider. Die Wallbox spricht via ocpp mit ioBroker über websocket (IP und Port).
                                Deine Wallbox beherrscht nach meiner Recherche das Protokoll ebenfalls.

                                Proxmox und HA ...
                                Ich schreibe den Code nicht mehr selbst – ich schimpfe mit der KI, bis es funktioniert.

                                fuzzy1955F 1 Antwort Letzte Antwort
                                0
                                • Meister MopperM Meister Mopper

                                  @fuzzy1955 sagte:

                                  @Meister-Mopper sagte:

                                  Internet benötige ich dafür nicht

                                  Aah, danke! Welchen OCPP-Provider (Host, Pfad) verwendest du da?

                                  Da benötige ich keinen Provider. Die Wallbox spricht via ocpp mit ioBroker über websocket (IP und Port).
                                  Deine Wallbox beherrscht nach meiner Recherche das Protokoll ebenfalls.

                                  fuzzy1955F Online
                                  fuzzy1955F Online
                                  fuzzy1955
                                  schrieb am zuletzt editiert von
                                  #16

                                  @Meister-Mopper sagte:

                                  Deine Wallbox beherrscht nach meiner Recherche das Protokoll ebenfalls

                                  Ja, das kann sie. Wie hast du diese Seite konfiguriert?

                                  dc4c7876-d4a3-4919-ba05-251b1306add5-image.jpeg

                                  Und hättest du ein JavaScript- Beispiel?

                                  Smart-Home-Automation unter IOB auf RASPI5, 16GB RAM, 50GB SSD, MariaSQL, VIS-2.
                                  Anfang 2025 war ich Newbie in Sachen RaspBerry, Linux und IOB.
                                  Jetzt läuft alles konstant gut und ich gebe gern meine Erfahrungen und mein Wissen an die Forums-User/Innen weiter.
                                  Großes Danke an alle tatkräftigen Helfer im Forum!

                                  Meister MopperM 1 Antwort Letzte Antwort
                                  0
                                  • fuzzy1955F fuzzy1955

                                    @Meister-Mopper sagte:

                                    Deine Wallbox beherrscht nach meiner Recherche das Protokoll ebenfalls

                                    Ja, das kann sie. Wie hast du diese Seite konfiguriert?

                                    dc4c7876-d4a3-4919-ba05-251b1306add5-image.jpeg

                                    Und hättest du ein JavaScript- Beispiel?

                                    Meister MopperM Online
                                    Meister MopperM Online
                                    Meister Mopper
                                    Most Active
                                    schrieb am zuletzt editiert von Meister Mopper
                                    #17

                                    @fuzzy1955

                                    Ich habe eine EVBox.

                                    Die verbindet sich mit ws://IPdesioBroker:Port ohne Benutzername und Passwort mit dem ioBroker. Der Port wird im Adapter festgelegt.

                                    6d2284a5-f73a-4318-a118-ec1fcc316075-image.jpeg

                                    Mein Ladeskript hat mehr als 700 Zeilen, aber bitte:

                                    /* eslint-env es2022 */
                                    /**
                                    * Name:    EV3 Charge-Master
                                    * Purpose: Start/stop management for Kia EV3 wallbox charging (fixed 6A / 3.96 kW).
                                    * Modes:   1. Manual: User triggered via VIS
                                    *          2. PV Auto: Automated based on PV surplus and home battery SoC
                                    * Features: Home battery protection, debounced status handling, forced transaction stops.
                                    */
                                    
                                    // --- 1. SETUP: DIGITALE ZENTRALE (21 DATENPUNKTE) ---
                                    
                                    const VIN = `bluelink.0.${getState("0_userdata.0.Energie.Kia_e_niro.vin")?.val}`;
                                    const PATH_USER = "0_userdata.0.Energie.Kia_e_niro";
                                    
                                    const IDS = {
                                     // Wallbox (Hardware via OCPP)
                                     wbStat: "ocpp.0.http://192_168_178_80:9220/EVB-P21312507.1.status", // [1] Status (Charging, Preparing...)
                                     wbTrans: "ocpp.0.http://192_168_178_80:9220/EVB-P21312507.1.transactionActive", // [2] Steuert den Stromfluss (Transaktion aktiv)
                                     wbAvail: "ocpp.0.http://192_168_178_80:9220/EVB-P21312507.1.availability", // [3] Reset / Verfügbarkeit
                                     wbConn: "ocpp.0.http://192_168_178_80:9220/EVB-P21312507.connected", // Verbindung zum ioBroker
                                     unifiReconnect: "unifi-network.0.clients.users.60:09:c3:2f:46:49.reconnect", // [22] Neu verbinden über UniFi
                                    
                                     // Fahrzeugdaten (Cloud)
                                     soc: `${VIN}.vehicleStatusRaw.Green.BatteryManagement.BatteryRemain.Ratio`, // [4] Ladestand %
                                     bat12v: `${VIN}.vehicleStatusRaw.Electronics.Battery.Level`, // [5] 12V-Batterieschutz
                                     conn: `${VIN}.vehicleStatusRaw.Green.ChargingInformation.ConnectorFastening.State`, // [6] Steckerstatus
                                     remTime: `${VIN}.vehicleStatusRaw.Green.ChargingInformation.Charging.RemainTime`, // [7] Restzeit in Min (vom Fahrzeug gemeldet)
                                     targetSocSrv: `${VIN}.control.charge_limit_slow`, // [23] Ladeziel (AC) vom Fahrzeug (Steuerungspunkt)
                                     refreshCar: `${VIN}.control.force_refresh_from_car`, // [8] Fahrzeug aufwecken (Live-Daten)
                                     refreshSrv: `${VIN}.control.force_refresh_from_server`, // [8b] Server-Status abrufen
                                    
                                     // Energie-Zentrale (Hardware-Werte)
                                     pvPower: "solax.0.data.acpower", // [9] Aktuelle PV-Leistung in Watt
                                     pvAverage: "0_userdata.0.Energie.PV.Durchschnitt", // [10] Geglätteter Wert (EMA)
                                     netPower: "0_userdata.0.Energie.PV.Netzbezug", // [11] Hauszähler (+Bezug/-Einspeisung)
                                     hausCons: "0_userdata.0.Energie.PV.Hausverbrauch", // [12] Hausverbrauch
                                     batSocPV: "modbus.0.inputRegisters.100.843_Battery_State_of_Charge_(System)", // [13] Heimspeicher %
                                     minSocSet: "modbus.0.holdingRegisters.100.2901_ESS_Minimum_SoC_(unless_grid_fails)",
                                     minSocRead: "modbus.0.inputRegisters.100.2901_ESS_Minimum_SoC_(unless_grid_fails)",
                                    
                                     // Steuerung & Statistiken (VIS)
                                     u_auto: `${PATH_USER}.autoladen`, // [14] Schalter: PV-Automatik an/aus (Boolean)
                                     u_limit: `${PATH_USER}.Ladeprozent`, // [15] Ziel-SoC Schieberegler
                                     u_smooth: `${PATH_USER}.Glaettung_Zeit`, // [16] Trägheits-Schieberegler für EMA
                                     u_power: `${PATH_USER}.Ladeleistung`, // [17] Anzeige Ladeleistung (fix 3960W)
                                     u_timeDay: `${PATH_USER}.Ladezeit`, // [18] Lademinuten heute
                                     u_rest: `${PATH_USER}.Restladezeit`, // [19] HH:MM Anzeige
                                     aliasKm: "alias.0.umrechnen.kia_ladekm", // [20] Gewonnene Reichweite
                                     aliasDur: "alias.0.umrechnen.kia_ladezeit", // [21] Zeit-Objekt
                                     u_startChargeRequest: `${PATH_USER}.Start_Charge_Request`, // [NEU] Anforderung zum Starten des Ladevorgangs
                                     u_startTs: `${PATH_USER}.LastStartTimestamp`, // [PERSISTENCE] Merker für Startzeit
                                     u_origSoc: `${PATH_USER}.LastOriginalMinSoc`, // [PERSISTENCE] Merker für Batterie-Schutz
                                    };
                                    
                                    // --- PARAMETER ---
                                    const PV_START_LIMIT = 4600; // Startgrenze (Sonne muss > 4.6kW + Puffer liefern)
                                    const PV_STOP_LIMIT = 4000; // Stoppgrenze (Ladevorgang pausieren, wenn Überschuss sinkt)
                                    const FIXED_CHARGE_W = 3960; // Fixe Leistung bei 6A (220V * 3 Phasen * 6A)
                                    const CAR_CAPACITY_KWH = 81.4;
                                    const RANGE_SUMMER = 550;
                                    const RANGE_WINTER = 450;
                                    
                                    // --- TIMING KONSTANTEN ---
                                    const DEBOUNCE_STOP_MS = 45000; // 45 Sek. Wartezeit vor endgültigem Stopp
                                    const RECONNECT_WB_MS = 180000; // 3 Min. Wartezeit vor WLAN-Neuverbindung
                                    const START_REFRESH_DELAY_MS = 75000; // 75 Sek. nach Ladestart: Fahrzeug aufwecken für Restzeit & SoC
                                    const STOP_REFRESH_DELAY_MS = 30000; // 30 Sek. nach bestätigtem Ladestopp: Finalen SoC & Status abrufen
                                    const START_VERIFY_TIMEOUT_MS = 35000; // 35 Sek. maximale Wartezeit auf "Charging"-Status nach Startbefehl
                                    const START_AVAILABILITY_TOGGLE_DELAY_MS = 2000; // 2 Sek. Pause bei Verfügbarkeitswechsel
                                    const START_HANDSHAKE_DELAY_MS = 4000; // 4 Sek. Puffer für OCPP-Handshake nach Re-Aktivierung
                                    // [NEU] Verzögerung vor dem erneuten Versuch des Stopp-Befehls nach dem ersten Versuch.
                                    const FORCE_STOP_RETRY_DELAY_MS = 5000;
                                    // [NEU] Verzögerung während des Verfügbarkeitswechsels, um der Wallbox Zeit zur Verarbeitung zu geben.
                                    const FORCE_STOP_AVAILABILITY_TOGGLE_DELAY_MS = 2000;
                                    
                                    let startZeitLaden = null; // Merker für Statistik
                                    let originalMinSoc = null; // Merker für Min-SoC bei manuellem Laden
                                    let stopTimer = null; // Timer zur Entprellung von kurzen Lade-Unterbrechungen
                                    let startRefreshTimer = null; // Timer für Statusabfrage nach Ladestart
                                    let stopRefreshTimer = null; // Timer für Statusabfrage nach Ladeende
                                    let reconnectTimer = null; // Timer für Wallbox-Recovery
                                    let wasOfflineReported = false; // Status für Anti-Spam Meldungen
                                    let hasWarnedOcppOffline = false; // Flag to prevent repeated warning logs per script run
                                    // [NEU] Sperrvariable zur Vermeidung von Race Conditions während der Startsequenz.
                                    let isStartingSequenceActive = false;
                                    // [NEU] Sperrvariable zur Vermeidung mehrerer gleichzeitiger Ausführungen von erzwungenen Stopps.
                                    let isForceStopping = false;
                                    
                                    // --- 2. INITIALISIERUNG ---
                                    
                                    async function initLadeSystem() {
                                     // Erstellt nur noch die für diese Version nötigen Punkte
                                     if (!existsState(IDS.u_auto))
                                       await createStateAsync(IDS.u_auto, true, {
                                         type: "boolean",
                                         name: "PV Automatic",
                                       });
                                     if (!existsState(IDS.u_smooth))
                                       await createStateAsync(IDS.u_smooth, 10, {
                                         type: "number",
                                         name: "EMA Smoothing",
                                       });
                                     if (!existsState(IDS.u_limit))
                                       await createStateAsync(IDS.u_limit, 80, {
                                         type: "number",
                                         name: "Charge Target",
                                       });
                                     // NEU: Datenpunkt für die Ladestart-Anforderung
                                     if (!existsState(IDS.u_startChargeRequest))
                                       await createStateAsync(IDS.u_startChargeRequest, false, {
                                         type: "boolean",
                                         name: "Start Charging (Request)",
                                         role: "button",
                                       });
                                     if (!existsState(IDS.u_startTs))
                                       await createStateAsync(IDS.u_startTs, 0, { type: "number", name: "Start Timestamp" });
                                     if (!existsState(IDS.u_origSoc))
                                       await createStateAsync(IDS.u_origSoc, 0, { type: "number", name: "Original MinSoc Backup" });
                                    
                                     // Laufende Prozesse nach Skript-Neustart wiederherstellen
                                     if (getState(IDS.wbTrans)?.val === true) {
                                       startZeitLaden = getState(IDS.u_startTs)?.val || Date.now();
                                       const savedSoc = getState(IDS.u_origSoc)?.val;
                                       originalMinSoc = savedSoc !== null && savedSoc !== 0 ? savedSoc : null;
                                       if (getState(IDS.wbStat)?.val === "Charging") {
                                         setState(IDS.u_power, FIXED_CHARGE_W, true);
                                       }
                                     }
                                    }
                                    initLadeSystem();
                                    
                                    // --- 2.1 HELPER: ASYNCHRONE PAUSE & MESSWERTE ---
                                    
                                    /**
                                    * Asynchroner Timer zur Ablaufverzögerung in async-Funktionen.
                                    * @param {number} ms Millisekunden
                                    */
                                    const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
                                    
                                    /**
                                    * Wartet bis der Wallbox-Status auf "Charging" wechselt oder der Timeout abläuft.
                                    * @param {number} timeoutMs Maximale Wartezeit in Millisekunden
                                    * @returns {Promise<boolean>} True falls "Charging" erreicht wurde, sonst False
                                    */
                                    async function waitForChargingState(timeoutMs) {
                                     const startTime = Date.now();
                                     while (Date.now() - startTime < timeoutMs) {
                                       if (getState(IDS.wbStat)?.val === "Charging") {
                                         return true;
                                       }
                                       await wait(1000);
                                     }
                                     return getState(IDS.wbStat)?.val === "Charging";
                                    }
                                    
                                    /**
                                    * Sammelt alle relevanten Leistungs- und SoC-Werte aus den Datenpunkten.
                                    * Stellt sicher, dass die Werte Zahlen sind.
                                    */
                                    function getPowerMetrics() {
                                     return {
                                       pvPower: Math.max(0, Number(getState(IDS.pvPower)?.val) || 0),
                                       pvAverage: Number(getState(IDS.pvAverage)?.val) || 0,
                                       batSoc: Number(getState(IDS.batSocPV)?.val) || 0,
                                       evSoc: Number(getState(IDS.soc)?.val) || 0,
                                     };
                                    }
                                    
                                    // --- 3. KOMMUNIKATION ---
                                    
                                    /**
                                    * Führt die intelligente Startsequenz der Wallbox inklusive Verifikations-Watchdog
                                    * und automatischem Retry-Mechanismus aus.
                                    * @param {string} reason Grund für den Start (z. B. "PV-Automatik", "VIS-Manual")
                                    */
                                    async function triggerStartSequence(reason = "PV-Surplus") {
                                     if (isStartingSequenceActive) {
                                       console.log(`[EV3 Master] Start sequence already active, skipping (${reason}).`);
                                       return;
                                     }
                                    
                                     const wbStatus = getState(IDS.wbStat)?.val;
                                     if (wbStatus === "Charging") {
                                       console.log(`[EV3 Master] Wallbox is already charging. Skipping start sequence.`);
                                       return;
                                     }
                                    
                                     const readyToStart = ["Preparing", "Finishing", "SuspendedEVSE", "SuspendedEV"].includes(
                                       wbStatus,
                                     );
                                    
                                     if (!readyToStart) {
                                       if (wbStatus === "Available") {
                                         // console.warn(`[EV3 Master] Start (${reason}) aborted: No vehicle detected.`);
                                         return;
                                       }
                                     }
                                    
                                     isStartingSequenceActive = true;
                                     console.log(
                                       `[EV3 Master] Starting wallbox sequence for: ${reason} (Current Status: ${wbStatus})`,
                                     );
                                    
                                     try {
                                       // --- VERSUCH 1 ---
                                       console.log("[EV3 Master] Start attempt 1: Toggling availability and setting wbTrans = true.");
                                       setState(IDS.wbAvail, false);
                                       await wait(START_AVAILABILITY_TOGGLE_DELAY_MS);
                                       setState(IDS.wbAvail, true);
                                       await wait(START_HANDSHAKE_DELAY_MS); // Erhöhter Puffer für den OCPP-Handshake
                                       setState(IDS.wbTrans, true);
                                    
                                       let started = await waitForChargingState(START_VERIFY_TIMEOUT_MS);
                                    
                                       // --- VERSUCH 2 (AUTOMATISCHER RETRY BEI TIMEOUT / FEHLSCHLAG) ---
                                       if (!started) {
                                         const currentStatus = getState(IDS.wbStat)?.val;
                                         console.warn(
                                           `[EV3 Master] Start attempt 1 timed out. Wallbox status is '${currentStatus}'. Retrying reset sequence...`,
                                         );
                                    
                                         setState(IDS.wbTrans, false);
                                         await wait(FORCE_STOP_RETRY_DELAY_MS);
                                         setState(IDS.wbAvail, false);
                                         await wait(START_AVAILABILITY_TOGGLE_DELAY_MS);
                                         setState(IDS.wbAvail, true);
                                         await wait(START_HANDSHAKE_DELAY_MS);
                                         setState(IDS.wbTrans, true);
                                    
                                         started = await waitForChargingState(START_VERIFY_TIMEOUT_MS);
                                       }
                                    
                                       // --- ERGEBNIS-AUSWERTUNG ---
                                       if (started) {
                                         console.log(`[EV3 Master] Wallbox start verified successfully (${reason}).`);
                                         ev3Notify(`🔋 EV3-Ladung gestartet via ${reason} mit 6A`);
                                       } else {
                                         const finalStatus = getState(IDS.wbStat)?.val;
                                         console.error(
                                           `[EV3 Master] Start failed after retry. Wallbox did not reach 'Charging' state (Status: ${finalStatus}). Reverting wbTrans.`,
                                         );
                                         setState(IDS.wbTrans, false);
                                         ev3Notify(
                                           `⚠️ EV3 Ladestart fehlgeschlagen: Wallbox reagiert nicht (Status: ${finalStatus})`,
                                           4,
                                         );
                                       }
                                     } catch (e) {
                                       console.error(`[EV3 Master] Error during start sequence: ${e.message}`);
                                       setState(IDS.wbTrans, false);
                                       ev3Notify(`❌ Fehler bei Ladestart-Sequenz: ${e.message}`, 5);
                                     } finally {
                                       isStartingSequenceActive = false;
                                     }
                                    }
                                    
                                    /**
                                    * [NEU] forceStopCharging()
                                    * Versucht, den Ladevorgang zu beenden, selbst wenn der Status "hängt".
                                    * Nutzt den Verfügbarkeitswechsel (Availability-Toggle) als letzten Ausweg.
                                    * Diese Funktion wird aufgerufen, wenn `transactionActive` auf `false` gesetzt wurde,
                                    * die Wallbox aber immer noch den Status `Charging` meldet.
                                    */
                                    async function forceStopCharging() {
                                     // Gleichzeitige Ausführung verhindern
                                     if (isForceStopping) {
                                       console.log("[EV3 Master] Force stop already active, skipping.");
                                       return;
                                     }
                                     isForceStopping = true;
                                     console.warn("[EV3 Master] Initiating forced charging stop sequence.");
                                    
                                     try {
                                       // Versuch 1: Sende transactionActive: false erneut
                                       // Standardweg, um eine Session zu beenden.
                                       console.log("[EV3 Master] Force stop attempt 1: Setting wbTrans to false.");
                                       setState(IDS.wbTrans, false);
                                       // Warten, damit die Wallbox Zeit zur Verarbeitung hat.
                                       await wait(FORCE_STOP_RETRY_DELAY_MS);
                                    
                                       if (getState(IDS.wbStat)?.val === "Charging") {
                                         console.warn(
                                           "[EV3 Master] Force stop attempt 1 failed. Proceeding with Availability Toggle.",
                                         );
                                         // Versuch 2: Verfügbarkeitswechsel (Availability-Toggle)
                                         console.log("[EV3 Master] Force stop attempt 2: Toggling wbAvail (false -> true).");
                                         setState(IDS.wbAvail, false);
                                         // Nach dem Deaktivieren warten
                                         await wait(FORCE_STOP_AVAILABILITY_TOGGLE_DELAY_MS);
                                         setState(IDS.wbAvail, true);
                                         // Vor dem erneuten Stopp-Versuch warten
                                         await wait(FORCE_STOP_AVAILABILITY_TOGGLE_DELAY_MS);
                                         setState(IDS.wbTrans, false);
                                         ev3Notify("⚠️ Wallbox Ladestop erzwungen (Availability Reset)", 3);
                                         console.log("[EV3 Master] Force stop attempt 2 completed.");
                                       } else {
                                         console.log("[EV3 Master] Forced charging stop successful on first attempt.");
                                       }
                                     } catch (e) {
                                       console.error(`[EV3 Master] Error during forced charging stop: ${e.message}`);
                                       ev3Notify(`❌ Fehler beim erzwungenen Ladestopp: ${e.message}`, 5);
                                     } finally {
                                       isForceStopping = false;
                                       if (stopTimer) {
                                         clearTimeout(stopTimer);
                                         stopTimer = null;
                                         console.log("[EV3 Master] Cleared stopTimer after forced stop.");
                                       }
                                       if (startRefreshTimer) {
                                         clearTimeout(startRefreshTimer);
                                         startRefreshTimer = null;
                                       }
                                       setState(IDS.u_power, 0, true);
                                       if (startZeitLaden) {
                                         const stats = updateChargeStatistics(Date.now() - startZeitLaden);
                                         setState(IDS.u_timeDay, stats.totalMinToday, true);
                                         ev3Notify(
                                           `❌ Ladung beendet (forced). Heute geladen: ${stats.formattedTime} (+approx. ${stats.kmToday} km)`,
                                           1,
                                         );
                                         startZeitLaden = null;
                                         setState(IDS.u_startTs, 0, true);
                                       }
                                       if (originalMinSoc !== null) {
                                         setState(IDS.minSocSet, Math.max(0, originalMinSoc));
                                         ev3Notify(`🔌 Hausbatterie MinSoc auf ${originalMinSoc}% nach erzwungenem Stop eingestellt`);
                                         originalMinSoc = null;
                                         setState(IDS.u_origSoc, 0, true);
                                       }
                                       if (stopRefreshTimer) clearTimeout(stopRefreshTimer);
                                       stopRefreshTimer = setTimeout(() => {
                                         console.log(
                                           "[EV3 Master] Triggering post-stop vehicle refresh for final SoC and statistics.",
                                         );
                                         if (existsState(IDS.refreshCar)) {
                                           setState(IDS.refreshCar, true);
                                         }
                                         stopRefreshTimer = null;
                                       }, STOP_REFRESH_DELAY_MS);
                                     }
                                    }
                                    
                                    function ev3Notify(text, prio = 1, spoken = null) {
                                     sendTo("telegram", "send", { text: text }); // An Telegram senden
                                    
                                     // Token dynamisch auflösen für erhöhte Robustheit
                                     const gotifyToken = getState("0_userdata.0.gotifytoken.iobroker")?.val;
                                     if (gotifyToken) {
                                       const url = `https://mygotify.meistermopper.de/message?token=${gotifyToken}`;
                                       const payload = { title: "EV3 Master", message: text, priority: prio };
                                       const options = {
                                         headers: { "Content-Type": "application/json" },
                                         timeout: 10000,
                                       };
                                    
                                       httpPost(url, payload, options, (err) => {
                                         if (err) console.error(`[EV3 Master] Gotify Error: ${err}`);
                                       });
                                     } else {
                                       console.warn("[EV3 Master] Gotify Token ist nicht definiert oder leer.");
                                     }
                                    
                                     // Sprachausgabe tagsüber
                                     if (compareTime("08:00", "20:00", "between")) {
                                       // Wenn ein spezieller Sprechtext übergeben wurde (spoken), nutzen wir diesen.
                                       // Andernfalls nehmen wir den Standardtext.
                                       let voice = spoken || text;
                                       voice = voice
                                         .replace(/%/g, " Prozent")
                                         .replace(/SOC/gi, "Ladestand")
                                         .replace(/🔋|🔌|⚠️|🚗|❌/g, "");
                                       // sendTo("sayit", "say", { text: voice });
                                     }
                                    }
                                    
                                    // --- 4. INTELLIGENTE PV-GLÄTTUNG (EMA) ---
                                    
                                    /**
                                    * Berechnet die durchschnittliche PV-Leistung zur Stabilisierung der Regelung.
                                    * Reagiert schnell auf Einbrüche, langsam auf Erhöhungen.
                                    */
                                    schedule("* * * * *", async () => {
                                     const { pvPower: current, pvAverage: oldAvg, batSoc } = getPowerMetrics();
                                     const inertia = Number(getState(IDS.u_smooth)?.val) || 10;
                                    
                                     let alpha;
                                     if (current < oldAvg) {
                                       // ABFALL: Wenn die Hausbatterie voll ist (>85%), langsamer reagieren (0,2 statt 0,5).
                                       // Dies verhindert unnötige Ladestopps bei kurzen Wolken.
                                       alpha = batSoc > 85 ? 0.2 : 0.5;
                                     } else {
                                       // ANSTIEG: Wenn die Hausbatterie noch leer ist (<50%), länger auf stabile Sonne warten.
                                       // Wenn die Batterie voll ist, die Sonne schneller nutzen.
                                       const dynamicInertia = batSoc > 75 ? Math.max(2, inertia / 2) : inertia;
                                       alpha = 1 / dynamicInertia;
                                     }
                                    
                                     const newAvg = alpha * current + (1 - alpha) * oldAvg;
                                     setState(IDS.pvAverage, Math.round(newAvg), true);
                                    });
                                    
                                    // --- 5. AUTOMATISIERUNGS-LOGIK (PV-ÜBERSCHUSS) ---
                                    
                                    /**
                                    * Überwacht den PV-Durchschnitt und schaltet das Laden automatisch,
                                    * vorausgesetzt der Automatik-Schalter in VIS ist aktiv.
                                    */
                                    function checkPvAutomation() {
                                     const isAuto = !!getState(IDS.u_auto)?.val; // Automatik-Schalter
                                     const { pvAverage: mittel, batSoc, evSoc } = getPowerMetrics(); // Aktuelle Leistungswerte
                                    
                                     // Abbrechen, wenn Wallbox offline ist
                                     const isConnected = !!getState(IDS.wbConn)?.val;
                                     if (!isConnected && mittel > PV_START_LIMIT) {
                                       if (!hasWarnedOcppOffline) {
                                         console.warn("[EV3 Master] Start not possible: Wallbox connection missing (OCPP Offline)");
                                         hasWarnedOcppOffline = true;
                                       }
                                     }
                                     if (!isAuto || !isConnected) return;
                                    
                                     const isTransActive = !!getState(IDS.wbTrans)?.val;
                                     const _wbStatus = getState(IDS.wbStat)?.val;
                                     const limitCar = getState(IDS.targetSocSrv)?.val || 100;
                                    
                                     // Diagnose-Log für ausreichenden Überschuss, falls nicht geladen wird
                                     //if (!isTransActive && (mittel > (PV_START_LIMIT - 500))) {
                                     //    console.log(`[EV3 Master] Status: ${wbStatus} | PV-Avg: ${mittel}W | Bat-SoC: ${batSoc}% | EV-SoC: ${evSoc}% / Ziel: ${limitCar}%`);
                                     //}
                                    
                                     // START: Genug Sonne (>4.6kW) und Hausspeicher gut gefüllt (>75%)
                                     if (
                                       !isTransActive &&
                                       !isStartingSequenceActive &&
                                       mittel > PV_START_LIMIT &&
                                       batSoc > 75 &&
                                       evSoc < limitCar
                                     ) {
                                       triggerStartSequence("PV-Automatik");
                                     }
                                    
                                     // STOP: Überschuss sinkt unter Ladeleistung (Pause)
                                     // oder Ladeziel erreicht
                                     // oder Wallbox-Verbindung verloren (oben durch !isConnected abgefangen, hier als Redundanz)
                                     else if (isTransActive && (mittel < PV_STOP_LIMIT || evSoc >= limitCar)) {
                                       // Detailliertes Logging des Stopp-Grunds
                                       let reason = "";
                                       if (mittel < PV_STOP_LIMIT) reason = `Insufficient PV power (${mittel}W < ${PV_STOP_LIMIT}W)`;
                                       else if (evSoc >= limitCar)
                                         reason = `Vehicle charging target reached (${evSoc}% >= ${limitCar}%)`;
                                    
                                       if (reason) {
                                         console.log(`[EV3 Master] Automatically stopped: ${reason}`);
                                       }
                                    
                                       setState(IDS.wbTrans, false);
                                       //ev3Notify("EV3 charging ended");
                                     }
                                    }
                                    
                                    // Trigger bei neuen PV-Werten sowie bei Wiederherstellung der Verbindung
                                    on({ id: IDS.pvAverage, change: "ne" }, checkPvAutomation);
                                    on({ id: IDS.soc, change: "ne" }, checkPvAutomation);
                                    on({ id: IDS.wbConn, val: true, change: "ne" }, checkPvAutomation);
                                    
                                    // [NEU] Listener für den Datenpunkt wbTrans.
                                    // Dieser Listener ist entscheidend für das Erkennen und Beheben von "hängenden" Ladestatuse.
                                    // Wenn `wbTrans` auf `false` wechselt (Stopp-Befehl gesendet), prüfen wir nach einer Verzögerung
                                    // von 10 Sekunden, ob `wbStat` immer noch `Charging` ist, und rufen in diesem Fall `forceStopCharging()` auf.
                                    on({ id: IDS.wbTrans, change: "ne" }, (obj) => {
                                     if (obj.state.val === false) {
                                       // 10 Sekunden Verzögerung, um der Wallbox Zeit zur Verarbeitung zu geben
                                       setTimeout(async () => {
                                         if (getState(IDS.wbStat)?.val === "Charging") {
                                           console.warn(
                                             "[EV3 Master] Wallbox hängt im Status 'Charging' trotz beendeter Transaktion. Erzwinge Stopp.",
                                           );
                                           await forceStopCharging();
                                         }
                                       }, 10000);
                                     }
                                    });
                                    // --- 6. ÜBERWACHUNG & STATISTIKEN ---
                                    
                                    /**
                                    * Erfasst die Ladedauer und stellt die Leistungsanzeige ein.
                                    * Erfasst die Ladedauer, stellt die Leistungsanzeige ein und schützt die Hausbatterie
                                    * vor Entladung beim manuellen Laden.
                                    * Berechnet die Statistiken für den aktuellen oder abgeschlossenen Ladevorgang.
                                    */
                                    function updateChargeStatistics(sessionDurationMs) {
                                     const dauerMin = Math.max(1, Math.round(sessionDurationMs / 60000)); // Mindestens 1 Minute zählen
                                     const currentTotalMin = getState(IDS.u_timeDay)?.val || 0;
                                     const totalMinToday = currentTotalMin + dauerMin;
                                    
                                     // Energie und Reichweite
                                     const energyKWh = (totalMinToday / 60) * (FIXED_CHARGE_W / 1000);
                                     const month = new Date().getMonth();
                                     const rangeMax = month >= 3 && month <= 10 ? RANGE_SUMMER : RANGE_WINTER;
                                     const kmToday = Math.round((energyKWh / CAR_CAPACITY_KWH) * rangeMax);
                                    
                                     const h = Math.floor(totalMinToday / 60);
                                     const m = totalMinToday % 60;
                                     const formattedTime = h > 0 ? `${h}:${m < 10 ? `0${m}` : m} Std` : `${m} Min`;
                                    
                                     return {
                                       totalMinToday,
                                       formattedTime,
                                       kmToday,
                                       spokenTime: h > 0 ? `${h} Stunden, ${m} Minuten` : `${m} Minuten`,
                                     };
                                    }
                                    
                                    // Haupt-Überwacher für den Wallbox-Status (z. B. Charging, Preparing, SuspendedEV...)
                                    on({ id: IDS.wbStat, change: "ne" }, (obj) => {
                                     const status = String(obj.state.val);
                                     const isAuto = !!getState(IDS.u_auto)?.val;
                                    
                                     // FALL 1: Das Fahrzeug lädt aktiv
                                     if (status === "Charging") {
                                       // Falls ein Stop-Timer läuft (kurze Ladeunterbrechung durch z.B. Wolken):
                                       // Timer abbrechen, da die Ladung direkt fortgesetzt wurde (Hiccup-Schutz).
                                       if (stopTimer) {
                                         clearTimeout(stopTimer);
                                         stopTimer = null;
                                         console.log("[EV3 Master] Short interruption ended, resuming charge");
                                         return;
                                       }
                                    
                                       // Startzeitpunkt merken, sofern noch nicht gesetzt (für die tägliche Statistik)
                                       if (!startZeitLaden) {
                                         startZeitLaden = Date.now();
                                         setState(IDS.u_startTs, startZeitLaden, true);
                                    
                                         // 75 Sek. nach Ladestart Fahrzeug aufwecken, um verbleibende Ladedauer & SoC präzise abzurufen
                                         if (startRefreshTimer) clearTimeout(startRefreshTimer);
                                         startRefreshTimer = setTimeout(() => {
                                           if (getState(IDS.wbStat)?.val === "Charging") {
                                             console.log(
                                               "[EV3 Master] Triggering post-start vehicle refresh to update SoC and remaining time.",
                                             );
                                             if (existsState(IDS.refreshCar)) {
                                               setState(IDS.refreshCar, true);
                                             }
                                           }
                                           startRefreshTimer = null;
                                         }, START_REFRESH_DELAY_MS);
                                       }
                                    
                                       // Da die Box starr mit 6A lädt (3 Phasen * 230V * 6A = ~3,96 kW), setzen wir den festen Watt-Wert zur Anzeige
                                       setState(IDS.u_power, FIXED_CHARGE_W, true);
                                    
                                       // BATTERIESCHUTZ bei manuellem Laden (Automatik AUS):
                                       // Verhindert, dass der Hausspeicher entleert wird, indem der Min-SoC der Hausbatterie temporär
                                       // auf den aktuellen SoC-Wert gesetzt wird.
                                       if (!isAuto && originalMinSoc === null) {
                                         originalMinSoc = getState(IDS.minSocRead)?.val;
                                         setState(IDS.u_origSoc, originalMinSoc, true);
                                         const currentBatSoc = getState(IDS.batSocPV)?.val;
                                         // MinSoc sicherheitshalber nicht unter 0 setzen
                                         setState(IDS.minSocSet, Math.max(0, currentBatSoc));
                                         const msg = `Manuelles Laden gestartet. MinSoc auf ${currentBatSoc}% (vorher: ${originalMinSoc}%)`;
                                         console.log(`[EV3 Master] ${msg}`);
                                         ev3Notify(`🔋 ${msg}`);
                                       }
                                     }
                                    
                                     // FALL 2: Das Fahrzeug stoppt (durch Kabel ziehen, Auto-Ladeziel erreicht, Pause durch PV-Regelung etc.)
                                     else if (
                                       startZeitLaden &&
                                       (status === "Finishing" ||
                                         status === "Available" ||
                                         status === "SuspendedEV" ||
                                         status === "SuspendedEVSE")
                                     ) {
                                       if (startRefreshTimer) {
                                         clearTimeout(startRefreshTimer);
                                         startRefreshTimer = null;
                                       }
                                       // Um bei kurzen Unterbrechungen nicht sofort abzubrechen, warten wir 45 Sekunden (Entprellzeit).
                                       // Wechselt der Status in dieser Zeit zurück auf "Charging", läuft die Ladung oben nahtlos weiter.
                                       if (stopTimer) clearTimeout(stopTimer);
                                    
                                       stopTimer = setTimeout(() => {
                                         // 1. Batterieschutz aufheben: Min-SoC des Hausspeichers wieder auf den ursprünglichen Wert zurückstellen
                                         if (!isAuto && originalMinSoc !== null) {
                                           setState(IDS.minSocSet, Math.max(0, originalMinSoc));
                                           const msg = `EV3 Manuelles Laden beendet. Hausbatterie MinSoc wieder auf ${originalMinSoc}% gestellt`;
                                           console.log(`[EV3 Master] ${msg}`);
                                           ev3Notify(`🔌 ${msg}`);
                                           originalMinSoc = null;
                                           setState(IDS.u_origSoc, 0, true);
                                         }
                                    
                                         // 2. Ladestatistik berechnen (Dauer in Min, geladene kWh und hinzugewonnene Kilometer je nach Jahreszeit)
                                         const stats = updateChargeStatistics(Date.now() - startZeitLaden);
                                         setState(IDS.u_timeDay, stats.totalMinToday, true);
                                    
                                         // 3. Prüfen, ob das Auto das Ladeziel erreicht hat:
                                         // Vergleicht den aktuellen SoC des Kia mit dem eingestellten Ladeziel der Wallbox/des Fahrzeugs
                                         const evSoc = Number(getState(IDS.soc)?.val) || 0;
                                         const targetSoc = Number(getState(IDS.targetSocSrv)?.val) || 100;
                                    
                                         let msgText = `❌ EV3 Ladung beendet. Heute geladen: ${stats.formattedTime} (+approx. ${stats.kmToday} km)`;
                                         let spokenText = `Ladung beendet. Heute geladen: ${stats.spokenTime}. Reichweite approx. ${stats.kmToday} Kilometer.`;
                                    
                                         // Wenn das Ladeziel erreicht wurde, ergänzen wir die Benachrichtigungen
                                         if (evSoc >= targetSoc) {
                                           msgText += ` - Das Ladeziel von ${targetSoc}% wurde erreicht`;
                                           spokenText += ` Das Ladeziel von ${targetSoc} Prozent wurde erreicht`;
                                         }
                                    
                                         // Benachrichtigung senden (Telegram, Gotify, Alexa/SayIt)
                                         ev3Notify(msgText, 1, spokenText);
                                    
                                         // 4. Ladevariablen zurücksetzen & Ladevorgang sauber abschließen
                                         startZeitLaden = null;
                                         setState(IDS.u_startTs, 0, true);
                                         setState(IDS.u_power, 0, true);
                                    
                                         // WICHTIG: Setzt transactionActive auf false, damit die Wallbox die Transaktion beendet
                                         // und die VIS-Visualisierung nicht mehr "lädt..." anzeigt (Logikfehler-Behebung).
                                         setState(IDS.wbTrans, false);
                                    
                                         stopTimer = null;
                                    
                                         // Finalen Status nach Ladeende vom Fahrzeug abrufen
                                         if (stopRefreshTimer) clearTimeout(stopRefreshTimer);
                                         stopRefreshTimer = setTimeout(() => {
                                           console.log(
                                             "[EV3 Master] Triggering post-stop vehicle refresh for final SoC and statistics.",
                                           );
                                           if (existsState(IDS.refreshCar)) {
                                             setState(IDS.refreshCar, true);
                                           }
                                           stopRefreshTimer = null;
                                         }, STOP_REFRESH_DELAY_MS);
                                       }, DEBOUNCE_STOP_MS);
                                     }
                                    });
                                    
                                    // Dynamischer Batterieschutz bei manuellem Laden:
                                    // Erhöht sich der SoC des Heimspeichers während des manuellen Ladens (z. B. durch PV-Ertrag),
                                    // wird der Min-SoC des Wechselrichters entsprechend nach oben angepasst.
                                    on({ id: IDS.batSocPV, change: "ne" }, (obj) => {
                                     const isAuto = !!getState(IDS.u_auto)?.val;
                                     const isCharging = getState(IDS.wbStat)?.val === "Charging";
                                    
                                     if (!isAuto && isCharging) {
                                       const newSoc = Number(obj.state.val) || 0;
                                       const oldSoc = Number(obj.oldState?.val) || 0;
                                    
                                       if (newSoc > oldSoc) {
                                         if (originalMinSoc === null) {
                                           originalMinSoc = getState(IDS.minSocRead)?.val;
                                           setState(IDS.u_origSoc, originalMinSoc, true);
                                         }
                                         setState(IDS.minSocSet, Math.max(0, newSoc));
                                         console.log(
                                           `[EV3 Master] Manual charging: Home battery SoC increased from ${oldSoc}% to ${newSoc}%. Updated MinSoC to ${newSoc}%.`,
                                         );
                                       }
                                     }
                                    });
                                    
                                    // --- 7. ZUSÄTZLICHE FUNKTIONEN ---
                                    
                                    /**
                                    * Verbindungs-Watchdog: Überwacht die Erreichbarkeit der Wallbox.
                                    * Meldet Statusänderungen (Anti-Spam) und löst nach 3 Min. Offline-Zeit einen Reconnect über den UniFi-AP aus.
                                    */
                                    on({ id: IDS.wbConn, change: "ne" }, (obj) => {
                                     const isConnected = !!obj.state.val;
                                    
                                     if (!isConnected) {
                                       // Nur beim ersten Mal warnen
                                       if (!wasOfflineReported) {
                                         //console.warn("[EV3 Master] Wallbox-Verbindung verloren. Reconnect-Timer (3 Min) gestartet.");
                                         wasOfflineReported = true;
                                       }
                                       // Reconnect-Timer starten (falls nicht schon einer läuft)
                                       if (!reconnectTimer) {
                                         reconnectTimer = setTimeout(() => {
                                           //console.log("[EV3 Master] Führe WLAN-Neuverbindung über UniFi AP aus...");
                                           setState(IDS.unifiReconnect, true);
                                           reconnectTimer = null;
                                         }, RECONNECT_WB_MS);
                                       }
                                     } else {
                                       // Wieder online: Status zurücksetzen und Timer stoppen
                                       if (wasOfflineReported) console.log("[EV3 Master] Wallbox connection restored.");
                                       wasOfflineReported = false;
                                       if (reconnectTimer) {
                                         clearTimeout(reconnectTimer);
                                         reconnectTimer = null;
                                       }
                                     }
                                    });
                                    
                                    /**
                                    * Formatiert die verbleibende Ladezeit für die Anzeige in VIS.
                                    */
                                    on({ id: IDS.remTime, change: "any" }, (obj) => {
                                     const m = obj.state.val;
                                     let t = "0:00";
                                     if (m > 0) {
                                       const hh = Math.floor(m / 60);
                                       const mm = m % 60;
                                       t = `${hh}:${mm < 10 ? `0${mm}` : mm}`;
                                     }
                                     setState(IDS.u_rest, t, true);
                                    });
                                    
                                    // Synchronisiert den VIS-Anzeige-Datenpunkt mit dem echten Ladeziel des Autos
                                    on({ id: IDS.targetSocSrv, change: "ne" }, (obj) => {
                                     console.log(`[EV3 Master] Charge target sync: Setting VIS slider to ${obj.state.val}%.`);
                                     setState(IDS.u_limit, obj.state.val, true);
                                    });
                                    
                                    // Handler für manuelle Start-Anforderungen
                                    on({ id: IDS.u_startChargeRequest, val: true, change: "any" }, () => {
                                     console.log("[EV3 Master] Manual start request received via VIS.");
                                     triggerStartSequence("VIS-Manual");
                                     setTimeout(() => {
                                       setState(IDS.u_startChargeRequest, false, true);
                                     }, 1000);
                                    });
                                    
                                    // Täglicher Reset der Ladestatistik um 02:05 Uhr
                                    schedule("5 2 * * *", () => {
                                     setState(IDS.u_timeDay, 0, true);
                                    });
                                    
                                    // Schutz der Kia 12V-Starterbatterie
                                    on({ id: IDS.bat12v, change: "ne" }, (obj) => {
                                     if (obj.state.val <= 50) ev3Notify(`⚠️ Kia 12V battery critical!`, 5);
                                    });
                                    
                                    

                                    Proxmox und HA ...
                                    Ich schreibe den Code nicht mehr selbst – ich schimpfe mit der KI, bis es funktioniert.

                                    fuzzy1955F 2 Antworten Letzte Antwort
                                    0
                                    • Meister MopperM Meister Mopper

                                      @fuzzy1955

                                      Ich habe eine EVBox.

                                      Die verbindet sich mit ws://IPdesioBroker:Port ohne Benutzername und Passwort mit dem ioBroker. Der Port wird im Adapter festgelegt.

                                      6d2284a5-f73a-4318-a118-ec1fcc316075-image.jpeg

                                      Mein Ladeskript hat mehr als 700 Zeilen, aber bitte:

                                      /* eslint-env es2022 */
                                      /**
                                      * Name:    EV3 Charge-Master
                                      * Purpose: Start/stop management for Kia EV3 wallbox charging (fixed 6A / 3.96 kW).
                                      * Modes:   1. Manual: User triggered via VIS
                                      *          2. PV Auto: Automated based on PV surplus and home battery SoC
                                      * Features: Home battery protection, debounced status handling, forced transaction stops.
                                      */
                                      
                                      // --- 1. SETUP: DIGITALE ZENTRALE (21 DATENPUNKTE) ---
                                      
                                      const VIN = `bluelink.0.${getState("0_userdata.0.Energie.Kia_e_niro.vin")?.val}`;
                                      const PATH_USER = "0_userdata.0.Energie.Kia_e_niro";
                                      
                                      const IDS = {
                                       // Wallbox (Hardware via OCPP)
                                       wbStat: "ocpp.0.http://192_168_178_80:9220/EVB-P21312507.1.status", // [1] Status (Charging, Preparing...)
                                       wbTrans: "ocpp.0.http://192_168_178_80:9220/EVB-P21312507.1.transactionActive", // [2] Steuert den Stromfluss (Transaktion aktiv)
                                       wbAvail: "ocpp.0.http://192_168_178_80:9220/EVB-P21312507.1.availability", // [3] Reset / Verfügbarkeit
                                       wbConn: "ocpp.0.http://192_168_178_80:9220/EVB-P21312507.connected", // Verbindung zum ioBroker
                                       unifiReconnect: "unifi-network.0.clients.users.60:09:c3:2f:46:49.reconnect", // [22] Neu verbinden über UniFi
                                      
                                       // Fahrzeugdaten (Cloud)
                                       soc: `${VIN}.vehicleStatusRaw.Green.BatteryManagement.BatteryRemain.Ratio`, // [4] Ladestand %
                                       bat12v: `${VIN}.vehicleStatusRaw.Electronics.Battery.Level`, // [5] 12V-Batterieschutz
                                       conn: `${VIN}.vehicleStatusRaw.Green.ChargingInformation.ConnectorFastening.State`, // [6] Steckerstatus
                                       remTime: `${VIN}.vehicleStatusRaw.Green.ChargingInformation.Charging.RemainTime`, // [7] Restzeit in Min (vom Fahrzeug gemeldet)
                                       targetSocSrv: `${VIN}.control.charge_limit_slow`, // [23] Ladeziel (AC) vom Fahrzeug (Steuerungspunkt)
                                       refreshCar: `${VIN}.control.force_refresh_from_car`, // [8] Fahrzeug aufwecken (Live-Daten)
                                       refreshSrv: `${VIN}.control.force_refresh_from_server`, // [8b] Server-Status abrufen
                                      
                                       // Energie-Zentrale (Hardware-Werte)
                                       pvPower: "solax.0.data.acpower", // [9] Aktuelle PV-Leistung in Watt
                                       pvAverage: "0_userdata.0.Energie.PV.Durchschnitt", // [10] Geglätteter Wert (EMA)
                                       netPower: "0_userdata.0.Energie.PV.Netzbezug", // [11] Hauszähler (+Bezug/-Einspeisung)
                                       hausCons: "0_userdata.0.Energie.PV.Hausverbrauch", // [12] Hausverbrauch
                                       batSocPV: "modbus.0.inputRegisters.100.843_Battery_State_of_Charge_(System)", // [13] Heimspeicher %
                                       minSocSet: "modbus.0.holdingRegisters.100.2901_ESS_Minimum_SoC_(unless_grid_fails)",
                                       minSocRead: "modbus.0.inputRegisters.100.2901_ESS_Minimum_SoC_(unless_grid_fails)",
                                      
                                       // Steuerung & Statistiken (VIS)
                                       u_auto: `${PATH_USER}.autoladen`, // [14] Schalter: PV-Automatik an/aus (Boolean)
                                       u_limit: `${PATH_USER}.Ladeprozent`, // [15] Ziel-SoC Schieberegler
                                       u_smooth: `${PATH_USER}.Glaettung_Zeit`, // [16] Trägheits-Schieberegler für EMA
                                       u_power: `${PATH_USER}.Ladeleistung`, // [17] Anzeige Ladeleistung (fix 3960W)
                                       u_timeDay: `${PATH_USER}.Ladezeit`, // [18] Lademinuten heute
                                       u_rest: `${PATH_USER}.Restladezeit`, // [19] HH:MM Anzeige
                                       aliasKm: "alias.0.umrechnen.kia_ladekm", // [20] Gewonnene Reichweite
                                       aliasDur: "alias.0.umrechnen.kia_ladezeit", // [21] Zeit-Objekt
                                       u_startChargeRequest: `${PATH_USER}.Start_Charge_Request`, // [NEU] Anforderung zum Starten des Ladevorgangs
                                       u_startTs: `${PATH_USER}.LastStartTimestamp`, // [PERSISTENCE] Merker für Startzeit
                                       u_origSoc: `${PATH_USER}.LastOriginalMinSoc`, // [PERSISTENCE] Merker für Batterie-Schutz
                                      };
                                      
                                      // --- PARAMETER ---
                                      const PV_START_LIMIT = 4600; // Startgrenze (Sonne muss > 4.6kW + Puffer liefern)
                                      const PV_STOP_LIMIT = 4000; // Stoppgrenze (Ladevorgang pausieren, wenn Überschuss sinkt)
                                      const FIXED_CHARGE_W = 3960; // Fixe Leistung bei 6A (220V * 3 Phasen * 6A)
                                      const CAR_CAPACITY_KWH = 81.4;
                                      const RANGE_SUMMER = 550;
                                      const RANGE_WINTER = 450;
                                      
                                      // --- TIMING KONSTANTEN ---
                                      const DEBOUNCE_STOP_MS = 45000; // 45 Sek. Wartezeit vor endgültigem Stopp
                                      const RECONNECT_WB_MS = 180000; // 3 Min. Wartezeit vor WLAN-Neuverbindung
                                      const START_REFRESH_DELAY_MS = 75000; // 75 Sek. nach Ladestart: Fahrzeug aufwecken für Restzeit & SoC
                                      const STOP_REFRESH_DELAY_MS = 30000; // 30 Sek. nach bestätigtem Ladestopp: Finalen SoC & Status abrufen
                                      const START_VERIFY_TIMEOUT_MS = 35000; // 35 Sek. maximale Wartezeit auf "Charging"-Status nach Startbefehl
                                      const START_AVAILABILITY_TOGGLE_DELAY_MS = 2000; // 2 Sek. Pause bei Verfügbarkeitswechsel
                                      const START_HANDSHAKE_DELAY_MS = 4000; // 4 Sek. Puffer für OCPP-Handshake nach Re-Aktivierung
                                      // [NEU] Verzögerung vor dem erneuten Versuch des Stopp-Befehls nach dem ersten Versuch.
                                      const FORCE_STOP_RETRY_DELAY_MS = 5000;
                                      // [NEU] Verzögerung während des Verfügbarkeitswechsels, um der Wallbox Zeit zur Verarbeitung zu geben.
                                      const FORCE_STOP_AVAILABILITY_TOGGLE_DELAY_MS = 2000;
                                      
                                      let startZeitLaden = null; // Merker für Statistik
                                      let originalMinSoc = null; // Merker für Min-SoC bei manuellem Laden
                                      let stopTimer = null; // Timer zur Entprellung von kurzen Lade-Unterbrechungen
                                      let startRefreshTimer = null; // Timer für Statusabfrage nach Ladestart
                                      let stopRefreshTimer = null; // Timer für Statusabfrage nach Ladeende
                                      let reconnectTimer = null; // Timer für Wallbox-Recovery
                                      let wasOfflineReported = false; // Status für Anti-Spam Meldungen
                                      let hasWarnedOcppOffline = false; // Flag to prevent repeated warning logs per script run
                                      // [NEU] Sperrvariable zur Vermeidung von Race Conditions während der Startsequenz.
                                      let isStartingSequenceActive = false;
                                      // [NEU] Sperrvariable zur Vermeidung mehrerer gleichzeitiger Ausführungen von erzwungenen Stopps.
                                      let isForceStopping = false;
                                      
                                      // --- 2. INITIALISIERUNG ---
                                      
                                      async function initLadeSystem() {
                                       // Erstellt nur noch die für diese Version nötigen Punkte
                                       if (!existsState(IDS.u_auto))
                                         await createStateAsync(IDS.u_auto, true, {
                                           type: "boolean",
                                           name: "PV Automatic",
                                         });
                                       if (!existsState(IDS.u_smooth))
                                         await createStateAsync(IDS.u_smooth, 10, {
                                           type: "number",
                                           name: "EMA Smoothing",
                                         });
                                       if (!existsState(IDS.u_limit))
                                         await createStateAsync(IDS.u_limit, 80, {
                                           type: "number",
                                           name: "Charge Target",
                                         });
                                       // NEU: Datenpunkt für die Ladestart-Anforderung
                                       if (!existsState(IDS.u_startChargeRequest))
                                         await createStateAsync(IDS.u_startChargeRequest, false, {
                                           type: "boolean",
                                           name: "Start Charging (Request)",
                                           role: "button",
                                         });
                                       if (!existsState(IDS.u_startTs))
                                         await createStateAsync(IDS.u_startTs, 0, { type: "number", name: "Start Timestamp" });
                                       if (!existsState(IDS.u_origSoc))
                                         await createStateAsync(IDS.u_origSoc, 0, { type: "number", name: "Original MinSoc Backup" });
                                      
                                       // Laufende Prozesse nach Skript-Neustart wiederherstellen
                                       if (getState(IDS.wbTrans)?.val === true) {
                                         startZeitLaden = getState(IDS.u_startTs)?.val || Date.now();
                                         const savedSoc = getState(IDS.u_origSoc)?.val;
                                         originalMinSoc = savedSoc !== null && savedSoc !== 0 ? savedSoc : null;
                                         if (getState(IDS.wbStat)?.val === "Charging") {
                                           setState(IDS.u_power, FIXED_CHARGE_W, true);
                                         }
                                       }
                                      }
                                      initLadeSystem();
                                      
                                      // --- 2.1 HELPER: ASYNCHRONE PAUSE & MESSWERTE ---
                                      
                                      /**
                                      * Asynchroner Timer zur Ablaufverzögerung in async-Funktionen.
                                      * @param {number} ms Millisekunden
                                      */
                                      const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
                                      
                                      /**
                                      * Wartet bis der Wallbox-Status auf "Charging" wechselt oder der Timeout abläuft.
                                      * @param {number} timeoutMs Maximale Wartezeit in Millisekunden
                                      * @returns {Promise<boolean>} True falls "Charging" erreicht wurde, sonst False
                                      */
                                      async function waitForChargingState(timeoutMs) {
                                       const startTime = Date.now();
                                       while (Date.now() - startTime < timeoutMs) {
                                         if (getState(IDS.wbStat)?.val === "Charging") {
                                           return true;
                                         }
                                         await wait(1000);
                                       }
                                       return getState(IDS.wbStat)?.val === "Charging";
                                      }
                                      
                                      /**
                                      * Sammelt alle relevanten Leistungs- und SoC-Werte aus den Datenpunkten.
                                      * Stellt sicher, dass die Werte Zahlen sind.
                                      */
                                      function getPowerMetrics() {
                                       return {
                                         pvPower: Math.max(0, Number(getState(IDS.pvPower)?.val) || 0),
                                         pvAverage: Number(getState(IDS.pvAverage)?.val) || 0,
                                         batSoc: Number(getState(IDS.batSocPV)?.val) || 0,
                                         evSoc: Number(getState(IDS.soc)?.val) || 0,
                                       };
                                      }
                                      
                                      // --- 3. KOMMUNIKATION ---
                                      
                                      /**
                                      * Führt die intelligente Startsequenz der Wallbox inklusive Verifikations-Watchdog
                                      * und automatischem Retry-Mechanismus aus.
                                      * @param {string} reason Grund für den Start (z. B. "PV-Automatik", "VIS-Manual")
                                      */
                                      async function triggerStartSequence(reason = "PV-Surplus") {
                                       if (isStartingSequenceActive) {
                                         console.log(`[EV3 Master] Start sequence already active, skipping (${reason}).`);
                                         return;
                                       }
                                      
                                       const wbStatus = getState(IDS.wbStat)?.val;
                                       if (wbStatus === "Charging") {
                                         console.log(`[EV3 Master] Wallbox is already charging. Skipping start sequence.`);
                                         return;
                                       }
                                      
                                       const readyToStart = ["Preparing", "Finishing", "SuspendedEVSE", "SuspendedEV"].includes(
                                         wbStatus,
                                       );
                                      
                                       if (!readyToStart) {
                                         if (wbStatus === "Available") {
                                           // console.warn(`[EV3 Master] Start (${reason}) aborted: No vehicle detected.`);
                                           return;
                                         }
                                       }
                                      
                                       isStartingSequenceActive = true;
                                       console.log(
                                         `[EV3 Master] Starting wallbox sequence for: ${reason} (Current Status: ${wbStatus})`,
                                       );
                                      
                                       try {
                                         // --- VERSUCH 1 ---
                                         console.log("[EV3 Master] Start attempt 1: Toggling availability and setting wbTrans = true.");
                                         setState(IDS.wbAvail, false);
                                         await wait(START_AVAILABILITY_TOGGLE_DELAY_MS);
                                         setState(IDS.wbAvail, true);
                                         await wait(START_HANDSHAKE_DELAY_MS); // Erhöhter Puffer für den OCPP-Handshake
                                         setState(IDS.wbTrans, true);
                                      
                                         let started = await waitForChargingState(START_VERIFY_TIMEOUT_MS);
                                      
                                         // --- VERSUCH 2 (AUTOMATISCHER RETRY BEI TIMEOUT / FEHLSCHLAG) ---
                                         if (!started) {
                                           const currentStatus = getState(IDS.wbStat)?.val;
                                           console.warn(
                                             `[EV3 Master] Start attempt 1 timed out. Wallbox status is '${currentStatus}'. Retrying reset sequence...`,
                                           );
                                      
                                           setState(IDS.wbTrans, false);
                                           await wait(FORCE_STOP_RETRY_DELAY_MS);
                                           setState(IDS.wbAvail, false);
                                           await wait(START_AVAILABILITY_TOGGLE_DELAY_MS);
                                           setState(IDS.wbAvail, true);
                                           await wait(START_HANDSHAKE_DELAY_MS);
                                           setState(IDS.wbTrans, true);
                                      
                                           started = await waitForChargingState(START_VERIFY_TIMEOUT_MS);
                                         }
                                      
                                         // --- ERGEBNIS-AUSWERTUNG ---
                                         if (started) {
                                           console.log(`[EV3 Master] Wallbox start verified successfully (${reason}).`);
                                           ev3Notify(`🔋 EV3-Ladung gestartet via ${reason} mit 6A`);
                                         } else {
                                           const finalStatus = getState(IDS.wbStat)?.val;
                                           console.error(
                                             `[EV3 Master] Start failed after retry. Wallbox did not reach 'Charging' state (Status: ${finalStatus}). Reverting wbTrans.`,
                                           );
                                           setState(IDS.wbTrans, false);
                                           ev3Notify(
                                             `⚠️ EV3 Ladestart fehlgeschlagen: Wallbox reagiert nicht (Status: ${finalStatus})`,
                                             4,
                                           );
                                         }
                                       } catch (e) {
                                         console.error(`[EV3 Master] Error during start sequence: ${e.message}`);
                                         setState(IDS.wbTrans, false);
                                         ev3Notify(`❌ Fehler bei Ladestart-Sequenz: ${e.message}`, 5);
                                       } finally {
                                         isStartingSequenceActive = false;
                                       }
                                      }
                                      
                                      /**
                                      * [NEU] forceStopCharging()
                                      * Versucht, den Ladevorgang zu beenden, selbst wenn der Status "hängt".
                                      * Nutzt den Verfügbarkeitswechsel (Availability-Toggle) als letzten Ausweg.
                                      * Diese Funktion wird aufgerufen, wenn `transactionActive` auf `false` gesetzt wurde,
                                      * die Wallbox aber immer noch den Status `Charging` meldet.
                                      */
                                      async function forceStopCharging() {
                                       // Gleichzeitige Ausführung verhindern
                                       if (isForceStopping) {
                                         console.log("[EV3 Master] Force stop already active, skipping.");
                                         return;
                                       }
                                       isForceStopping = true;
                                       console.warn("[EV3 Master] Initiating forced charging stop sequence.");
                                      
                                       try {
                                         // Versuch 1: Sende transactionActive: false erneut
                                         // Standardweg, um eine Session zu beenden.
                                         console.log("[EV3 Master] Force stop attempt 1: Setting wbTrans to false.");
                                         setState(IDS.wbTrans, false);
                                         // Warten, damit die Wallbox Zeit zur Verarbeitung hat.
                                         await wait(FORCE_STOP_RETRY_DELAY_MS);
                                      
                                         if (getState(IDS.wbStat)?.val === "Charging") {
                                           console.warn(
                                             "[EV3 Master] Force stop attempt 1 failed. Proceeding with Availability Toggle.",
                                           );
                                           // Versuch 2: Verfügbarkeitswechsel (Availability-Toggle)
                                           console.log("[EV3 Master] Force stop attempt 2: Toggling wbAvail (false -> true).");
                                           setState(IDS.wbAvail, false);
                                           // Nach dem Deaktivieren warten
                                           await wait(FORCE_STOP_AVAILABILITY_TOGGLE_DELAY_MS);
                                           setState(IDS.wbAvail, true);
                                           // Vor dem erneuten Stopp-Versuch warten
                                           await wait(FORCE_STOP_AVAILABILITY_TOGGLE_DELAY_MS);
                                           setState(IDS.wbTrans, false);
                                           ev3Notify("⚠️ Wallbox Ladestop erzwungen (Availability Reset)", 3);
                                           console.log("[EV3 Master] Force stop attempt 2 completed.");
                                         } else {
                                           console.log("[EV3 Master] Forced charging stop successful on first attempt.");
                                         }
                                       } catch (e) {
                                         console.error(`[EV3 Master] Error during forced charging stop: ${e.message}`);
                                         ev3Notify(`❌ Fehler beim erzwungenen Ladestopp: ${e.message}`, 5);
                                       } finally {
                                         isForceStopping = false;
                                         if (stopTimer) {
                                           clearTimeout(stopTimer);
                                           stopTimer = null;
                                           console.log("[EV3 Master] Cleared stopTimer after forced stop.");
                                         }
                                         if (startRefreshTimer) {
                                           clearTimeout(startRefreshTimer);
                                           startRefreshTimer = null;
                                         }
                                         setState(IDS.u_power, 0, true);
                                         if (startZeitLaden) {
                                           const stats = updateChargeStatistics(Date.now() - startZeitLaden);
                                           setState(IDS.u_timeDay, stats.totalMinToday, true);
                                           ev3Notify(
                                             `❌ Ladung beendet (forced). Heute geladen: ${stats.formattedTime} (+approx. ${stats.kmToday} km)`,
                                             1,
                                           );
                                           startZeitLaden = null;
                                           setState(IDS.u_startTs, 0, true);
                                         }
                                         if (originalMinSoc !== null) {
                                           setState(IDS.minSocSet, Math.max(0, originalMinSoc));
                                           ev3Notify(`🔌 Hausbatterie MinSoc auf ${originalMinSoc}% nach erzwungenem Stop eingestellt`);
                                           originalMinSoc = null;
                                           setState(IDS.u_origSoc, 0, true);
                                         }
                                         if (stopRefreshTimer) clearTimeout(stopRefreshTimer);
                                         stopRefreshTimer = setTimeout(() => {
                                           console.log(
                                             "[EV3 Master] Triggering post-stop vehicle refresh for final SoC and statistics.",
                                           );
                                           if (existsState(IDS.refreshCar)) {
                                             setState(IDS.refreshCar, true);
                                           }
                                           stopRefreshTimer = null;
                                         }, STOP_REFRESH_DELAY_MS);
                                       }
                                      }
                                      
                                      function ev3Notify(text, prio = 1, spoken = null) {
                                       sendTo("telegram", "send", { text: text }); // An Telegram senden
                                      
                                       // Token dynamisch auflösen für erhöhte Robustheit
                                       const gotifyToken = getState("0_userdata.0.gotifytoken.iobroker")?.val;
                                       if (gotifyToken) {
                                         const url = `https://mygotify.meistermopper.de/message?token=${gotifyToken}`;
                                         const payload = { title: "EV3 Master", message: text, priority: prio };
                                         const options = {
                                           headers: { "Content-Type": "application/json" },
                                           timeout: 10000,
                                         };
                                      
                                         httpPost(url, payload, options, (err) => {
                                           if (err) console.error(`[EV3 Master] Gotify Error: ${err}`);
                                         });
                                       } else {
                                         console.warn("[EV3 Master] Gotify Token ist nicht definiert oder leer.");
                                       }
                                      
                                       // Sprachausgabe tagsüber
                                       if (compareTime("08:00", "20:00", "between")) {
                                         // Wenn ein spezieller Sprechtext übergeben wurde (spoken), nutzen wir diesen.
                                         // Andernfalls nehmen wir den Standardtext.
                                         let voice = spoken || text;
                                         voice = voice
                                           .replace(/%/g, " Prozent")
                                           .replace(/SOC/gi, "Ladestand")
                                           .replace(/🔋|🔌|⚠️|🚗|❌/g, "");
                                         // sendTo("sayit", "say", { text: voice });
                                       }
                                      }
                                      
                                      // --- 4. INTELLIGENTE PV-GLÄTTUNG (EMA) ---
                                      
                                      /**
                                      * Berechnet die durchschnittliche PV-Leistung zur Stabilisierung der Regelung.
                                      * Reagiert schnell auf Einbrüche, langsam auf Erhöhungen.
                                      */
                                      schedule("* * * * *", async () => {
                                       const { pvPower: current, pvAverage: oldAvg, batSoc } = getPowerMetrics();
                                       const inertia = Number(getState(IDS.u_smooth)?.val) || 10;
                                      
                                       let alpha;
                                       if (current < oldAvg) {
                                         // ABFALL: Wenn die Hausbatterie voll ist (>85%), langsamer reagieren (0,2 statt 0,5).
                                         // Dies verhindert unnötige Ladestopps bei kurzen Wolken.
                                         alpha = batSoc > 85 ? 0.2 : 0.5;
                                       } else {
                                         // ANSTIEG: Wenn die Hausbatterie noch leer ist (<50%), länger auf stabile Sonne warten.
                                         // Wenn die Batterie voll ist, die Sonne schneller nutzen.
                                         const dynamicInertia = batSoc > 75 ? Math.max(2, inertia / 2) : inertia;
                                         alpha = 1 / dynamicInertia;
                                       }
                                      
                                       const newAvg = alpha * current + (1 - alpha) * oldAvg;
                                       setState(IDS.pvAverage, Math.round(newAvg), true);
                                      });
                                      
                                      // --- 5. AUTOMATISIERUNGS-LOGIK (PV-ÜBERSCHUSS) ---
                                      
                                      /**
                                      * Überwacht den PV-Durchschnitt und schaltet das Laden automatisch,
                                      * vorausgesetzt der Automatik-Schalter in VIS ist aktiv.
                                      */
                                      function checkPvAutomation() {
                                       const isAuto = !!getState(IDS.u_auto)?.val; // Automatik-Schalter
                                       const { pvAverage: mittel, batSoc, evSoc } = getPowerMetrics(); // Aktuelle Leistungswerte
                                      
                                       // Abbrechen, wenn Wallbox offline ist
                                       const isConnected = !!getState(IDS.wbConn)?.val;
                                       if (!isConnected && mittel > PV_START_LIMIT) {
                                         if (!hasWarnedOcppOffline) {
                                           console.warn("[EV3 Master] Start not possible: Wallbox connection missing (OCPP Offline)");
                                           hasWarnedOcppOffline = true;
                                         }
                                       }
                                       if (!isAuto || !isConnected) return;
                                      
                                       const isTransActive = !!getState(IDS.wbTrans)?.val;
                                       const _wbStatus = getState(IDS.wbStat)?.val;
                                       const limitCar = getState(IDS.targetSocSrv)?.val || 100;
                                      
                                       // Diagnose-Log für ausreichenden Überschuss, falls nicht geladen wird
                                       //if (!isTransActive && (mittel > (PV_START_LIMIT - 500))) {
                                       //    console.log(`[EV3 Master] Status: ${wbStatus} | PV-Avg: ${mittel}W | Bat-SoC: ${batSoc}% | EV-SoC: ${evSoc}% / Ziel: ${limitCar}%`);
                                       //}
                                      
                                       // START: Genug Sonne (>4.6kW) und Hausspeicher gut gefüllt (>75%)
                                       if (
                                         !isTransActive &&
                                         !isStartingSequenceActive &&
                                         mittel > PV_START_LIMIT &&
                                         batSoc > 75 &&
                                         evSoc < limitCar
                                       ) {
                                         triggerStartSequence("PV-Automatik");
                                       }
                                      
                                       // STOP: Überschuss sinkt unter Ladeleistung (Pause)
                                       // oder Ladeziel erreicht
                                       // oder Wallbox-Verbindung verloren (oben durch !isConnected abgefangen, hier als Redundanz)
                                       else if (isTransActive && (mittel < PV_STOP_LIMIT || evSoc >= limitCar)) {
                                         // Detailliertes Logging des Stopp-Grunds
                                         let reason = "";
                                         if (mittel < PV_STOP_LIMIT) reason = `Insufficient PV power (${mittel}W < ${PV_STOP_LIMIT}W)`;
                                         else if (evSoc >= limitCar)
                                           reason = `Vehicle charging target reached (${evSoc}% >= ${limitCar}%)`;
                                      
                                         if (reason) {
                                           console.log(`[EV3 Master] Automatically stopped: ${reason}`);
                                         }
                                      
                                         setState(IDS.wbTrans, false);
                                         //ev3Notify("EV3 charging ended");
                                       }
                                      }
                                      
                                      // Trigger bei neuen PV-Werten sowie bei Wiederherstellung der Verbindung
                                      on({ id: IDS.pvAverage, change: "ne" }, checkPvAutomation);
                                      on({ id: IDS.soc, change: "ne" }, checkPvAutomation);
                                      on({ id: IDS.wbConn, val: true, change: "ne" }, checkPvAutomation);
                                      
                                      // [NEU] Listener für den Datenpunkt wbTrans.
                                      // Dieser Listener ist entscheidend für das Erkennen und Beheben von "hängenden" Ladestatuse.
                                      // Wenn `wbTrans` auf `false` wechselt (Stopp-Befehl gesendet), prüfen wir nach einer Verzögerung
                                      // von 10 Sekunden, ob `wbStat` immer noch `Charging` ist, und rufen in diesem Fall `forceStopCharging()` auf.
                                      on({ id: IDS.wbTrans, change: "ne" }, (obj) => {
                                       if (obj.state.val === false) {
                                         // 10 Sekunden Verzögerung, um der Wallbox Zeit zur Verarbeitung zu geben
                                         setTimeout(async () => {
                                           if (getState(IDS.wbStat)?.val === "Charging") {
                                             console.warn(
                                               "[EV3 Master] Wallbox hängt im Status 'Charging' trotz beendeter Transaktion. Erzwinge Stopp.",
                                             );
                                             await forceStopCharging();
                                           }
                                         }, 10000);
                                       }
                                      });
                                      // --- 6. ÜBERWACHUNG & STATISTIKEN ---
                                      
                                      /**
                                      * Erfasst die Ladedauer und stellt die Leistungsanzeige ein.
                                      * Erfasst die Ladedauer, stellt die Leistungsanzeige ein und schützt die Hausbatterie
                                      * vor Entladung beim manuellen Laden.
                                      * Berechnet die Statistiken für den aktuellen oder abgeschlossenen Ladevorgang.
                                      */
                                      function updateChargeStatistics(sessionDurationMs) {
                                       const dauerMin = Math.max(1, Math.round(sessionDurationMs / 60000)); // Mindestens 1 Minute zählen
                                       const currentTotalMin = getState(IDS.u_timeDay)?.val || 0;
                                       const totalMinToday = currentTotalMin + dauerMin;
                                      
                                       // Energie und Reichweite
                                       const energyKWh = (totalMinToday / 60) * (FIXED_CHARGE_W / 1000);
                                       const month = new Date().getMonth();
                                       const rangeMax = month >= 3 && month <= 10 ? RANGE_SUMMER : RANGE_WINTER;
                                       const kmToday = Math.round((energyKWh / CAR_CAPACITY_KWH) * rangeMax);
                                      
                                       const h = Math.floor(totalMinToday / 60);
                                       const m = totalMinToday % 60;
                                       const formattedTime = h > 0 ? `${h}:${m < 10 ? `0${m}` : m} Std` : `${m} Min`;
                                      
                                       return {
                                         totalMinToday,
                                         formattedTime,
                                         kmToday,
                                         spokenTime: h > 0 ? `${h} Stunden, ${m} Minuten` : `${m} Minuten`,
                                       };
                                      }
                                      
                                      // Haupt-Überwacher für den Wallbox-Status (z. B. Charging, Preparing, SuspendedEV...)
                                      on({ id: IDS.wbStat, change: "ne" }, (obj) => {
                                       const status = String(obj.state.val);
                                       const isAuto = !!getState(IDS.u_auto)?.val;
                                      
                                       // FALL 1: Das Fahrzeug lädt aktiv
                                       if (status === "Charging") {
                                         // Falls ein Stop-Timer läuft (kurze Ladeunterbrechung durch z.B. Wolken):
                                         // Timer abbrechen, da die Ladung direkt fortgesetzt wurde (Hiccup-Schutz).
                                         if (stopTimer) {
                                           clearTimeout(stopTimer);
                                           stopTimer = null;
                                           console.log("[EV3 Master] Short interruption ended, resuming charge");
                                           return;
                                         }
                                      
                                         // Startzeitpunkt merken, sofern noch nicht gesetzt (für die tägliche Statistik)
                                         if (!startZeitLaden) {
                                           startZeitLaden = Date.now();
                                           setState(IDS.u_startTs, startZeitLaden, true);
                                      
                                           // 75 Sek. nach Ladestart Fahrzeug aufwecken, um verbleibende Ladedauer & SoC präzise abzurufen
                                           if (startRefreshTimer) clearTimeout(startRefreshTimer);
                                           startRefreshTimer = setTimeout(() => {
                                             if (getState(IDS.wbStat)?.val === "Charging") {
                                               console.log(
                                                 "[EV3 Master] Triggering post-start vehicle refresh to update SoC and remaining time.",
                                               );
                                               if (existsState(IDS.refreshCar)) {
                                                 setState(IDS.refreshCar, true);
                                               }
                                             }
                                             startRefreshTimer = null;
                                           }, START_REFRESH_DELAY_MS);
                                         }
                                      
                                         // Da die Box starr mit 6A lädt (3 Phasen * 230V * 6A = ~3,96 kW), setzen wir den festen Watt-Wert zur Anzeige
                                         setState(IDS.u_power, FIXED_CHARGE_W, true);
                                      
                                         // BATTERIESCHUTZ bei manuellem Laden (Automatik AUS):
                                         // Verhindert, dass der Hausspeicher entleert wird, indem der Min-SoC der Hausbatterie temporär
                                         // auf den aktuellen SoC-Wert gesetzt wird.
                                         if (!isAuto && originalMinSoc === null) {
                                           originalMinSoc = getState(IDS.minSocRead)?.val;
                                           setState(IDS.u_origSoc, originalMinSoc, true);
                                           const currentBatSoc = getState(IDS.batSocPV)?.val;
                                           // MinSoc sicherheitshalber nicht unter 0 setzen
                                           setState(IDS.minSocSet, Math.max(0, currentBatSoc));
                                           const msg = `Manuelles Laden gestartet. MinSoc auf ${currentBatSoc}% (vorher: ${originalMinSoc}%)`;
                                           console.log(`[EV3 Master] ${msg}`);
                                           ev3Notify(`🔋 ${msg}`);
                                         }
                                       }
                                      
                                       // FALL 2: Das Fahrzeug stoppt (durch Kabel ziehen, Auto-Ladeziel erreicht, Pause durch PV-Regelung etc.)
                                       else if (
                                         startZeitLaden &&
                                         (status === "Finishing" ||
                                           status === "Available" ||
                                           status === "SuspendedEV" ||
                                           status === "SuspendedEVSE")
                                       ) {
                                         if (startRefreshTimer) {
                                           clearTimeout(startRefreshTimer);
                                           startRefreshTimer = null;
                                         }
                                         // Um bei kurzen Unterbrechungen nicht sofort abzubrechen, warten wir 45 Sekunden (Entprellzeit).
                                         // Wechselt der Status in dieser Zeit zurück auf "Charging", läuft die Ladung oben nahtlos weiter.
                                         if (stopTimer) clearTimeout(stopTimer);
                                      
                                         stopTimer = setTimeout(() => {
                                           // 1. Batterieschutz aufheben: Min-SoC des Hausspeichers wieder auf den ursprünglichen Wert zurückstellen
                                           if (!isAuto && originalMinSoc !== null) {
                                             setState(IDS.minSocSet, Math.max(0, originalMinSoc));
                                             const msg = `EV3 Manuelles Laden beendet. Hausbatterie MinSoc wieder auf ${originalMinSoc}% gestellt`;
                                             console.log(`[EV3 Master] ${msg}`);
                                             ev3Notify(`🔌 ${msg}`);
                                             originalMinSoc = null;
                                             setState(IDS.u_origSoc, 0, true);
                                           }
                                      
                                           // 2. Ladestatistik berechnen (Dauer in Min, geladene kWh und hinzugewonnene Kilometer je nach Jahreszeit)
                                           const stats = updateChargeStatistics(Date.now() - startZeitLaden);
                                           setState(IDS.u_timeDay, stats.totalMinToday, true);
                                      
                                           // 3. Prüfen, ob das Auto das Ladeziel erreicht hat:
                                           // Vergleicht den aktuellen SoC des Kia mit dem eingestellten Ladeziel der Wallbox/des Fahrzeugs
                                           const evSoc = Number(getState(IDS.soc)?.val) || 0;
                                           const targetSoc = Number(getState(IDS.targetSocSrv)?.val) || 100;
                                      
                                           let msgText = `❌ EV3 Ladung beendet. Heute geladen: ${stats.formattedTime} (+approx. ${stats.kmToday} km)`;
                                           let spokenText = `Ladung beendet. Heute geladen: ${stats.spokenTime}. Reichweite approx. ${stats.kmToday} Kilometer.`;
                                      
                                           // Wenn das Ladeziel erreicht wurde, ergänzen wir die Benachrichtigungen
                                           if (evSoc >= targetSoc) {
                                             msgText += ` - Das Ladeziel von ${targetSoc}% wurde erreicht`;
                                             spokenText += ` Das Ladeziel von ${targetSoc} Prozent wurde erreicht`;
                                           }
                                      
                                           // Benachrichtigung senden (Telegram, Gotify, Alexa/SayIt)
                                           ev3Notify(msgText, 1, spokenText);
                                      
                                           // 4. Ladevariablen zurücksetzen & Ladevorgang sauber abschließen
                                           startZeitLaden = null;
                                           setState(IDS.u_startTs, 0, true);
                                           setState(IDS.u_power, 0, true);
                                      
                                           // WICHTIG: Setzt transactionActive auf false, damit die Wallbox die Transaktion beendet
                                           // und die VIS-Visualisierung nicht mehr "lädt..." anzeigt (Logikfehler-Behebung).
                                           setState(IDS.wbTrans, false);
                                      
                                           stopTimer = null;
                                      
                                           // Finalen Status nach Ladeende vom Fahrzeug abrufen
                                           if (stopRefreshTimer) clearTimeout(stopRefreshTimer);
                                           stopRefreshTimer = setTimeout(() => {
                                             console.log(
                                               "[EV3 Master] Triggering post-stop vehicle refresh for final SoC and statistics.",
                                             );
                                             if (existsState(IDS.refreshCar)) {
                                               setState(IDS.refreshCar, true);
                                             }
                                             stopRefreshTimer = null;
                                           }, STOP_REFRESH_DELAY_MS);
                                         }, DEBOUNCE_STOP_MS);
                                       }
                                      });
                                      
                                      // Dynamischer Batterieschutz bei manuellem Laden:
                                      // Erhöht sich der SoC des Heimspeichers während des manuellen Ladens (z. B. durch PV-Ertrag),
                                      // wird der Min-SoC des Wechselrichters entsprechend nach oben angepasst.
                                      on({ id: IDS.batSocPV, change: "ne" }, (obj) => {
                                       const isAuto = !!getState(IDS.u_auto)?.val;
                                       const isCharging = getState(IDS.wbStat)?.val === "Charging";
                                      
                                       if (!isAuto && isCharging) {
                                         const newSoc = Number(obj.state.val) || 0;
                                         const oldSoc = Number(obj.oldState?.val) || 0;
                                      
                                         if (newSoc > oldSoc) {
                                           if (originalMinSoc === null) {
                                             originalMinSoc = getState(IDS.minSocRead)?.val;
                                             setState(IDS.u_origSoc, originalMinSoc, true);
                                           }
                                           setState(IDS.minSocSet, Math.max(0, newSoc));
                                           console.log(
                                             `[EV3 Master] Manual charging: Home battery SoC increased from ${oldSoc}% to ${newSoc}%. Updated MinSoC to ${newSoc}%.`,
                                           );
                                         }
                                       }
                                      });
                                      
                                      // --- 7. ZUSÄTZLICHE FUNKTIONEN ---
                                      
                                      /**
                                      * Verbindungs-Watchdog: Überwacht die Erreichbarkeit der Wallbox.
                                      * Meldet Statusänderungen (Anti-Spam) und löst nach 3 Min. Offline-Zeit einen Reconnect über den UniFi-AP aus.
                                      */
                                      on({ id: IDS.wbConn, change: "ne" }, (obj) => {
                                       const isConnected = !!obj.state.val;
                                      
                                       if (!isConnected) {
                                         // Nur beim ersten Mal warnen
                                         if (!wasOfflineReported) {
                                           //console.warn("[EV3 Master] Wallbox-Verbindung verloren. Reconnect-Timer (3 Min) gestartet.");
                                           wasOfflineReported = true;
                                         }
                                         // Reconnect-Timer starten (falls nicht schon einer läuft)
                                         if (!reconnectTimer) {
                                           reconnectTimer = setTimeout(() => {
                                             //console.log("[EV3 Master] Führe WLAN-Neuverbindung über UniFi AP aus...");
                                             setState(IDS.unifiReconnect, true);
                                             reconnectTimer = null;
                                           }, RECONNECT_WB_MS);
                                         }
                                       } else {
                                         // Wieder online: Status zurücksetzen und Timer stoppen
                                         if (wasOfflineReported) console.log("[EV3 Master] Wallbox connection restored.");
                                         wasOfflineReported = false;
                                         if (reconnectTimer) {
                                           clearTimeout(reconnectTimer);
                                           reconnectTimer = null;
                                         }
                                       }
                                      });
                                      
                                      /**
                                      * Formatiert die verbleibende Ladezeit für die Anzeige in VIS.
                                      */
                                      on({ id: IDS.remTime, change: "any" }, (obj) => {
                                       const m = obj.state.val;
                                       let t = "0:00";
                                       if (m > 0) {
                                         const hh = Math.floor(m / 60);
                                         const mm = m % 60;
                                         t = `${hh}:${mm < 10 ? `0${mm}` : mm}`;
                                       }
                                       setState(IDS.u_rest, t, true);
                                      });
                                      
                                      // Synchronisiert den VIS-Anzeige-Datenpunkt mit dem echten Ladeziel des Autos
                                      on({ id: IDS.targetSocSrv, change: "ne" }, (obj) => {
                                       console.log(`[EV3 Master] Charge target sync: Setting VIS slider to ${obj.state.val}%.`);
                                       setState(IDS.u_limit, obj.state.val, true);
                                      });
                                      
                                      // Handler für manuelle Start-Anforderungen
                                      on({ id: IDS.u_startChargeRequest, val: true, change: "any" }, () => {
                                       console.log("[EV3 Master] Manual start request received via VIS.");
                                       triggerStartSequence("VIS-Manual");
                                       setTimeout(() => {
                                         setState(IDS.u_startChargeRequest, false, true);
                                       }, 1000);
                                      });
                                      
                                      // Täglicher Reset der Ladestatistik um 02:05 Uhr
                                      schedule("5 2 * * *", () => {
                                       setState(IDS.u_timeDay, 0, true);
                                      });
                                      
                                      // Schutz der Kia 12V-Starterbatterie
                                      on({ id: IDS.bat12v, change: "ne" }, (obj) => {
                                       if (obj.state.val <= 50) ev3Notify(`⚠️ Kia 12V battery critical!`, 5);
                                      });
                                      
                                      

                                      fuzzy1955F Online
                                      fuzzy1955F Online
                                      fuzzy1955
                                      schrieb am zuletzt editiert von
                                      #18

                                      @Meister-Mopper sagte:

                                      Mein Ladeskript hat mehr als 700 Zeilen, aber bitte

                                      Danke, das hat es in sich ;-) Ich probier' mal etwas davon aus.

                                      Smart-Home-Automation unter IOB auf RASPI5, 16GB RAM, 50GB SSD, MariaSQL, VIS-2.
                                      Anfang 2025 war ich Newbie in Sachen RaspBerry, Linux und IOB.
                                      Jetzt läuft alles konstant gut und ich gebe gern meine Erfahrungen und mein Wissen an die Forums-User/Innen weiter.
                                      Großes Danke an alle tatkräftigen Helfer im Forum!

                                      1 Antwort Letzte Antwort
                                      0
                                      • Meister MopperM Meister Mopper

                                        @fuzzy1955

                                        Ich habe eine EVBox.

                                        Die verbindet sich mit ws://IPdesioBroker:Port ohne Benutzername und Passwort mit dem ioBroker. Der Port wird im Adapter festgelegt.

                                        6d2284a5-f73a-4318-a118-ec1fcc316075-image.jpeg

                                        Mein Ladeskript hat mehr als 700 Zeilen, aber bitte:

                                        /* eslint-env es2022 */
                                        /**
                                        * Name:    EV3 Charge-Master
                                        * Purpose: Start/stop management for Kia EV3 wallbox charging (fixed 6A / 3.96 kW).
                                        * Modes:   1. Manual: User triggered via VIS
                                        *          2. PV Auto: Automated based on PV surplus and home battery SoC
                                        * Features: Home battery protection, debounced status handling, forced transaction stops.
                                        */
                                        
                                        // --- 1. SETUP: DIGITALE ZENTRALE (21 DATENPUNKTE) ---
                                        
                                        const VIN = `bluelink.0.${getState("0_userdata.0.Energie.Kia_e_niro.vin")?.val}`;
                                        const PATH_USER = "0_userdata.0.Energie.Kia_e_niro";
                                        
                                        const IDS = {
                                         // Wallbox (Hardware via OCPP)
                                         wbStat: "ocpp.0.http://192_168_178_80:9220/EVB-P21312507.1.status", // [1] Status (Charging, Preparing...)
                                         wbTrans: "ocpp.0.http://192_168_178_80:9220/EVB-P21312507.1.transactionActive", // [2] Steuert den Stromfluss (Transaktion aktiv)
                                         wbAvail: "ocpp.0.http://192_168_178_80:9220/EVB-P21312507.1.availability", // [3] Reset / Verfügbarkeit
                                         wbConn: "ocpp.0.http://192_168_178_80:9220/EVB-P21312507.connected", // Verbindung zum ioBroker
                                         unifiReconnect: "unifi-network.0.clients.users.60:09:c3:2f:46:49.reconnect", // [22] Neu verbinden über UniFi
                                        
                                         // Fahrzeugdaten (Cloud)
                                         soc: `${VIN}.vehicleStatusRaw.Green.BatteryManagement.BatteryRemain.Ratio`, // [4] Ladestand %
                                         bat12v: `${VIN}.vehicleStatusRaw.Electronics.Battery.Level`, // [5] 12V-Batterieschutz
                                         conn: `${VIN}.vehicleStatusRaw.Green.ChargingInformation.ConnectorFastening.State`, // [6] Steckerstatus
                                         remTime: `${VIN}.vehicleStatusRaw.Green.ChargingInformation.Charging.RemainTime`, // [7] Restzeit in Min (vom Fahrzeug gemeldet)
                                         targetSocSrv: `${VIN}.control.charge_limit_slow`, // [23] Ladeziel (AC) vom Fahrzeug (Steuerungspunkt)
                                         refreshCar: `${VIN}.control.force_refresh_from_car`, // [8] Fahrzeug aufwecken (Live-Daten)
                                         refreshSrv: `${VIN}.control.force_refresh_from_server`, // [8b] Server-Status abrufen
                                        
                                         // Energie-Zentrale (Hardware-Werte)
                                         pvPower: "solax.0.data.acpower", // [9] Aktuelle PV-Leistung in Watt
                                         pvAverage: "0_userdata.0.Energie.PV.Durchschnitt", // [10] Geglätteter Wert (EMA)
                                         netPower: "0_userdata.0.Energie.PV.Netzbezug", // [11] Hauszähler (+Bezug/-Einspeisung)
                                         hausCons: "0_userdata.0.Energie.PV.Hausverbrauch", // [12] Hausverbrauch
                                         batSocPV: "modbus.0.inputRegisters.100.843_Battery_State_of_Charge_(System)", // [13] Heimspeicher %
                                         minSocSet: "modbus.0.holdingRegisters.100.2901_ESS_Minimum_SoC_(unless_grid_fails)",
                                         minSocRead: "modbus.0.inputRegisters.100.2901_ESS_Minimum_SoC_(unless_grid_fails)",
                                        
                                         // Steuerung & Statistiken (VIS)
                                         u_auto: `${PATH_USER}.autoladen`, // [14] Schalter: PV-Automatik an/aus (Boolean)
                                         u_limit: `${PATH_USER}.Ladeprozent`, // [15] Ziel-SoC Schieberegler
                                         u_smooth: `${PATH_USER}.Glaettung_Zeit`, // [16] Trägheits-Schieberegler für EMA
                                         u_power: `${PATH_USER}.Ladeleistung`, // [17] Anzeige Ladeleistung (fix 3960W)
                                         u_timeDay: `${PATH_USER}.Ladezeit`, // [18] Lademinuten heute
                                         u_rest: `${PATH_USER}.Restladezeit`, // [19] HH:MM Anzeige
                                         aliasKm: "alias.0.umrechnen.kia_ladekm", // [20] Gewonnene Reichweite
                                         aliasDur: "alias.0.umrechnen.kia_ladezeit", // [21] Zeit-Objekt
                                         u_startChargeRequest: `${PATH_USER}.Start_Charge_Request`, // [NEU] Anforderung zum Starten des Ladevorgangs
                                         u_startTs: `${PATH_USER}.LastStartTimestamp`, // [PERSISTENCE] Merker für Startzeit
                                         u_origSoc: `${PATH_USER}.LastOriginalMinSoc`, // [PERSISTENCE] Merker für Batterie-Schutz
                                        };
                                        
                                        // --- PARAMETER ---
                                        const PV_START_LIMIT = 4600; // Startgrenze (Sonne muss > 4.6kW + Puffer liefern)
                                        const PV_STOP_LIMIT = 4000; // Stoppgrenze (Ladevorgang pausieren, wenn Überschuss sinkt)
                                        const FIXED_CHARGE_W = 3960; // Fixe Leistung bei 6A (220V * 3 Phasen * 6A)
                                        const CAR_CAPACITY_KWH = 81.4;
                                        const RANGE_SUMMER = 550;
                                        const RANGE_WINTER = 450;
                                        
                                        // --- TIMING KONSTANTEN ---
                                        const DEBOUNCE_STOP_MS = 45000; // 45 Sek. Wartezeit vor endgültigem Stopp
                                        const RECONNECT_WB_MS = 180000; // 3 Min. Wartezeit vor WLAN-Neuverbindung
                                        const START_REFRESH_DELAY_MS = 75000; // 75 Sek. nach Ladestart: Fahrzeug aufwecken für Restzeit & SoC
                                        const STOP_REFRESH_DELAY_MS = 30000; // 30 Sek. nach bestätigtem Ladestopp: Finalen SoC & Status abrufen
                                        const START_VERIFY_TIMEOUT_MS = 35000; // 35 Sek. maximale Wartezeit auf "Charging"-Status nach Startbefehl
                                        const START_AVAILABILITY_TOGGLE_DELAY_MS = 2000; // 2 Sek. Pause bei Verfügbarkeitswechsel
                                        const START_HANDSHAKE_DELAY_MS = 4000; // 4 Sek. Puffer für OCPP-Handshake nach Re-Aktivierung
                                        // [NEU] Verzögerung vor dem erneuten Versuch des Stopp-Befehls nach dem ersten Versuch.
                                        const FORCE_STOP_RETRY_DELAY_MS = 5000;
                                        // [NEU] Verzögerung während des Verfügbarkeitswechsels, um der Wallbox Zeit zur Verarbeitung zu geben.
                                        const FORCE_STOP_AVAILABILITY_TOGGLE_DELAY_MS = 2000;
                                        
                                        let startZeitLaden = null; // Merker für Statistik
                                        let originalMinSoc = null; // Merker für Min-SoC bei manuellem Laden
                                        let stopTimer = null; // Timer zur Entprellung von kurzen Lade-Unterbrechungen
                                        let startRefreshTimer = null; // Timer für Statusabfrage nach Ladestart
                                        let stopRefreshTimer = null; // Timer für Statusabfrage nach Ladeende
                                        let reconnectTimer = null; // Timer für Wallbox-Recovery
                                        let wasOfflineReported = false; // Status für Anti-Spam Meldungen
                                        let hasWarnedOcppOffline = false; // Flag to prevent repeated warning logs per script run
                                        // [NEU] Sperrvariable zur Vermeidung von Race Conditions während der Startsequenz.
                                        let isStartingSequenceActive = false;
                                        // [NEU] Sperrvariable zur Vermeidung mehrerer gleichzeitiger Ausführungen von erzwungenen Stopps.
                                        let isForceStopping = false;
                                        
                                        // --- 2. INITIALISIERUNG ---
                                        
                                        async function initLadeSystem() {
                                         // Erstellt nur noch die für diese Version nötigen Punkte
                                         if (!existsState(IDS.u_auto))
                                           await createStateAsync(IDS.u_auto, true, {
                                             type: "boolean",
                                             name: "PV Automatic",
                                           });
                                         if (!existsState(IDS.u_smooth))
                                           await createStateAsync(IDS.u_smooth, 10, {
                                             type: "number",
                                             name: "EMA Smoothing",
                                           });
                                         if (!existsState(IDS.u_limit))
                                           await createStateAsync(IDS.u_limit, 80, {
                                             type: "number",
                                             name: "Charge Target",
                                           });
                                         // NEU: Datenpunkt für die Ladestart-Anforderung
                                         if (!existsState(IDS.u_startChargeRequest))
                                           await createStateAsync(IDS.u_startChargeRequest, false, {
                                             type: "boolean",
                                             name: "Start Charging (Request)",
                                             role: "button",
                                           });
                                         if (!existsState(IDS.u_startTs))
                                           await createStateAsync(IDS.u_startTs, 0, { type: "number", name: "Start Timestamp" });
                                         if (!existsState(IDS.u_origSoc))
                                           await createStateAsync(IDS.u_origSoc, 0, { type: "number", name: "Original MinSoc Backup" });
                                        
                                         // Laufende Prozesse nach Skript-Neustart wiederherstellen
                                         if (getState(IDS.wbTrans)?.val === true) {
                                           startZeitLaden = getState(IDS.u_startTs)?.val || Date.now();
                                           const savedSoc = getState(IDS.u_origSoc)?.val;
                                           originalMinSoc = savedSoc !== null && savedSoc !== 0 ? savedSoc : null;
                                           if (getState(IDS.wbStat)?.val === "Charging") {
                                             setState(IDS.u_power, FIXED_CHARGE_W, true);
                                           }
                                         }
                                        }
                                        initLadeSystem();
                                        
                                        // --- 2.1 HELPER: ASYNCHRONE PAUSE & MESSWERTE ---
                                        
                                        /**
                                        * Asynchroner Timer zur Ablaufverzögerung in async-Funktionen.
                                        * @param {number} ms Millisekunden
                                        */
                                        const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
                                        
                                        /**
                                        * Wartet bis der Wallbox-Status auf "Charging" wechselt oder der Timeout abläuft.
                                        * @param {number} timeoutMs Maximale Wartezeit in Millisekunden
                                        * @returns {Promise<boolean>} True falls "Charging" erreicht wurde, sonst False
                                        */
                                        async function waitForChargingState(timeoutMs) {
                                         const startTime = Date.now();
                                         while (Date.now() - startTime < timeoutMs) {
                                           if (getState(IDS.wbStat)?.val === "Charging") {
                                             return true;
                                           }
                                           await wait(1000);
                                         }
                                         return getState(IDS.wbStat)?.val === "Charging";
                                        }
                                        
                                        /**
                                        * Sammelt alle relevanten Leistungs- und SoC-Werte aus den Datenpunkten.
                                        * Stellt sicher, dass die Werte Zahlen sind.
                                        */
                                        function getPowerMetrics() {
                                         return {
                                           pvPower: Math.max(0, Number(getState(IDS.pvPower)?.val) || 0),
                                           pvAverage: Number(getState(IDS.pvAverage)?.val) || 0,
                                           batSoc: Number(getState(IDS.batSocPV)?.val) || 0,
                                           evSoc: Number(getState(IDS.soc)?.val) || 0,
                                         };
                                        }
                                        
                                        // --- 3. KOMMUNIKATION ---
                                        
                                        /**
                                        * Führt die intelligente Startsequenz der Wallbox inklusive Verifikations-Watchdog
                                        * und automatischem Retry-Mechanismus aus.
                                        * @param {string} reason Grund für den Start (z. B. "PV-Automatik", "VIS-Manual")
                                        */
                                        async function triggerStartSequence(reason = "PV-Surplus") {
                                         if (isStartingSequenceActive) {
                                           console.log(`[EV3 Master] Start sequence already active, skipping (${reason}).`);
                                           return;
                                         }
                                        
                                         const wbStatus = getState(IDS.wbStat)?.val;
                                         if (wbStatus === "Charging") {
                                           console.log(`[EV3 Master] Wallbox is already charging. Skipping start sequence.`);
                                           return;
                                         }
                                        
                                         const readyToStart = ["Preparing", "Finishing", "SuspendedEVSE", "SuspendedEV"].includes(
                                           wbStatus,
                                         );
                                        
                                         if (!readyToStart) {
                                           if (wbStatus === "Available") {
                                             // console.warn(`[EV3 Master] Start (${reason}) aborted: No vehicle detected.`);
                                             return;
                                           }
                                         }
                                        
                                         isStartingSequenceActive = true;
                                         console.log(
                                           `[EV3 Master] Starting wallbox sequence for: ${reason} (Current Status: ${wbStatus})`,
                                         );
                                        
                                         try {
                                           // --- VERSUCH 1 ---
                                           console.log("[EV3 Master] Start attempt 1: Toggling availability and setting wbTrans = true.");
                                           setState(IDS.wbAvail, false);
                                           await wait(START_AVAILABILITY_TOGGLE_DELAY_MS);
                                           setState(IDS.wbAvail, true);
                                           await wait(START_HANDSHAKE_DELAY_MS); // Erhöhter Puffer für den OCPP-Handshake
                                           setState(IDS.wbTrans, true);
                                        
                                           let started = await waitForChargingState(START_VERIFY_TIMEOUT_MS);
                                        
                                           // --- VERSUCH 2 (AUTOMATISCHER RETRY BEI TIMEOUT / FEHLSCHLAG) ---
                                           if (!started) {
                                             const currentStatus = getState(IDS.wbStat)?.val;
                                             console.warn(
                                               `[EV3 Master] Start attempt 1 timed out. Wallbox status is '${currentStatus}'. Retrying reset sequence...`,
                                             );
                                        
                                             setState(IDS.wbTrans, false);
                                             await wait(FORCE_STOP_RETRY_DELAY_MS);
                                             setState(IDS.wbAvail, false);
                                             await wait(START_AVAILABILITY_TOGGLE_DELAY_MS);
                                             setState(IDS.wbAvail, true);
                                             await wait(START_HANDSHAKE_DELAY_MS);
                                             setState(IDS.wbTrans, true);
                                        
                                             started = await waitForChargingState(START_VERIFY_TIMEOUT_MS);
                                           }
                                        
                                           // --- ERGEBNIS-AUSWERTUNG ---
                                           if (started) {
                                             console.log(`[EV3 Master] Wallbox start verified successfully (${reason}).`);
                                             ev3Notify(`🔋 EV3-Ladung gestartet via ${reason} mit 6A`);
                                           } else {
                                             const finalStatus = getState(IDS.wbStat)?.val;
                                             console.error(
                                               `[EV3 Master] Start failed after retry. Wallbox did not reach 'Charging' state (Status: ${finalStatus}). Reverting wbTrans.`,
                                             );
                                             setState(IDS.wbTrans, false);
                                             ev3Notify(
                                               `⚠️ EV3 Ladestart fehlgeschlagen: Wallbox reagiert nicht (Status: ${finalStatus})`,
                                               4,
                                             );
                                           }
                                         } catch (e) {
                                           console.error(`[EV3 Master] Error during start sequence: ${e.message}`);
                                           setState(IDS.wbTrans, false);
                                           ev3Notify(`❌ Fehler bei Ladestart-Sequenz: ${e.message}`, 5);
                                         } finally {
                                           isStartingSequenceActive = false;
                                         }
                                        }
                                        
                                        /**
                                        * [NEU] forceStopCharging()
                                        * Versucht, den Ladevorgang zu beenden, selbst wenn der Status "hängt".
                                        * Nutzt den Verfügbarkeitswechsel (Availability-Toggle) als letzten Ausweg.
                                        * Diese Funktion wird aufgerufen, wenn `transactionActive` auf `false` gesetzt wurde,
                                        * die Wallbox aber immer noch den Status `Charging` meldet.
                                        */
                                        async function forceStopCharging() {
                                         // Gleichzeitige Ausführung verhindern
                                         if (isForceStopping) {
                                           console.log("[EV3 Master] Force stop already active, skipping.");
                                           return;
                                         }
                                         isForceStopping = true;
                                         console.warn("[EV3 Master] Initiating forced charging stop sequence.");
                                        
                                         try {
                                           // Versuch 1: Sende transactionActive: false erneut
                                           // Standardweg, um eine Session zu beenden.
                                           console.log("[EV3 Master] Force stop attempt 1: Setting wbTrans to false.");
                                           setState(IDS.wbTrans, false);
                                           // Warten, damit die Wallbox Zeit zur Verarbeitung hat.
                                           await wait(FORCE_STOP_RETRY_DELAY_MS);
                                        
                                           if (getState(IDS.wbStat)?.val === "Charging") {
                                             console.warn(
                                               "[EV3 Master] Force stop attempt 1 failed. Proceeding with Availability Toggle.",
                                             );
                                             // Versuch 2: Verfügbarkeitswechsel (Availability-Toggle)
                                             console.log("[EV3 Master] Force stop attempt 2: Toggling wbAvail (false -> true).");
                                             setState(IDS.wbAvail, false);
                                             // Nach dem Deaktivieren warten
                                             await wait(FORCE_STOP_AVAILABILITY_TOGGLE_DELAY_MS);
                                             setState(IDS.wbAvail, true);
                                             // Vor dem erneuten Stopp-Versuch warten
                                             await wait(FORCE_STOP_AVAILABILITY_TOGGLE_DELAY_MS);
                                             setState(IDS.wbTrans, false);
                                             ev3Notify("⚠️ Wallbox Ladestop erzwungen (Availability Reset)", 3);
                                             console.log("[EV3 Master] Force stop attempt 2 completed.");
                                           } else {
                                             console.log("[EV3 Master] Forced charging stop successful on first attempt.");
                                           }
                                         } catch (e) {
                                           console.error(`[EV3 Master] Error during forced charging stop: ${e.message}`);
                                           ev3Notify(`❌ Fehler beim erzwungenen Ladestopp: ${e.message}`, 5);
                                         } finally {
                                           isForceStopping = false;
                                           if (stopTimer) {
                                             clearTimeout(stopTimer);
                                             stopTimer = null;
                                             console.log("[EV3 Master] Cleared stopTimer after forced stop.");
                                           }
                                           if (startRefreshTimer) {
                                             clearTimeout(startRefreshTimer);
                                             startRefreshTimer = null;
                                           }
                                           setState(IDS.u_power, 0, true);
                                           if (startZeitLaden) {
                                             const stats = updateChargeStatistics(Date.now() - startZeitLaden);
                                             setState(IDS.u_timeDay, stats.totalMinToday, true);
                                             ev3Notify(
                                               `❌ Ladung beendet (forced). Heute geladen: ${stats.formattedTime} (+approx. ${stats.kmToday} km)`,
                                               1,
                                             );
                                             startZeitLaden = null;
                                             setState(IDS.u_startTs, 0, true);
                                           }
                                           if (originalMinSoc !== null) {
                                             setState(IDS.minSocSet, Math.max(0, originalMinSoc));
                                             ev3Notify(`🔌 Hausbatterie MinSoc auf ${originalMinSoc}% nach erzwungenem Stop eingestellt`);
                                             originalMinSoc = null;
                                             setState(IDS.u_origSoc, 0, true);
                                           }
                                           if (stopRefreshTimer) clearTimeout(stopRefreshTimer);
                                           stopRefreshTimer = setTimeout(() => {
                                             console.log(
                                               "[EV3 Master] Triggering post-stop vehicle refresh for final SoC and statistics.",
                                             );
                                             if (existsState(IDS.refreshCar)) {
                                               setState(IDS.refreshCar, true);
                                             }
                                             stopRefreshTimer = null;
                                           }, STOP_REFRESH_DELAY_MS);
                                         }
                                        }
                                        
                                        function ev3Notify(text, prio = 1, spoken = null) {
                                         sendTo("telegram", "send", { text: text }); // An Telegram senden
                                        
                                         // Token dynamisch auflösen für erhöhte Robustheit
                                         const gotifyToken = getState("0_userdata.0.gotifytoken.iobroker")?.val;
                                         if (gotifyToken) {
                                           const url = `https://mygotify.meistermopper.de/message?token=${gotifyToken}`;
                                           const payload = { title: "EV3 Master", message: text, priority: prio };
                                           const options = {
                                             headers: { "Content-Type": "application/json" },
                                             timeout: 10000,
                                           };
                                        
                                           httpPost(url, payload, options, (err) => {
                                             if (err) console.error(`[EV3 Master] Gotify Error: ${err}`);
                                           });
                                         } else {
                                           console.warn("[EV3 Master] Gotify Token ist nicht definiert oder leer.");
                                         }
                                        
                                         // Sprachausgabe tagsüber
                                         if (compareTime("08:00", "20:00", "between")) {
                                           // Wenn ein spezieller Sprechtext übergeben wurde (spoken), nutzen wir diesen.
                                           // Andernfalls nehmen wir den Standardtext.
                                           let voice = spoken || text;
                                           voice = voice
                                             .replace(/%/g, " Prozent")
                                             .replace(/SOC/gi, "Ladestand")
                                             .replace(/🔋|🔌|⚠️|🚗|❌/g, "");
                                           // sendTo("sayit", "say", { text: voice });
                                         }
                                        }
                                        
                                        // --- 4. INTELLIGENTE PV-GLÄTTUNG (EMA) ---
                                        
                                        /**
                                        * Berechnet die durchschnittliche PV-Leistung zur Stabilisierung der Regelung.
                                        * Reagiert schnell auf Einbrüche, langsam auf Erhöhungen.
                                        */
                                        schedule("* * * * *", async () => {
                                         const { pvPower: current, pvAverage: oldAvg, batSoc } = getPowerMetrics();
                                         const inertia = Number(getState(IDS.u_smooth)?.val) || 10;
                                        
                                         let alpha;
                                         if (current < oldAvg) {
                                           // ABFALL: Wenn die Hausbatterie voll ist (>85%), langsamer reagieren (0,2 statt 0,5).
                                           // Dies verhindert unnötige Ladestopps bei kurzen Wolken.
                                           alpha = batSoc > 85 ? 0.2 : 0.5;
                                         } else {
                                           // ANSTIEG: Wenn die Hausbatterie noch leer ist (<50%), länger auf stabile Sonne warten.
                                           // Wenn die Batterie voll ist, die Sonne schneller nutzen.
                                           const dynamicInertia = batSoc > 75 ? Math.max(2, inertia / 2) : inertia;
                                           alpha = 1 / dynamicInertia;
                                         }
                                        
                                         const newAvg = alpha * current + (1 - alpha) * oldAvg;
                                         setState(IDS.pvAverage, Math.round(newAvg), true);
                                        });
                                        
                                        // --- 5. AUTOMATISIERUNGS-LOGIK (PV-ÜBERSCHUSS) ---
                                        
                                        /**
                                        * Überwacht den PV-Durchschnitt und schaltet das Laden automatisch,
                                        * vorausgesetzt der Automatik-Schalter in VIS ist aktiv.
                                        */
                                        function checkPvAutomation() {
                                         const isAuto = !!getState(IDS.u_auto)?.val; // Automatik-Schalter
                                         const { pvAverage: mittel, batSoc, evSoc } = getPowerMetrics(); // Aktuelle Leistungswerte
                                        
                                         // Abbrechen, wenn Wallbox offline ist
                                         const isConnected = !!getState(IDS.wbConn)?.val;
                                         if (!isConnected && mittel > PV_START_LIMIT) {
                                           if (!hasWarnedOcppOffline) {
                                             console.warn("[EV3 Master] Start not possible: Wallbox connection missing (OCPP Offline)");
                                             hasWarnedOcppOffline = true;
                                           }
                                         }
                                         if (!isAuto || !isConnected) return;
                                        
                                         const isTransActive = !!getState(IDS.wbTrans)?.val;
                                         const _wbStatus = getState(IDS.wbStat)?.val;
                                         const limitCar = getState(IDS.targetSocSrv)?.val || 100;
                                        
                                         // Diagnose-Log für ausreichenden Überschuss, falls nicht geladen wird
                                         //if (!isTransActive && (mittel > (PV_START_LIMIT - 500))) {
                                         //    console.log(`[EV3 Master] Status: ${wbStatus} | PV-Avg: ${mittel}W | Bat-SoC: ${batSoc}% | EV-SoC: ${evSoc}% / Ziel: ${limitCar}%`);
                                         //}
                                        
                                         // START: Genug Sonne (>4.6kW) und Hausspeicher gut gefüllt (>75%)
                                         if (
                                           !isTransActive &&
                                           !isStartingSequenceActive &&
                                           mittel > PV_START_LIMIT &&
                                           batSoc > 75 &&
                                           evSoc < limitCar
                                         ) {
                                           triggerStartSequence("PV-Automatik");
                                         }
                                        
                                         // STOP: Überschuss sinkt unter Ladeleistung (Pause)
                                         // oder Ladeziel erreicht
                                         // oder Wallbox-Verbindung verloren (oben durch !isConnected abgefangen, hier als Redundanz)
                                         else if (isTransActive && (mittel < PV_STOP_LIMIT || evSoc >= limitCar)) {
                                           // Detailliertes Logging des Stopp-Grunds
                                           let reason = "";
                                           if (mittel < PV_STOP_LIMIT) reason = `Insufficient PV power (${mittel}W < ${PV_STOP_LIMIT}W)`;
                                           else if (evSoc >= limitCar)
                                             reason = `Vehicle charging target reached (${evSoc}% >= ${limitCar}%)`;
                                        
                                           if (reason) {
                                             console.log(`[EV3 Master] Automatically stopped: ${reason}`);
                                           }
                                        
                                           setState(IDS.wbTrans, false);
                                           //ev3Notify("EV3 charging ended");
                                         }
                                        }
                                        
                                        // Trigger bei neuen PV-Werten sowie bei Wiederherstellung der Verbindung
                                        on({ id: IDS.pvAverage, change: "ne" }, checkPvAutomation);
                                        on({ id: IDS.soc, change: "ne" }, checkPvAutomation);
                                        on({ id: IDS.wbConn, val: true, change: "ne" }, checkPvAutomation);
                                        
                                        // [NEU] Listener für den Datenpunkt wbTrans.
                                        // Dieser Listener ist entscheidend für das Erkennen und Beheben von "hängenden" Ladestatuse.
                                        // Wenn `wbTrans` auf `false` wechselt (Stopp-Befehl gesendet), prüfen wir nach einer Verzögerung
                                        // von 10 Sekunden, ob `wbStat` immer noch `Charging` ist, und rufen in diesem Fall `forceStopCharging()` auf.
                                        on({ id: IDS.wbTrans, change: "ne" }, (obj) => {
                                         if (obj.state.val === false) {
                                           // 10 Sekunden Verzögerung, um der Wallbox Zeit zur Verarbeitung zu geben
                                           setTimeout(async () => {
                                             if (getState(IDS.wbStat)?.val === "Charging") {
                                               console.warn(
                                                 "[EV3 Master] Wallbox hängt im Status 'Charging' trotz beendeter Transaktion. Erzwinge Stopp.",
                                               );
                                               await forceStopCharging();
                                             }
                                           }, 10000);
                                         }
                                        });
                                        // --- 6. ÜBERWACHUNG & STATISTIKEN ---
                                        
                                        /**
                                        * Erfasst die Ladedauer und stellt die Leistungsanzeige ein.
                                        * Erfasst die Ladedauer, stellt die Leistungsanzeige ein und schützt die Hausbatterie
                                        * vor Entladung beim manuellen Laden.
                                        * Berechnet die Statistiken für den aktuellen oder abgeschlossenen Ladevorgang.
                                        */
                                        function updateChargeStatistics(sessionDurationMs) {
                                         const dauerMin = Math.max(1, Math.round(sessionDurationMs / 60000)); // Mindestens 1 Minute zählen
                                         const currentTotalMin = getState(IDS.u_timeDay)?.val || 0;
                                         const totalMinToday = currentTotalMin + dauerMin;
                                        
                                         // Energie und Reichweite
                                         const energyKWh = (totalMinToday / 60) * (FIXED_CHARGE_W / 1000);
                                         const month = new Date().getMonth();
                                         const rangeMax = month >= 3 && month <= 10 ? RANGE_SUMMER : RANGE_WINTER;
                                         const kmToday = Math.round((energyKWh / CAR_CAPACITY_KWH) * rangeMax);
                                        
                                         const h = Math.floor(totalMinToday / 60);
                                         const m = totalMinToday % 60;
                                         const formattedTime = h > 0 ? `${h}:${m < 10 ? `0${m}` : m} Std` : `${m} Min`;
                                        
                                         return {
                                           totalMinToday,
                                           formattedTime,
                                           kmToday,
                                           spokenTime: h > 0 ? `${h} Stunden, ${m} Minuten` : `${m} Minuten`,
                                         };
                                        }
                                        
                                        // Haupt-Überwacher für den Wallbox-Status (z. B. Charging, Preparing, SuspendedEV...)
                                        on({ id: IDS.wbStat, change: "ne" }, (obj) => {
                                         const status = String(obj.state.val);
                                         const isAuto = !!getState(IDS.u_auto)?.val;
                                        
                                         // FALL 1: Das Fahrzeug lädt aktiv
                                         if (status === "Charging") {
                                           // Falls ein Stop-Timer läuft (kurze Ladeunterbrechung durch z.B. Wolken):
                                           // Timer abbrechen, da die Ladung direkt fortgesetzt wurde (Hiccup-Schutz).
                                           if (stopTimer) {
                                             clearTimeout(stopTimer);
                                             stopTimer = null;
                                             console.log("[EV3 Master] Short interruption ended, resuming charge");
                                             return;
                                           }
                                        
                                           // Startzeitpunkt merken, sofern noch nicht gesetzt (für die tägliche Statistik)
                                           if (!startZeitLaden) {
                                             startZeitLaden = Date.now();
                                             setState(IDS.u_startTs, startZeitLaden, true);
                                        
                                             // 75 Sek. nach Ladestart Fahrzeug aufwecken, um verbleibende Ladedauer & SoC präzise abzurufen
                                             if (startRefreshTimer) clearTimeout(startRefreshTimer);
                                             startRefreshTimer = setTimeout(() => {
                                               if (getState(IDS.wbStat)?.val === "Charging") {
                                                 console.log(
                                                   "[EV3 Master] Triggering post-start vehicle refresh to update SoC and remaining time.",
                                                 );
                                                 if (existsState(IDS.refreshCar)) {
                                                   setState(IDS.refreshCar, true);
                                                 }
                                               }
                                               startRefreshTimer = null;
                                             }, START_REFRESH_DELAY_MS);
                                           }
                                        
                                           // Da die Box starr mit 6A lädt (3 Phasen * 230V * 6A = ~3,96 kW), setzen wir den festen Watt-Wert zur Anzeige
                                           setState(IDS.u_power, FIXED_CHARGE_W, true);
                                        
                                           // BATTERIESCHUTZ bei manuellem Laden (Automatik AUS):
                                           // Verhindert, dass der Hausspeicher entleert wird, indem der Min-SoC der Hausbatterie temporär
                                           // auf den aktuellen SoC-Wert gesetzt wird.
                                           if (!isAuto && originalMinSoc === null) {
                                             originalMinSoc = getState(IDS.minSocRead)?.val;
                                             setState(IDS.u_origSoc, originalMinSoc, true);
                                             const currentBatSoc = getState(IDS.batSocPV)?.val;
                                             // MinSoc sicherheitshalber nicht unter 0 setzen
                                             setState(IDS.minSocSet, Math.max(0, currentBatSoc));
                                             const msg = `Manuelles Laden gestartet. MinSoc auf ${currentBatSoc}% (vorher: ${originalMinSoc}%)`;
                                             console.log(`[EV3 Master] ${msg}`);
                                             ev3Notify(`🔋 ${msg}`);
                                           }
                                         }
                                        
                                         // FALL 2: Das Fahrzeug stoppt (durch Kabel ziehen, Auto-Ladeziel erreicht, Pause durch PV-Regelung etc.)
                                         else if (
                                           startZeitLaden &&
                                           (status === "Finishing" ||
                                             status === "Available" ||
                                             status === "SuspendedEV" ||
                                             status === "SuspendedEVSE")
                                         ) {
                                           if (startRefreshTimer) {
                                             clearTimeout(startRefreshTimer);
                                             startRefreshTimer = null;
                                           }
                                           // Um bei kurzen Unterbrechungen nicht sofort abzubrechen, warten wir 45 Sekunden (Entprellzeit).
                                           // Wechselt der Status in dieser Zeit zurück auf "Charging", läuft die Ladung oben nahtlos weiter.
                                           if (stopTimer) clearTimeout(stopTimer);
                                        
                                           stopTimer = setTimeout(() => {
                                             // 1. Batterieschutz aufheben: Min-SoC des Hausspeichers wieder auf den ursprünglichen Wert zurückstellen
                                             if (!isAuto && originalMinSoc !== null) {
                                               setState(IDS.minSocSet, Math.max(0, originalMinSoc));
                                               const msg = `EV3 Manuelles Laden beendet. Hausbatterie MinSoc wieder auf ${originalMinSoc}% gestellt`;
                                               console.log(`[EV3 Master] ${msg}`);
                                               ev3Notify(`🔌 ${msg}`);
                                               originalMinSoc = null;
                                               setState(IDS.u_origSoc, 0, true);
                                             }
                                        
                                             // 2. Ladestatistik berechnen (Dauer in Min, geladene kWh und hinzugewonnene Kilometer je nach Jahreszeit)
                                             const stats = updateChargeStatistics(Date.now() - startZeitLaden);
                                             setState(IDS.u_timeDay, stats.totalMinToday, true);
                                        
                                             // 3. Prüfen, ob das Auto das Ladeziel erreicht hat:
                                             // Vergleicht den aktuellen SoC des Kia mit dem eingestellten Ladeziel der Wallbox/des Fahrzeugs
                                             const evSoc = Number(getState(IDS.soc)?.val) || 0;
                                             const targetSoc = Number(getState(IDS.targetSocSrv)?.val) || 100;
                                        
                                             let msgText = `❌ EV3 Ladung beendet. Heute geladen: ${stats.formattedTime} (+approx. ${stats.kmToday} km)`;
                                             let spokenText = `Ladung beendet. Heute geladen: ${stats.spokenTime}. Reichweite approx. ${stats.kmToday} Kilometer.`;
                                        
                                             // Wenn das Ladeziel erreicht wurde, ergänzen wir die Benachrichtigungen
                                             if (evSoc >= targetSoc) {
                                               msgText += ` - Das Ladeziel von ${targetSoc}% wurde erreicht`;
                                               spokenText += ` Das Ladeziel von ${targetSoc} Prozent wurde erreicht`;
                                             }
                                        
                                             // Benachrichtigung senden (Telegram, Gotify, Alexa/SayIt)
                                             ev3Notify(msgText, 1, spokenText);
                                        
                                             // 4. Ladevariablen zurücksetzen & Ladevorgang sauber abschließen
                                             startZeitLaden = null;
                                             setState(IDS.u_startTs, 0, true);
                                             setState(IDS.u_power, 0, true);
                                        
                                             // WICHTIG: Setzt transactionActive auf false, damit die Wallbox die Transaktion beendet
                                             // und die VIS-Visualisierung nicht mehr "lädt..." anzeigt (Logikfehler-Behebung).
                                             setState(IDS.wbTrans, false);
                                        
                                             stopTimer = null;
                                        
                                             // Finalen Status nach Ladeende vom Fahrzeug abrufen
                                             if (stopRefreshTimer) clearTimeout(stopRefreshTimer);
                                             stopRefreshTimer = setTimeout(() => {
                                               console.log(
                                                 "[EV3 Master] Triggering post-stop vehicle refresh for final SoC and statistics.",
                                               );
                                               if (existsState(IDS.refreshCar)) {
                                                 setState(IDS.refreshCar, true);
                                               }
                                               stopRefreshTimer = null;
                                             }, STOP_REFRESH_DELAY_MS);
                                           }, DEBOUNCE_STOP_MS);
                                         }
                                        });
                                        
                                        // Dynamischer Batterieschutz bei manuellem Laden:
                                        // Erhöht sich der SoC des Heimspeichers während des manuellen Ladens (z. B. durch PV-Ertrag),
                                        // wird der Min-SoC des Wechselrichters entsprechend nach oben angepasst.
                                        on({ id: IDS.batSocPV, change: "ne" }, (obj) => {
                                         const isAuto = !!getState(IDS.u_auto)?.val;
                                         const isCharging = getState(IDS.wbStat)?.val === "Charging";
                                        
                                         if (!isAuto && isCharging) {
                                           const newSoc = Number(obj.state.val) || 0;
                                           const oldSoc = Number(obj.oldState?.val) || 0;
                                        
                                           if (newSoc > oldSoc) {
                                             if (originalMinSoc === null) {
                                               originalMinSoc = getState(IDS.minSocRead)?.val;
                                               setState(IDS.u_origSoc, originalMinSoc, true);
                                             }
                                             setState(IDS.minSocSet, Math.max(0, newSoc));
                                             console.log(
                                               `[EV3 Master] Manual charging: Home battery SoC increased from ${oldSoc}% to ${newSoc}%. Updated MinSoC to ${newSoc}%.`,
                                             );
                                           }
                                         }
                                        });
                                        
                                        // --- 7. ZUSÄTZLICHE FUNKTIONEN ---
                                        
                                        /**
                                        * Verbindungs-Watchdog: Überwacht die Erreichbarkeit der Wallbox.
                                        * Meldet Statusänderungen (Anti-Spam) und löst nach 3 Min. Offline-Zeit einen Reconnect über den UniFi-AP aus.
                                        */
                                        on({ id: IDS.wbConn, change: "ne" }, (obj) => {
                                         const isConnected = !!obj.state.val;
                                        
                                         if (!isConnected) {
                                           // Nur beim ersten Mal warnen
                                           if (!wasOfflineReported) {
                                             //console.warn("[EV3 Master] Wallbox-Verbindung verloren. Reconnect-Timer (3 Min) gestartet.");
                                             wasOfflineReported = true;
                                           }
                                           // Reconnect-Timer starten (falls nicht schon einer läuft)
                                           if (!reconnectTimer) {
                                             reconnectTimer = setTimeout(() => {
                                               //console.log("[EV3 Master] Führe WLAN-Neuverbindung über UniFi AP aus...");
                                               setState(IDS.unifiReconnect, true);
                                               reconnectTimer = null;
                                             }, RECONNECT_WB_MS);
                                           }
                                         } else {
                                           // Wieder online: Status zurücksetzen und Timer stoppen
                                           if (wasOfflineReported) console.log("[EV3 Master] Wallbox connection restored.");
                                           wasOfflineReported = false;
                                           if (reconnectTimer) {
                                             clearTimeout(reconnectTimer);
                                             reconnectTimer = null;
                                           }
                                         }
                                        });
                                        
                                        /**
                                        * Formatiert die verbleibende Ladezeit für die Anzeige in VIS.
                                        */
                                        on({ id: IDS.remTime, change: "any" }, (obj) => {
                                         const m = obj.state.val;
                                         let t = "0:00";
                                         if (m > 0) {
                                           const hh = Math.floor(m / 60);
                                           const mm = m % 60;
                                           t = `${hh}:${mm < 10 ? `0${mm}` : mm}`;
                                         }
                                         setState(IDS.u_rest, t, true);
                                        });
                                        
                                        // Synchronisiert den VIS-Anzeige-Datenpunkt mit dem echten Ladeziel des Autos
                                        on({ id: IDS.targetSocSrv, change: "ne" }, (obj) => {
                                         console.log(`[EV3 Master] Charge target sync: Setting VIS slider to ${obj.state.val}%.`);
                                         setState(IDS.u_limit, obj.state.val, true);
                                        });
                                        
                                        // Handler für manuelle Start-Anforderungen
                                        on({ id: IDS.u_startChargeRequest, val: true, change: "any" }, () => {
                                         console.log("[EV3 Master] Manual start request received via VIS.");
                                         triggerStartSequence("VIS-Manual");
                                         setTimeout(() => {
                                           setState(IDS.u_startChargeRequest, false, true);
                                         }, 1000);
                                        });
                                        
                                        // Täglicher Reset der Ladestatistik um 02:05 Uhr
                                        schedule("5 2 * * *", () => {
                                         setState(IDS.u_timeDay, 0, true);
                                        });
                                        
                                        // Schutz der Kia 12V-Starterbatterie
                                        on({ id: IDS.bat12v, change: "ne" }, (obj) => {
                                         if (obj.state.val <= 50) ev3Notify(`⚠️ Kia 12V battery critical!`, 5);
                                        });
                                        
                                        

                                        fuzzy1955F Online
                                        fuzzy1955F Online
                                        fuzzy1955
                                        schrieb zuletzt editiert von
                                        #19

                                        @Meister-Mopper sagte:

                                        Die verbindet sich mit ws://IPdesioBroker:Port ohne Benutzername und Passwort mit dem ioBroker.

                                        Hallo Meister-Mopper,

                                        jetzt habe ich Stunden herumprobiert, aber es scheint, dass Fronius beim Wattpilot Go 11 J 2.0 mit der Firmware 42.5 die API UND OCPP deaktiviert hat.

                                        Tests mit

                                        ws://192.168.0.xxx:9220/ocpp/Wattpilot_xxxxxxxx oder 
                                        ws://192.168.0.xxx:9220/Wattpilot_xxxxxxxx oder 
                                        ws://192.168.0.xxx:9220/Wattpilot_xxxxxxxx/ocpp
                                        
                                        sudo tcpdump -i any port 9220
                                        

                                        brachten kein Ergebnis. Was tun?

                                        Smart-Home-Automation unter IOB auf RASPI5, 16GB RAM, 50GB SSD, MariaSQL, VIS-2.
                                        Anfang 2025 war ich Newbie in Sachen RaspBerry, Linux und IOB.
                                        Jetzt läuft alles konstant gut und ich gebe gern meine Erfahrungen und mein Wissen an die Forums-User/Innen weiter.
                                        Großes Danke an alle tatkräftigen Helfer im Forum!

                                        Meister MopperM 2 Antworten Letzte Antwort
                                        0
                                        • fuzzy1955F fuzzy1955

                                          @Meister-Mopper sagte:

                                          Die verbindet sich mit ws://IPdesioBroker:Port ohne Benutzername und Passwort mit dem ioBroker.

                                          Hallo Meister-Mopper,

                                          jetzt habe ich Stunden herumprobiert, aber es scheint, dass Fronius beim Wattpilot Go 11 J 2.0 mit der Firmware 42.5 die API UND OCPP deaktiviert hat.

                                          Tests mit

                                          ws://192.168.0.xxx:9220/ocpp/Wattpilot_xxxxxxxx oder 
                                          ws://192.168.0.xxx:9220/Wattpilot_xxxxxxxx oder 
                                          ws://192.168.0.xxx:9220/Wattpilot_xxxxxxxx/ocpp
                                          
                                          sudo tcpdump -i any port 9220
                                          

                                          brachten kein Ergebnis. Was tun?

                                          Meister MopperM Online
                                          Meister MopperM Online
                                          Meister Mopper
                                          Most Active
                                          schrieb zuletzt editiert von
                                          #20

                                          @fuzzy1955

                                          Nach allem, was ich lese, wird ocpp weiterhin unterstützt. Mach das Teil mal stromlos (am besten länger über Nacht).

                                          Proxmox und HA ...
                                          Ich schreibe den Code nicht mehr selbst – ich schimpfe mit der KI, bis es funktioniert.

                                          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

                                          316

                                          Online

                                          33.0k

                                          Benutzende

                                          83.7k

                                          Themen

                                          1.3m

                                          Beiträge
                                          Community
                                          Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen | Einwilligungseinstellungen
                                          ioBroker Community 2014-2026
                                          logo
                                          • Anmelden

                                          • Du hast noch kein Konto? Registrieren

                                          • Anmelden oder registrieren, um zu suchen
                                          • Erster Beitrag
                                            Letzter Beitrag
                                          0
                                          • Home
                                          • Aktuell
                                          • Ungelesen 0
                                          • Kategorien
                                          • Unreplied
                                          • Beliebt
                                          • GitHub
                                          • Docu
                                          • Hilfe