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
    376

  • 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
18 Beiträge 5 Kommentatoren 158 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 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 Offline
      fuzzy1955F Offline
      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 Offline
          fuzzy1955F Offline
          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 Offline
            fuzzy1955F Offline
            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 Offline
                fuzzy1955F Offline
                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 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 Offline
                    fuzzy1955F Offline
                    fuzzy1955
                    schrieb 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 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 Offline
                        fuzzy1955F Offline
                        fuzzy1955
                        schrieb 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 Offline
                          Meister MopperM Offline
                          Meister Mopper
                          Most Active
                          schrieb 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 Offline
                            fuzzy1955F Offline
                            fuzzy1955
                            schrieb 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 Offline
                              Meister MopperM Offline
                              Meister Mopper
                              Most Active
                              schrieb 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 Offline
                                fuzzy1955F Offline
                                fuzzy1955
                                schrieb 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 Offline
                                  Meister MopperM Offline
                                  Meister Mopper
                                  Most Active
                                  schrieb 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 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 Offline
                                    fuzzy1955F Offline
                                    fuzzy1955
                                    schrieb 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

                                    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

                                    176

                                    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