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

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

Community Forum

donate donate
  1. ioBroker Community Home
  2. Deutsch
  3. Skripten / Logik
  4. Verbesserung erfahren Blockly/Javascript/KI/AI

NEWS

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

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

  • Weihnachtsangebot 2025! 🎄
    BluefoxB
    Bluefox
    25
    1
    2.4k

Verbesserung erfahren Blockly/Javascript/KI/AI

Geplant Angeheftet Gesperrt Verschoben Skripten / Logik
48 Beiträge 11 Kommentatoren 1.2k Aufrufe 10 Watching
  • Älteste zuerst
  • Neuste zuerst
  • Meiste Stimmen
Antworten
  • In einem neuen Thema antworten
Anmelden zum Antworten
Dieses Thema wurde gelöscht. Nur Nutzer mit entsprechenden Rechten können es sehen.
  • crunchipC Offline
    crunchipC Offline
    crunchip
    Forum Testing Most Active
    schrieb am zuletzt editiert von
    #11

    Ich denke, es muss jeder selbst abschätzen ob und in wie weit er die KI dafür hernimmt. Ich behaupte mal, 70% der User können kein JavaScript. Dennoch ist durch das stetige wachsen von Iobroker und immer mehr Möglichkeiten der User gewillt dies auch zu nutzen.
    Was hab ich von iobroker, wenn ich die Hälfte nicht nutzen kann, nur weil ich nicht programmieren kann. Es sollte auch kein Zwang sein, unzählige Dinge zu erlernen, nur um Smarthome betreiben zu können.

    Letztendlich kann man viele Dinge eigenständig umsetzen, man muss sich nur zu helfen wissen. Unterm Strich, bei stetiger Nutzung lernt man ja auch etwas dabei, zumindest mancher, der sich intensiver damit befasst.
    Es hat nun mal Vor- und Nachteile.
    Hoffe es kommt nicht falsch rüber und wird verstanden, was ich damit ausdrücken wollte

    umgestiegen von Proxmox auf Unraid

    1 Antwort Letzte Antwort
    3
    • OliverIOO OliverIO

      @Asgothian

      Konkrete Beispiel wo KI 70-80% erstellt hat ist

      https://github.com/oweitman/fail2bancontrol
      Und
      https://github.com/oweitman/ioBroker.med-plan

      Klar sollte sein, das das nicht aus einem prompt heraus erstellt wurde, einige Runden notwendig waren um einzelne Features hinzuzufügen.
      Bei fail2ban hat die ki das backend/api sehr gut verstanden und es waren wenige Runden notwendig.
      Bei frontend/react mehr runden

      AsgothianA Offline
      AsgothianA Offline
      Asgothian
      Developer
      schrieb am zuletzt editiert von Asgothian
      #12

      @OliverIO sagte in Verbesserung erfahren Blockly/Javascript/KI/AI:

      Konkrete Beispiel wo KI 70-80% erstellt hat ist

      Ich fürchte wir schreiben aneinander vorbei.

      Beide Beispiele zeigen das die KI (wenn sie ordentlich angeleitet wird) eine gute Doku erzeugen kann wie eine API nutzen ist, sprich welche Aufrufe möglich sind, was deren Parameter sind, und so weiter. Das gleiche gilt für Funktionsaufrufe. Auch da kann die KI viel erklären.

      Aber wie / warum der code hinter der API / dem Aufruf funktioniert hat die KI nicht beschrieben (in den Beispielen - auch weil es nicht Ziel Deiner Doku ist. Die Doku soll ja dazu dienen das jemand die Adapter benutzen kann. Das das geht hatte ich vorher schon als unbestritten dargestellt. Das ist aber nicht das worum es @arteck und mir geht.

      Um das vielleicht noch einmal deutlich zu machen:

      Der Ablauf

      • JS Funktionen mit KI schreiben lassen um komplexe Abläufe zu realiseren
      • diese JS Funktionen dann mit KI dokumentieren zu lassen

      Führt (sofern nur bedingt wissen über JS vorhanden ist) zu Code der am Ende Unverständlich ist - man kann den 'as is' nutzen, aber zum Überarbeiten muss dann jemand viel Zeit aufwenden sich da hinein zu arbeiten. Sprich - der OP ist mit seiner KI Optimierung weiter abhängig geworden von externen Dienstleistern (menschlich oder KI) um diesen Code in der Zukunft lauffähig zu halten oder zu modifizieren.

      Ob das Sinnvoll ist wage ich zu bezweifeln.

      Alle Beispiele die Du gepostet hat bringen dazu keinerlei Argumente.

      A.

      ioBroker auf RPi4 - Hardware soweit wie möglich via Zigbee.
      "Shit don't work" ist keine Fehlermeldung, sondern ein Fluch.

      Jey CeeJ Meister MopperM 2 Antworten Letzte Antwort
      0
      • AsgothianA Asgothian

        @OliverIO sagte in Verbesserung erfahren Blockly/Javascript/KI/AI:

        Konkrete Beispiel wo KI 70-80% erstellt hat ist

        Ich fürchte wir schreiben aneinander vorbei.

        Beide Beispiele zeigen das die KI (wenn sie ordentlich angeleitet wird) eine gute Doku erzeugen kann wie eine API nutzen ist, sprich welche Aufrufe möglich sind, was deren Parameter sind, und so weiter. Das gleiche gilt für Funktionsaufrufe. Auch da kann die KI viel erklären.

        Aber wie / warum der code hinter der API / dem Aufruf funktioniert hat die KI nicht beschrieben (in den Beispielen - auch weil es nicht Ziel Deiner Doku ist. Die Doku soll ja dazu dienen das jemand die Adapter benutzen kann. Das das geht hatte ich vorher schon als unbestritten dargestellt. Das ist aber nicht das worum es @arteck und mir geht.

        Um das vielleicht noch einmal deutlich zu machen:

        Der Ablauf

        • JS Funktionen mit KI schreiben lassen um komplexe Abläufe zu realiseren
        • diese JS Funktionen dann mit KI dokumentieren zu lassen

        Führt (sofern nur bedingt wissen über JS vorhanden ist) zu Code der am Ende Unverständlich ist - man kann den 'as is' nutzen, aber zum Überarbeiten muss dann jemand viel Zeit aufwenden sich da hinein zu arbeiten. Sprich - der OP ist mit seiner KI Optimierung weiter abhängig geworden von externen Dienstleistern (menschlich oder KI) um diesen Code in der Zukunft lauffähig zu halten oder zu modifizieren.

        Ob das Sinnvoll ist wage ich zu bezweifeln.

        Alle Beispiele die Du gepostet hat bringen dazu keinerlei Argumente.

        A.

        Jey CeeJ Online
        Jey CeeJ Online
        Jey Cee
        Developer
        schrieb am zuletzt editiert von
        #13

        @Asgothian sagte in Verbesserung erfahren Blockly/Javascript/KI/AI:

        aber zum Überarbeiten muss dann jemand viel Zeit aufwenden sich da hinein zu arbeiten.

        Ehrlich, wenn du deinen Code von vor sagen wir mal 3 Jahren anschaust, versteht du dann noch auf Anhieb warum er tut was er tut oder musst du dich da wieder rein finden?
        Ich muss das jeden falls.

        Mit Hilfe von KI kann man sich das durchaus erklären lassen, warum Code tut was er tut. Das habe ich mehrfach gemacht bei Code den ich nicht geschrieben habe. Wo das an seine Grenzen stößt ist wenn der Grund nicht aus dem Code heraus zu lesen ist.
        Und da sind wir am Springenden Punkt, wenn das nicht Dokumentiert wurde, wird auch ein erfahrener Entwickler an seine Grenzen kommen. Selbst bei seinem eigenen Code.

        Wenn du das Testen willst nimm dir Code den du gut kennst, schmeiß ihn bei Chatgpt rein (das geht Kostenlos und ohne Account) und lass dir den code erklären. Dann kannst du dir selbst ein Urteil bilden.

        Persönlicher Support
        Spenden -> paypal.me/J3YC33

        1 Antwort Letzte Antwort
        3
        • AsgothianA Asgothian

          @OliverIO sagte in Verbesserung erfahren Blockly/Javascript/KI/AI:

          Konkrete Beispiel wo KI 70-80% erstellt hat ist

          Ich fürchte wir schreiben aneinander vorbei.

          Beide Beispiele zeigen das die KI (wenn sie ordentlich angeleitet wird) eine gute Doku erzeugen kann wie eine API nutzen ist, sprich welche Aufrufe möglich sind, was deren Parameter sind, und so weiter. Das gleiche gilt für Funktionsaufrufe. Auch da kann die KI viel erklären.

          Aber wie / warum der code hinter der API / dem Aufruf funktioniert hat die KI nicht beschrieben (in den Beispielen - auch weil es nicht Ziel Deiner Doku ist. Die Doku soll ja dazu dienen das jemand die Adapter benutzen kann. Das das geht hatte ich vorher schon als unbestritten dargestellt. Das ist aber nicht das worum es @arteck und mir geht.

          Um das vielleicht noch einmal deutlich zu machen:

          Der Ablauf

          • JS Funktionen mit KI schreiben lassen um komplexe Abläufe zu realiseren
          • diese JS Funktionen dann mit KI dokumentieren zu lassen

          Führt (sofern nur bedingt wissen über JS vorhanden ist) zu Code der am Ende Unverständlich ist - man kann den 'as is' nutzen, aber zum Überarbeiten muss dann jemand viel Zeit aufwenden sich da hinein zu arbeiten. Sprich - der OP ist mit seiner KI Optimierung weiter abhängig geworden von externen Dienstleistern (menschlich oder KI) um diesen Code in der Zukunft lauffähig zu halten oder zu modifizieren.

          Ob das Sinnvoll ist wage ich zu bezweifeln.

          Alle Beispiele die Du gepostet hat bringen dazu keinerlei Argumente.

          A.

          Meister MopperM Online
          Meister MopperM Online
          Meister Mopper
          schrieb am zuletzt editiert von
          #14

          @Asgothian

          Ich habe im Schweiße (meiner Füße) den Stromfluss in unserem Haus mit Blockly realisiert. Es waren etliche Fehler drin, weil das Skript alle 10 Sekunden gerechnet hat, der Smartmeter-Adaper sich aber nicht dran gehalten hat. Das Ergebnis war aber, weil annähernd brauchbar.

          Mit KI habe ich jetzt das und ich "glaube", dass das besser ist, weil ich verstehe, was da läuft.
          Wäre schön, wenn du mal drüberschaust, wie gesagt: Ich bin kein Programmierer.


          /**

          • Name: PV-Energiemaster Pro
          • Zweck: Echtzeit-Berechnung von Hausverbrauch, Autarkie & Speicher-Logik
          • inkl. täglichem Reset für saubere Grafana-Balken
            */

          // --- KONFIGURATION: IDs ---
          const ID_BATTERIE_W = 'modbus.0.inputRegisters.100.842_Battery_Power_(System)';
          const ID_PV_DACH_W = 'solax.0.data.acpower';
          const ID_SMARTMETER_W = 'smartmeter.0.1-0:16_7_0__255.value';
          const ID_SOC = 'modbus.0.inputRegisters.100.843_Battery_State_of_Charge_(System)';
          const ID_SPEICHER_KWH = '0_userdata.0.Energie.PV.Speichergroesse';

          const PATH = '0_userdata.0.Energie.PV.';

          // --- HILFSFUNKTIONEN ---

          function formatTime(minutes) {
          if (isNaN(minutes) || minutes <= 0 || !isFinite(minutes)) return "n. n.";
          const h = Math.floor(minutes / 60);
          const m = Math.floor(minutes % 60);
          return ${h}:${m < 10 ? '0' + m : m};
          }

          /**

          • Kern-Logik: Berechnet alle Energieflüsse
            */
            function calculateEnergyMaster() {
            // 1. Rohdaten abrufen
            const pvPower = getState(ID_PV_DACH_W).val || 0;
            const netPower = getState(ID_SMARTMETER_W).val || 0; // Positiv = Bezug, Negativ = Einspeisung
            const batPower = getState(ID_BATTERIE_W).val || 0; // Positiv = Laden, Negativ = Entladen
            const soc = getState(ID_SOC).val || 0;
            const speicherMax = getState(ID_SPEICHER_KWH).val || 0;

            // 2. Zerlegung der Flüsse
            const netzBezug = netPower > 0 ? netPower : 0;
            const einspeisung = netPower < 0 ? Math.abs(netPower) : 0;
            const batterieLaden = batPower > 0 ? batPower : 0;
            const batterieEntladen = batPower < 0 ? Math.abs(batPower) : 0;

            // 3. Hausverbrauch berechnen (Physikalische Korrektheit erzwingen)
            // Formel: PV + Netzbezug + Entladung - Ladung - Einspeisung
            let hausverbrauch = pvPower + netzBezug + batterieEntladen - batterieLaden - einspeisung;
            if (hausverbrauch < 0) hausverbrauch = 0;

            // 4. Autarkie & Eigenverbrauch
            let autarkie = 0;
            if (hausverbrauch > 0) {
            autarkie = Math.min(100, (1 - (netzBezug / hausverbrauch)) * 100);
            }
            const eigenverbrauch = Math.max(0, pvPower - einspeisung);

            // 5. Speicher-Restlaufzeit
            const ladestandKWh = (speicherMax * soc) / 100;
            const leerspeicherKWh = Math.max(0, speicherMax - ladestandKWh);

            let restladezeitMin = 0;
            let restladezeitSec = 0;
            let fertigUm = "n. n.";

            if (batterieLaden > 50) {
            restladezeitMin = (leerspeicherKWh / (batterieLaden / 1000)) * 60;
            restladezeitSec = (leerspeicherKWh / (batterieLaden / 1000)) * 3600;

             // "Fertig um" Uhrzeit berechnen
             let now = new Date();
             now.setSeconds(now.getSeconds() + restladezeitSec);
             fertigUm = formatDate(now, "hh:mm");
            

            }

            // 6. Datenpunkte schreiben (Echtzeit)
            setState(PATH + 'Batterieleistung', batPower, true);
            setState(PATH + 'PV_Dach', pvPower, true);
            setState(PATH + 'L1_L3', netPower, true);
            setState(PATH + 'Netzbezug', netzBezug, true);
            setState(PATH + 'Einspeisung', einspeisung, true);
            setState(PATH + 'Hausverbrauch', hausverbrauch, true);
            setState(PATH + 'Autarkie', Math.round(autarkie), true);
            setState(PATH + 'Eigenverbrauch', eigenverbrauch, true);
            setState(PATH + 'lade_kwh', parseFloat(ladestandKWh.toFixed(1)), true);
            setState(PATH + 'Restladezeit', formatTime(restladezeitMin), true);
            setState(PATH + 'Restladezeit_sec', Math.round(restladezeitSec), true);
            setState(PATH + 'Restladezeit_final', fertigUm, true);
            }

          // --- ZEITPLANUNG & TRIGGER ---

          // Trigger: Sofort rechnen bei jeder Änderung der Hardware-Werte
          on({id: [ID_PV_DACH_W, ID_SMARTMETER_W, ID_BATTERIE_W], change: "any"}, calculateEnergyMaster);

          // Zähler: Alle 10 Sekunden den Energie-Akkumulator füllen (Wh-Schritte)
          setInterval(() => {
          const haus = getState(PATH + 'Hausverbrauch').val || 0;
          const oldVal = getState(PATH + 'Tagesverbrauch').val || 0;
          // Watt / 360 = Wh-Anteil für 10 Sekunden
          setState(PATH + 'Tagesverbrauch', oldVal + (haus / 360), true);
          }, 10000);

          // Reset: Jeden Tag um 00:00 Uhr den Tagesverbrauch für Grafana nullen
          schedule("0 0 * * *", () => {
          setState(PATH + 'Tagesverbrauch', 0, true);
          //console.log("PV-Master: Tagesverbrauch für den neuen Tag auf 0 gesetzt.");
          });

          // Initialer Start beim Skript-Speichern
          calculateEnergyMaster();

          Proxmox und HA

          AsgothianA 1 Antwort Letzte Antwort
          1
          • Meister MopperM Meister Mopper

            @Asgothian

            Ich habe im Schweiße (meiner Füße) den Stromfluss in unserem Haus mit Blockly realisiert. Es waren etliche Fehler drin, weil das Skript alle 10 Sekunden gerechnet hat, der Smartmeter-Adaper sich aber nicht dran gehalten hat. Das Ergebnis war aber, weil annähernd brauchbar.

            Mit KI habe ich jetzt das und ich "glaube", dass das besser ist, weil ich verstehe, was da läuft.
            Wäre schön, wenn du mal drüberschaust, wie gesagt: Ich bin kein Programmierer.


            /**

            • Name: PV-Energiemaster Pro
            • Zweck: Echtzeit-Berechnung von Hausverbrauch, Autarkie & Speicher-Logik
            • inkl. täglichem Reset für saubere Grafana-Balken
              */

            // --- KONFIGURATION: IDs ---
            const ID_BATTERIE_W = 'modbus.0.inputRegisters.100.842_Battery_Power_(System)';
            const ID_PV_DACH_W = 'solax.0.data.acpower';
            const ID_SMARTMETER_W = 'smartmeter.0.1-0:16_7_0__255.value';
            const ID_SOC = 'modbus.0.inputRegisters.100.843_Battery_State_of_Charge_(System)';
            const ID_SPEICHER_KWH = '0_userdata.0.Energie.PV.Speichergroesse';

            const PATH = '0_userdata.0.Energie.PV.';

            // --- HILFSFUNKTIONEN ---

            function formatTime(minutes) {
            if (isNaN(minutes) || minutes <= 0 || !isFinite(minutes)) return "n. n.";
            const h = Math.floor(minutes / 60);
            const m = Math.floor(minutes % 60);
            return ${h}:${m < 10 ? '0' + m : m};
            }

            /**

            • Kern-Logik: Berechnet alle Energieflüsse
              */
              function calculateEnergyMaster() {
              // 1. Rohdaten abrufen
              const pvPower = getState(ID_PV_DACH_W).val || 0;
              const netPower = getState(ID_SMARTMETER_W).val || 0; // Positiv = Bezug, Negativ = Einspeisung
              const batPower = getState(ID_BATTERIE_W).val || 0; // Positiv = Laden, Negativ = Entladen
              const soc = getState(ID_SOC).val || 0;
              const speicherMax = getState(ID_SPEICHER_KWH).val || 0;

              // 2. Zerlegung der Flüsse
              const netzBezug = netPower > 0 ? netPower : 0;
              const einspeisung = netPower < 0 ? Math.abs(netPower) : 0;
              const batterieLaden = batPower > 0 ? batPower : 0;
              const batterieEntladen = batPower < 0 ? Math.abs(batPower) : 0;

              // 3. Hausverbrauch berechnen (Physikalische Korrektheit erzwingen)
              // Formel: PV + Netzbezug + Entladung - Ladung - Einspeisung
              let hausverbrauch = pvPower + netzBezug + batterieEntladen - batterieLaden - einspeisung;
              if (hausverbrauch < 0) hausverbrauch = 0;

              // 4. Autarkie & Eigenverbrauch
              let autarkie = 0;
              if (hausverbrauch > 0) {
              autarkie = Math.min(100, (1 - (netzBezug / hausverbrauch)) * 100);
              }
              const eigenverbrauch = Math.max(0, pvPower - einspeisung);

              // 5. Speicher-Restlaufzeit
              const ladestandKWh = (speicherMax * soc) / 100;
              const leerspeicherKWh = Math.max(0, speicherMax - ladestandKWh);

              let restladezeitMin = 0;
              let restladezeitSec = 0;
              let fertigUm = "n. n.";

              if (batterieLaden > 50) {
              restladezeitMin = (leerspeicherKWh / (batterieLaden / 1000)) * 60;
              restladezeitSec = (leerspeicherKWh / (batterieLaden / 1000)) * 3600;

               // "Fertig um" Uhrzeit berechnen
               let now = new Date();
               now.setSeconds(now.getSeconds() + restladezeitSec);
               fertigUm = formatDate(now, "hh:mm");
              

              }

              // 6. Datenpunkte schreiben (Echtzeit)
              setState(PATH + 'Batterieleistung', batPower, true);
              setState(PATH + 'PV_Dach', pvPower, true);
              setState(PATH + 'L1_L3', netPower, true);
              setState(PATH + 'Netzbezug', netzBezug, true);
              setState(PATH + 'Einspeisung', einspeisung, true);
              setState(PATH + 'Hausverbrauch', hausverbrauch, true);
              setState(PATH + 'Autarkie', Math.round(autarkie), true);
              setState(PATH + 'Eigenverbrauch', eigenverbrauch, true);
              setState(PATH + 'lade_kwh', parseFloat(ladestandKWh.toFixed(1)), true);
              setState(PATH + 'Restladezeit', formatTime(restladezeitMin), true);
              setState(PATH + 'Restladezeit_sec', Math.round(restladezeitSec), true);
              setState(PATH + 'Restladezeit_final', fertigUm, true);
              }

            // --- ZEITPLANUNG & TRIGGER ---

            // Trigger: Sofort rechnen bei jeder Änderung der Hardware-Werte
            on({id: [ID_PV_DACH_W, ID_SMARTMETER_W, ID_BATTERIE_W], change: "any"}, calculateEnergyMaster);

            // Zähler: Alle 10 Sekunden den Energie-Akkumulator füllen (Wh-Schritte)
            setInterval(() => {
            const haus = getState(PATH + 'Hausverbrauch').val || 0;
            const oldVal = getState(PATH + 'Tagesverbrauch').val || 0;
            // Watt / 360 = Wh-Anteil für 10 Sekunden
            setState(PATH + 'Tagesverbrauch', oldVal + (haus / 360), true);
            }, 10000);

            // Reset: Jeden Tag um 00:00 Uhr den Tagesverbrauch für Grafana nullen
            schedule("0 0 * * *", () => {
            setState(PATH + 'Tagesverbrauch', 0, true);
            //console.log("PV-Master: Tagesverbrauch für den neuen Tag auf 0 gesetzt.");
            });

            // Initialer Start beim Skript-Speichern
            calculateEnergyMaster();

            AsgothianA Offline
            AsgothianA Offline
            Asgothian
            Developer
            schrieb am zuletzt editiert von
            #15

            @Meister-Mopper sagte in Verbesserung erfahren Blockly/Javascript/KI/AI:

            Mit KI habe ich jetzt das und ich "glaube", dass das besser ist, weil ich verstehe, was da läuft.

            Dann erklär mir bitte vorher in deinen Worten was da läuft, was die entscheidenden DP's sind und was du erreichen willst.

            Danach kann ich da drüber schauen und eine Meinung abgeben.

            A.

            ioBroker auf RPi4 - Hardware soweit wie möglich via Zigbee.
            "Shit don't work" ist keine Fehlermeldung, sondern ein Fluch.

            ilovegymI 1 Antwort Letzte Antwort
            1
            • AsgothianA Asgothian

              @Meister-Mopper sagte in Verbesserung erfahren Blockly/Javascript/KI/AI:

              Mit KI habe ich jetzt das und ich "glaube", dass das besser ist, weil ich verstehe, was da läuft.

              Dann erklär mir bitte vorher in deinen Worten was da läuft, was die entscheidenden DP's sind und was du erreichen willst.

              Danach kann ich da drüber schauen und eine Meinung abgeben.

              A.

              ilovegymI Offline
              ilovegymI Offline
              ilovegym
              schrieb am zuletzt editiert von
              #16

              @Asgothian

              das ist doch alles beschrieben, also ich verstehe, was er will und was es machen soll.. keine Ahnung, warum du da noch eine Erklärung brauchst?
              Ich sehe dich als "alteingesessener" Programmierer, der sowas in 5min aus dem Aermel schuetteln sollte.. :)

              Die Technik schreitet voran, und im Jahre 2025 ist das benutzen von AI-Agents alltag geworden, ohne diese Hilfen würden Programmierungen wie frueher Wochen/Monate dauern. Wenn du diese nicht nutzt, deine Sache, aber du bleibst damit auf deinem Stand stehen, und alle anderen gehen vorwaerts..

              Natuerlich muss man, wie selbstgemachtes, auch die Ergebnisse von den Agents prüfen, testen, und wenn ich mir in den letzten Jahren so manche Adapter-Releases anschaue, die nicht funktioniert haben, und man sich gefragt hat, warum testet man das nicht? hätte man gleich gemerkt, dass es so nicht geht.. da kann mir keiner sagen, dass die Agents hier und heute schlecht sind.

              Ich finde die Möglichkeit, das allgemein-Wissen der Agents als Lernhilfe und Unterstützung zu nutzen, sehr wichtig.

              Mal abgesehen davon, dass es viel schneller geht; bis du die Api-Doku gelesen hast, hat der Agent schon die 12.te Version geschrieben und das Teil ist fast fertig..

              ilovegym66 – ioBroker Projekte & Automationen
              GitHub: https://github.com/Ilovegym66 | Austausch im Discord: https://discord.gg/yC65zjr5uq

              NegaleinN 1 Antwort Letzte Antwort
              2
              • ilovegymI ilovegym

                @Asgothian

                das ist doch alles beschrieben, also ich verstehe, was er will und was es machen soll.. keine Ahnung, warum du da noch eine Erklärung brauchst?
                Ich sehe dich als "alteingesessener" Programmierer, der sowas in 5min aus dem Aermel schuetteln sollte.. :)

                Die Technik schreitet voran, und im Jahre 2025 ist das benutzen von AI-Agents alltag geworden, ohne diese Hilfen würden Programmierungen wie frueher Wochen/Monate dauern. Wenn du diese nicht nutzt, deine Sache, aber du bleibst damit auf deinem Stand stehen, und alle anderen gehen vorwaerts..

                Natuerlich muss man, wie selbstgemachtes, auch die Ergebnisse von den Agents prüfen, testen, und wenn ich mir in den letzten Jahren so manche Adapter-Releases anschaue, die nicht funktioniert haben, und man sich gefragt hat, warum testet man das nicht? hätte man gleich gemerkt, dass es so nicht geht.. da kann mir keiner sagen, dass die Agents hier und heute schlecht sind.

                Ich finde die Möglichkeit, das allgemein-Wissen der Agents als Lernhilfe und Unterstützung zu nutzen, sehr wichtig.

                Mal abgesehen davon, dass es viel schneller geht; bis du die Api-Doku gelesen hast, hat der Agent schon die 12.te Version geschrieben und das Teil ist fast fertig..

                NegaleinN Offline
                NegaleinN Offline
                Negalein
                Global Moderator
                schrieb am zuletzt editiert von Negalein
                #17

                @ilovegym sagte in Verbesserung erfahren Blockly/Javascript/KI/AI:

                Die Technik schreitet voran, und im Jahre 2025 ist das benutzen von AI-Agents alltag geworden

                da gebe ich dir vollkommen recht. Mit Hilfe von ChatGPT habe ich als Anfänger es geschafft Spoolman in ioBroker zu bekommen.
                Inkl. Vis usw.
                Erklärungen, wie/weshalb/warum, waren für einen Anfänger super verständlich.

                ° Node.js & System Update ---> sudo apt update, iob stop, sudo apt full-upgrade
                ° Node.js Fixer ---> iob nodejs-update
                ° Fixer ---> iob fix

                1 Antwort Letzte Antwort
                2
                • AsgothianA Offline
                  AsgothianA Offline
                  Asgothian
                  Developer
                  schrieb am zuletzt editiert von Asgothian
                  #18

                  Nun gut.. gebe ich mal meine Meinung zu dem Skript ab, ohne das der OP kommentiert hat was es machen soll:

                  es ist Ressourcenverschwendung im grossen Stil und birgt das Risiko von Fehlberechnungen:

                  • Es läuft ein Heartbeat alle 10 Sekunden auf Daten die sich wahrscheinlich deutlich seltener Ändern.
                  • Der Heartbeat beinhaltet eine race-condition zum Trigger der Hardware-Werte, sprich je häufiger sich diese Ändern desdo öfter kann es da klemmen.
                  • Die Ergebnisse dieses Heartbeats werden in eine DB geschrieben, damit diese die dann zur Darstellung 'Aggregieren' muss (Schon die Darstellung von nur 3 Stunden führt zu einem Graph der im Zweifelsfall mehr Datenpunkte hat als das zur Darstellung benutzte Gerät Pixel bereitstellt (3 Stunden = 180 minuten = 1800 Datenpunkte)
                  • Es wird ein Multi-Trigger genutzt auf DP's die sich (wahrscheinlich - hier fehlt die Aussage des OP) quasi-Synchron ändern. In diesem werden die Werte aller beteiligten Einzel-DPs extra aus der Datenbank geholt (Risiko: Fehlberechnung wegen race-condition)
                  • Es werden Dinge berechnet die nicht genutzt werden - in jedem Trigger-Durchlauf
                  • Daten die besser im Skript in Variablen gehalten würden werden trotzdem immer über getState/setState gezogen.
                  • Auch Konstante oder semi-Konstante Werte werden bei jeder Berechnung neu gezogen.
                  • Es gibt eine mögliche race condition zwischen dem setState(PATH + 'Hausverbrauch', hausverbrauch, true); aus dem Trigger und dem const haus = getState(PATH + 'Hausverbrauch').val || 0; aus dem intervall. Wenn die Zeitlich ungünstig zusammen fallen dann wird der 'alte' Verbrauch gelesen, weil das setState nicht abgeschlossen ist.

                  Es ist aus meiner Sicht ein wunderbares Beispiel dafür wie die KI etwas liefert was prinzipiell geht, aber wenn man genau hinschaut doch klemmt.

                  A.
                  Nachtrag:
                  Ja, das ist ein relativ hartes Urteil. Ich halte das Skript für nicht gut. Und nein, dafür kann der OP nichts. Ohne weitergehendes Programmierwissen sind diese Probleme nicht ohne weiteres zu erkennen.

                  ioBroker auf RPi4 - Hardware soweit wie möglich via Zigbee.
                  "Shit don't work" ist keine Fehlermeldung, sondern ein Fluch.

                  Meister MopperM 1 Antwort Letzte Antwort
                  2
                  • liv-in-skyL Offline
                    liv-in-skyL Offline
                    liv-in-sky
                    schrieb am zuletzt editiert von liv-in-sky
                    #19

                    ich finde es gut, sich mit ki und iobroker zu beschäftigen - iobroker ist eine hausautomatisierung und es sollte für user einfach sein, alles zu realisieren, was man sich vorstellt - ohne sich lange mit programmierung zu beschäftigen. man sollte ki momentan noch nicht als allwissend verstehen, aber auch nicht in den boden reden. wenn das projekt iobroker weiterhin erfolgreich sein möchte, wird man um ki nicht "rumkommen".

                    stattdessen wäre es wohl besser eine empfehlungsliste oder sowas zu machen: z.b.

                    • beginne nicht großen (langen) code zu generieren, sondern benutze es anfangs für funktionen
                    • evtl kann man eine liste erstellen wie oben erwähnt (achte darauf, das du den heartbeat nicht zu hoch setzt, .....
                    • was sind empfohlende ki's (claude code, gemini, ..) für die programmierung

                    usw

                    wenn ich mir ansehe, was openclaw kann, wird es nicht lange dauern, bis man ein system zur hausautomatisierung sehen wird - unsere adapter codes sind offenzugänglich - warum sollte ein neues "erfundenes" system das nicht nutzen können und iobroker einfach ersetzen ?

                    nach einem gelösten Thread wäre es sinnvoll dies in der Überschrift des ersten Posts einzutragen [gelöst]-... Bitte benutzt das Voting rechts unten im Beitrag wenn er euch geholfen hat. Forum-Tools: PicPick https://picpick.app/en/download/ und ScreenToGif https://www.screentogif.com/downloads.html

                    AsgothianA Jey CeeJ 2 Antworten Letzte Antwort
                    0
                    • liv-in-skyL liv-in-sky

                      ich finde es gut, sich mit ki und iobroker zu beschäftigen - iobroker ist eine hausautomatisierung und es sollte für user einfach sein, alles zu realisieren, was man sich vorstellt - ohne sich lange mit programmierung zu beschäftigen. man sollte ki momentan noch nicht als allwissend verstehen, aber auch nicht in den boden reden. wenn das projekt iobroker weiterhin erfolgreich sein möchte, wird man um ki nicht "rumkommen".

                      stattdessen wäre es wohl besser eine empfehlungsliste oder sowas zu machen: z.b.

                      • beginne nicht großen (langen) code zu generieren, sondern benutze es anfangs für funktionen
                      • evtl kann man eine liste erstellen wie oben erwähnt (achte darauf, das du den heartbeat nicht zu hoch setzt, .....
                      • was sind empfohlende ki's (claude code, gemini, ..) für die programmierung

                      usw

                      wenn ich mir ansehe, was openclaw kann, wird es nicht lange dauern, bis man ein system zur hausautomatisierung sehen wird - unsere adapter codes sind offenzugänglich - warum sollte ein neues "erfundenes" system das nicht nutzen können und iobroker einfach ersetzen ?

                      AsgothianA Offline
                      AsgothianA Offline
                      Asgothian
                      Developer
                      schrieb am zuletzt editiert von
                      #20

                      @liv-in-sky sagte in Verbesserung erfahren Blockly/Javascript/KI/AI:

                      ich finde es gut, sich mit ki und iobroker zu beschäftigen - iobroker ist eine hausautomatisierung und es sollte für user einfach sein, alles zu realisieren, was man sich vorstellt - ohne sich lange mit programmierung zu beschäftigen. man sollte ki momentan noch nicht als allwissend verstehen, aber auch nicht in den boden reden. wenn das projekt iobroker weiterhin erfolgreich sein möchte, wird man um ki nicht "rumkommen".

                      Muss man auch nicht. KI Nutzung ist durchaus an vielen Stellen Sinnvoll. Ob es aber bei der Erzeugung von User-spezifischen Automatisierungen sinnvoll ist, wo der User im zweifelsfall gerade nicht bewerten kann was da heraus gekommen ist wage ich zu bezweifeln.

                      stattdessen wäre es wohl besser eine empfehlungsliste oder sowas zu machen: z.b.

                      • beginne nicht großen (langen) code zu generieren, sondern benutze es anfangs für funktionen
                      • evtl kann man eine liste erstellen wie oben erwähnt (achte darauf, das du den heartbeat nicht zu hoch setzt, .....
                      • was sind empfohlende ki's (claude code, gemini, ..) für die programmierung

                      usw

                      Da gehe ich mit. EIne Liste was sich wo und wofür am besten eignet kann helfen. Allerdings nur wenn da auch Hinweise auf die 'häufigsten Fehler' dabei sind.

                      wenn ich mir ansehe, was openclaw kann, wird es nicht lange dauern, bis man ein system zur hausautomatisierung sehen wird - unsere adapter codes sind offenzugänglich - warum sollte ein neues "erfundenes" system das nicht nutzen können und iobroker einfach ersetzen ?

                      Da bin ich eher skeptisch. Wenn ich mir anschaue was OpenClaw bisher so kann warte ich nur darauf das dieses System schlecht konfiguriert so grossen Schaden anrichtet das

                      • der Gesetzgeber einschreitet
                      • die Platformen einschreiten und die Nutzung von KI Agenten auf der Platform unter Strafe stellen (i.e. wenn Wir Platformbetreiber heraus finden das du User KI Agenten auf unserer Platform nutzt dann bist du nicht mehr User unserer Platform)
                      • das Risiko es zu nutzen zu gross wird
                      • es von der 'dunklen Seite' der Gesellschaft ausgenutzt wird.

                      ioBroker auf RPi4 - Hardware soweit wie möglich via Zigbee.
                      "Shit don't work" ist keine Fehlermeldung, sondern ein Fluch.

                      liv-in-skyL 1 Antwort Letzte Antwort
                      0
                      • liv-in-skyL liv-in-sky

                        ich finde es gut, sich mit ki und iobroker zu beschäftigen - iobroker ist eine hausautomatisierung und es sollte für user einfach sein, alles zu realisieren, was man sich vorstellt - ohne sich lange mit programmierung zu beschäftigen. man sollte ki momentan noch nicht als allwissend verstehen, aber auch nicht in den boden reden. wenn das projekt iobroker weiterhin erfolgreich sein möchte, wird man um ki nicht "rumkommen".

                        stattdessen wäre es wohl besser eine empfehlungsliste oder sowas zu machen: z.b.

                        • beginne nicht großen (langen) code zu generieren, sondern benutze es anfangs für funktionen
                        • evtl kann man eine liste erstellen wie oben erwähnt (achte darauf, das du den heartbeat nicht zu hoch setzt, .....
                        • was sind empfohlende ki's (claude code, gemini, ..) für die programmierung

                        usw

                        wenn ich mir ansehe, was openclaw kann, wird es nicht lange dauern, bis man ein system zur hausautomatisierung sehen wird - unsere adapter codes sind offenzugänglich - warum sollte ein neues "erfundenes" system das nicht nutzen können und iobroker einfach ersetzen ?

                        Jey CeeJ Online
                        Jey CeeJ Online
                        Jey Cee
                        Developer
                        schrieb am zuletzt editiert von
                        #21

                        @liv-in-sky sagte in Verbesserung erfahren Blockly/Javascript/KI/AI:

                        wenn ich mir ansehe, was openclaw kann, wird es nicht lange dauern, bis man ein system zur hausautomatisierung sehen wird - unsere adapter codes sind offenzugänglich - warum sollte ein neues "erfundenes" system das nicht nutzen können und iobroker einfach ersetzen ?

                        Sicher das geht jetzt schon. Nur weil es geht ist es nicht gleich Sinnvoll.
                        Was für mich nach wie vor dagegen Spricht:

                        • Ressourcen Verschwendung
                        • Wiederholungsgenauigkeit nicht gegeben: man kann 5 mal das selbe rein werfen und 5 verschiedene Ergebnisse bekommen.

                        @asgothian hat hier schon ein Punkt das was raus kommt kann gut aussehen ohne es zu sein.
                        Ich denke hier muss man Unterscheiden zwischen Einzelfall und breiter Masse. Es gibt Fehler die treten bei einem von 100 Benutzern auf, wenn das 1000 nutzen ist das schlecht. Wenn es einer nutzt merkt er das vielleicht nie.
                        Und das passiert auch bei code der von Menschen geschrieben wird.

                        Ich Denke wir sollten damit Pragmatisch umgehen und erstmal bewerten (lernen) wann ist das vertretbar und wann nicht.

                        Persönlicher Support
                        Spenden -> paypal.me/J3YC33

                        1 Antwort Letzte Antwort
                        0
                        • OliverIOO Offline
                          OliverIOO Offline
                          OliverIO
                          schrieb am zuletzt editiert von OliverIO
                          #22

                          Ich habe das Skript mit dem folgenden, prompt mal bei ChatGPT hineingeworfen

                          Bitte analysiere zunächst das Folgende Skript
                          Dann liefere mir bitte das Skript ergänzt mit Kommentaren, so dass es ein Anfänger verstehen kann. In einem weiteren Schritt liefere mir bitte ein verbessertes Skript mit der Analyse, warum du welche Punkte verbessert hast
                          

                          Als Ergebnis kam folgendes

                          1. Analyse: Warum „das Folgende“ so vermutlich nicht klappt

                          Ich gehe davon aus, dass das ein ioBroker-JavaScript (JS-Adapter) Script ist (wegen getState(), setState(), on(), schedule(), formatDate()).

                          A) Harte Syntaxfehler (Script startet dann gar nicht)
                          1. formatTime() gibt einen Template-String ohne Backticks zurück

                          return ${h}:${m < 10 ? '0' + m : m};

                          Das ist ungültiges JavaScript. Template-Literals brauchen Backticks:

                          return ${h}:${m < 10 ? '0' + m : m};

                          2.	In deinem Code sind fremde Textzeilen mitten im JS:
                          
                          •	Copy to Clipboard
                          •	Bullet-Lines wie •  // "Fertig um" Uhrzeit berechnen
                          

                          Das sind keine Kommentare, sondern normaler Text → Syntax Error.
                          Wenn du das behalten willst, muss es als Kommentar geschrieben werden (// ... oder /* ... */).

                          B) Logik-/Robustheitsprobleme (läuft ggf., aber liefert falsche/instabile Werte)
                          3. formatDate() ist nicht Standard-JS
                          Im ioBroker-JS-Adapter existiert formatDate() typischerweise, aber nur dort. Wenn du das Script woanders testest, knallt es. (In ioBroker ist es ok.)
                          4. Trigger reagieren nicht auf SOC/Speichergröße
                          Du berechnest Restladezeit mit soc und speicherMax, aber dein on() triggert nur auf:

                          •	PV, Smartmeter, Batterie-Leistung
                          

                          Wenn sich SOC ändert (häufig), kann die Anzeige „hinterherhinken“.

                          5.	Akkumulator „Tagesverbrauch“: fest 10s gerechnet, aber ohne Drift-Korrektur
                          

                          setInterval(..., 10000) ist nicht garantiert exakt. Wenn das System hängt, stimmt der Tageswert langsam nicht mehr. Besser: echte Zeitdifferenz messen.
                          6. getState(...).val || 0 kann echte 0 überdecken?
                          Hier ist es okay (0 bleibt 0), aber bei NaN/Strings wird es stillschweigend zu 0. Besser: sauber parsen und validieren.
                          7. Einheiten & Vorzeichen sind nur korrekt, wenn deine Quellen wirklich so liefern

                          •	netPower: positiv Bezug, negativ Einspeisung (du schreibst das so)
                          •	batPower: positiv Laden, negativ Entladen (du schreibst das so)
                          

                          Wenn ein Gerät das anders liefert, sind alle Flüsse „gespiegelt“.

                          ⸻

                          1. Dein Skript – ergänzt und so kommentiert, dass Anfänger es verstehen

                          Ich habe nur die offensichtlichen Syntaxprobleme repariert und Kommentare ergänzt, ohne die Struktur stark zu verändern.

                          /*
                          Name: PV-Energiemaster Pro
                          Zweck: Echtzeit-Berechnung von Hausverbrauch, Autarkie & Speicher-Logik
                          inkl. täglichem Reset für saubere Grafana-Balken
                          */

                          // --- KONFIGURATION: IDs ---
                          const ID_BATTERIE_W = 'modbus.0.inputRegisters.100.842_Battery_Power_(System)';
                          const ID_PV_DACH_W = 'solax.0.data.acpower';
                          const ID_SMARTMETER_W = 'smartmeter.0.1-0:16_7_0__255.value';
                          const ID_SOC = 'modbus.0.inputRegisters.100.843_Battery_State_of_Charge_(System)';
                          const ID_SPEICHER_KWH = '0_userdata.0.Energie.PV.Speichergroesse';

                          const PATH = '0_userdata.0.Energie.PV.';

                          // --- HILFSFUNKTIONEN ---

                          /**

                          • Wandelt Minuten (z.B. 85.3) in "1:25" um.
                          • Wenn Minuten nicht sinnvoll sind, geben wir "n. n." zurück.
                            */
                            function formatTime(minutes) {
                            if (isNaN(minutes) || minutes <= 0 || !isFinite(minutes)) return "n. n.";

                          const h = Math.floor(minutes / 60);
                          const m = Math.floor(minutes % 60);

                          // WICHTIG: Template-String braucht Backticks: ...
                          return ${h}:${m < 10 ? '0' + m : m};
                          }

                          /**

                          • Kern-Logik: Berechnet alle Energieflüsse
                            */
                            function calculateEnergyMaster() {
                            // 1) Rohdaten abrufen (Watt bzw. % / kWh)
                            const pvPower = getState(ID_PV_DACH_W).val || 0;

                          // Smartmeter: + = Netzbezug, - = Einspeisung (laut Kommentar)
                          const netPower = getState(ID_SMARTMETER_W).val || 0;

                          // Batterie: + = Laden, - = Entladen (laut Kommentar)
                          const batPower = getState(ID_BATTERIE_W).val || 0;

                          const soc = getState(ID_SOC).val || 0; // Prozent
                          const speicherMax = getState(ID_SPEICHER_KWH).val || 0; // kWh

                          // 2) Zerlegung der Flüsse in „nur positive“ Teilgrößen
                          const netzBezug = netPower > 0 ? netPower : 0;
                          const einspeisung = netPower < 0 ? Math.abs(netPower) : 0;

                          const batterieLaden = batPower > 0 ? batPower : 0;
                          const batterieEntladen = batPower < 0 ? Math.abs(batPower) : 0;

                          // 3) Hausverbrauch berechnen (physikalisch konsistent)
                          // Idee: Alles was ins Haus "rein kommt" minus alles was "raus geht"
                          // Formel: PV + Netzbezug + Batterie-Entladung - Batterie-Ladung - Einspeisung
                          let hausverbrauch = pvPower + netzBezug + batterieEntladen - batterieLaden - einspeisung;
                          if (hausverbrauch < 0) hausverbrauch = 0;

                          // 4) Autarkie & Eigenverbrauch
                          // Autarkie: wie viel % des Hausverbrauchs NICHT aus dem Netz kommt
                          let autarkie = 0;
                          if (hausverbrauch > 0) {
                          autarkie = Math.min(100, (1 - (netzBezug / hausverbrauch)) * 100);
                          }

                          // Eigenverbrauch: PV-Leistung, die nicht eingespeist wird (vereinfacht)
                          const eigenverbrauch = Math.max(0, pvPower - einspeisung);

                          // 5) Speicher-Restlaufzeit (wie lange bis Akku voll, wenn er lädt)
                          const ladestandKWh = (speicherMax * soc) / 100;
                          const leerspeicherKWh = Math.max(0, speicherMax - ladestandKWh);

                          let restladezeitMin = 0;
                          let restladezeitSec = 0;
                          let fertigUm = "n. n.";

                          // Nur berechnen, wenn wirklich geladen wird (und nicht nur „Rauschen“)
                          if (batterieLaden > 50) {
                          // batterieLaden ist Watt, daher /1000 => kW
                          // Zeit in Stunden = kWh / kW
                          // dann *60 für Minuten, *3600 für Sekunden
                          restladezeitMin = (leerspeicherKWh / (batterieLaden / 1000)) * 60;
                          restladezeitSec = (leerspeicherKWh / (batterieLaden / 1000)) * 3600;

                          // "Fertig um" Uhrzeit berechnen
                          // (formatDate ist im ioBroker-JS-Adapter verfügbar)
                          let now = new Date();
                          now.setSeconds(now.getSeconds() + restladezeitSec);
                          fertigUm = formatDate(now, "hh:mm");
                          

                          }

                          // 6) Datenpunkte schreiben (Echtzeit)
                          setState(PATH + 'Batterieleistung', batPower, true);
                          setState(PATH + 'PV_Dach', pvPower, true);
                          setState(PATH + 'L1_L3', netPower, true);
                          setState(PATH + 'Netzbezug', netzBezug, true);
                          setState(PATH + 'Einspeisung', einspeisung, true);
                          setState(PATH + 'Hausverbrauch', hausverbrauch, true);
                          setState(PATH + 'Autarkie', Math.round(autarkie), true);
                          setState(PATH + 'Eigenverbrauch', eigenverbrauch, true);

                          setState(PATH + 'lade_kwh', parseFloat(ladestandKWh.toFixed(1)), true);
                          setState(PATH + 'Restladezeit', formatTime(restladezeitMin), true);
                          setState(PATH + 'Restladezeit_sec', Math.round(restladezeitSec), true);
                          setState(PATH + 'Restladezeit_final', fertigUm, true);
                          }

                          // --- ZEITPLANUNG & TRIGGER ---

                          // Trigger: Sofort rechnen bei jeder Änderung der Hardware-Werte
                          on(
                          { id: [ID_PV_DACH_W, ID_SMARTMETER_W, ID_BATTERIE_W], change: "any" },
                          calculateEnergyMaster
                          );

                          // Zähler: Alle 10 Sekunden den Energie-Akkumulator füllen (Wh-Schritte)
                          setInterval(() => {
                          const haus = getState(PATH + 'Hausverbrauch').val || 0;
                          const oldVal = getState(PATH + 'Tagesverbrauch').val || 0;

                          // Watt / 360 = Wh-Anteil für 10 Sekunden (weil 10s = 1/360 h)
                          setState(PATH + 'Tagesverbrauch', oldVal + (haus / 360), true);
                          }, 10000);

                          // Reset: Jeden Tag um 00:00 Uhr den Tagesverbrauch für Grafana nullen
                          schedule("0 0 * * *", () => {
                          setState(PATH + 'Tagesverbrauch', 0, true);
                          });

                          // Initialer Start beim Skript-Speichern
                          calculateEnergyMaster();

                          ⸻

                          1. Verbessertes Skript + Analyse, warum diese Punkte besser sind

                          Was ich verbessert habe (kurz & konkret)
                          1. Sauberes Einlesen von Zahlen: readNumber() verhindert NaN, Strings, null.
                          2. Trigger erweitert: SOC und Speichergröße triggern ebenfalls → Anzeigen bleiben aktuell.
                          3. Debounce: Wenn PV/Smartmeter/Batterie sehr häufig ändern, wird nicht 50×/Sek gerechnet.
                          4. Tagesverbrauch korrekt nach echter Zeitdifferenz statt „fix 10 Sekunden“ → weniger Drift.
                          5. State-Initialisierung (setObjectNotExists) optional, aber extrem hilfreich, damit Grafana/Objekte sauber sind.
                          6. Schutz gegen Division durch 0 / unrealistische Werte (z.B. Speichergröße 0).

                          ⸻

                          Verbessertes Skript (robuster & „produktionsnäher“)

                          /*
                          PV-Energiemaster Pro (improved)

                          • Robustere Zahlenverarbeitung
                          • Aktuellere Trigger
                          • Debounce gegen Rechen-Spam
                          • Tagesverbrauch über echte Zeitdifferenz
                            */

                          const ID_BATTERIE_W = 'modbus.0.inputRegisters.100.842_Battery_Power_(System)';
                          const ID_PV_DACH_W = 'solax.0.data.acpower';
                          const ID_SMARTMETER_W = 'smartmeter.0.1-0:16_7_0__255.value';
                          const ID_SOC = 'modbus.0.inputRegisters.100.843_Battery_State_of_Charge_(System)';
                          const ID_SPEICHER_KWH = '0_userdata.0.Energie.PV.Speichergroesse';

                          const PATH = '0_userdata.0.Energie.PV.';

                          // -------------------- Hilfsfunktionen --------------------

                          /** Liest einen Datenpunkt als Zahl und liefert bei Problemen defaultValue zurück. */
                          function readNumber(id, defaultValue = 0) {
                          const st = getState(id);
                          const v = st ? st.val : defaultValue;
                          const n = Number(v);
                          return Number.isFinite(n) ? n : defaultValue;
                          }

                          /** Wie zuvor: Minuten -> "h:mm" */
                          function formatTime(minutes) {
                          if (!Number.isFinite(minutes) || minutes <= 0) return "n. n.";
                          const h = Math.floor(minutes / 60);
                          const m = Math.floor(minutes % 60);
                          return ${h}:${m < 10 ? '0' + m : m};
                          }

                          /** Kleiner Debounce: fasst viele Änderungen zusammen und rechnet max. alle X ms. */
                          function debounce(fn, waitMs) {
                          let t = null;
                          return function () {
                          if (t) clearTimeout(t);
                          t = setTimeout(() => fn(), waitMs);
                          };
                          }

                          // -------------------- (Optional) State-Objekte anlegen --------------------
                          // Vorteil: Du siehst die States sauber im Objektbaum, inkl. Typ/Unit/Role.
                          // Wenn du das nicht willst, kannst du diesen Block weglassen.
                          function ensureStates() {
                          setObjectNotExists(PATH + 'Batterieleistung', { type: 'state', common: { name: 'Batterieleistung', type: 'number', role: 'value.power', unit: 'W', read: true, write: true }, native: {} });
                          setObjectNotExists(PATH + 'PV_Dach', { type: 'state', common: { name: 'PV Dach', type: 'number', role: 'value.power', unit: 'W', read: true, write: true }, native: {} });
                          setObjectNotExists(PATH + 'L1_L3', { type: 'state', common: { name: 'Netzleistung', type: 'number', role: 'value.power', unit: 'W', read: true, write: true }, native: {} });
                          setObjectNotExists(PATH + 'Netzbezug', { type: 'state', common: { name: 'Netzbezug', type: 'number', role: 'value.power', unit: 'W', read: true, write: true }, native: {} });
                          setObjectNotExists(PATH + 'Einspeisung', { type: 'state', common: { name: 'Einspeisung', type: 'number', role: 'value.power', unit: 'W', read: true, write: true }, native: {} });
                          setObjectNotExists(PATH + 'Hausverbrauch', { type: 'state', common: { name: 'Hausverbrauch', type: 'number', role: 'value.power', unit: 'W', read: true, write: true }, native: {} });
                          setObjectNotExists(PATH + 'Autarkie', { type: 'state', common: { name: 'Autarkie', type: 'number', role: 'value', unit: '%', read: true, write: true }, native: {} });
                          setObjectNotExists(PATH + 'Eigenverbrauch', { type: 'state', common: { name: 'Eigenverbrauch', type: 'number', role: 'value.power', unit: 'W', read: true, write: true }, native: {} });
                          setObjectNotExists(PATH + 'lade_kwh', { type: 'state', common: { name: 'Ladestand', type: 'number', role: 'value.energy', unit: 'kWh', read: true, write: true }, native: {} });
                          setObjectNotExists(PATH + 'Restladezeit', { type: 'state', common: { name: 'Restladezeit', type: 'string', role: 'text', read: true, write: true }, native: {} });
                          setObjectNotExists(PATH + 'Restladezeit_sec', { type: 'state', common: { name: 'Restladezeit (s)', type: 'number', role: 'value', unit: 's', read: true, write: true }, native: {} });
                          setObjectNotExists(PATH + 'Restladezeit_final',{ type: 'state', common:{ name:'Fertig um', type:'string', role:'text', read:true, write:true }, native:{} });
                          setObjectNotExists(PATH + 'Tagesverbrauch', { type: 'state', common: { name: 'Tagesverbrauch', type: 'number', role: 'value.energy', unit: 'Wh', read: true, write: true }, native: {} });
                          }

                          ensureStates();

                          // -------------------- Kernlogik --------------------

                          function calculateEnergyMaster() {
                          // 1) Rohdaten (robust eingelesen)
                          const pvPower = readNumber(ID_PV_DACH_W, 0);
                          const netPower = readNumber(ID_SMARTMETER_W, 0); // + Bezug, - Einspeisung
                          const batPower = readNumber(ID_BATTERIE_W, 0); // + Laden, - Entladen
                          const soc = readNumber(ID_SOC, 0); // %
                          const speicherMax = readNumber(ID_SPEICHER_KWH, 0); // kWh

                          // 2) Fluss-Zerlegung
                          const netzBezug = netPower > 0 ? netPower : 0;
                          const einspeisung = netPower < 0 ? -netPower : 0;

                          const batterieLaden = batPower > 0 ? batPower : 0;
                          const batterieEntladen = batPower < 0 ? -batPower : 0;

                          // 3) Hausverbrauch
                          let hausverbrauch = pvPower + netzBezug + batterieEntladen - batterieLaden - einspeisung;
                          if (!Number.isFinite(hausverbrauch) || hausverbrauch < 0) hausverbrauch = 0;

                          // 4) Autarkie & Eigenverbrauch
                          const autarkie = hausverbrauch > 0
                          ? Math.max(0, Math.min(100, (1 - (netzBezug / hausverbrauch)) * 100))
                          : 0;

                          const eigenverbrauch = Math.max(0, pvPower - einspeisung);

                          // 5) Speicher-Restladezeit
                          const speicherOk = speicherMax > 0 && soc >= 0 && soc <= 100;

                          const ladestandKWh = speicherOk ? (speicherMax * soc) / 100 : 0;
                          const leerspeicherKWh = speicherOk ? Math.max(0, speicherMax - ladestandKWh) : 0;

                          let restladezeitMin = 0;
                          let restladezeitSec = 0;
                          let fertigUm = "n. n.";

                          if (batterieLaden > 50 && speicherOk) {
                          const ladeLeistungKW = batterieLaden / 1000;
                          // Verhindert Division durch 0
                          if (ladeLeistungKW > 0) {
                          const hours = leerspeicherKWh / ladeLeistungKW;
                          restladezeitMin = hours * 60;
                          restladezeitSec = hours * 3600;

                            const now = new Date();
                            now.setSeconds(now.getSeconds() + restladezeitSec);
                            fertigUm = formatDate(now, "hh:mm");
                          }
                          

                          }

                          // 6) Schreiben
                          setState(PATH + 'Batterieleistung', batPower, true);
                          setState(PATH + 'PV_Dach', pvPower, true);
                          setState(PATH + 'L1_L3', netPower, true);
                          setState(PATH + 'Netzbezug', netzBezug, true);
                          setState(PATH + 'Einspeisung', einspeisung, true);
                          setState(PATH + 'Hausverbrauch', hausverbrauch, true);
                          setState(PATH + 'Autarkie', Math.round(autarkie), true);
                          setState(PATH + 'Eigenverbrauch', eigenverbrauch, true);

                          setState(PATH + 'lade_kwh', Number(ladestandKWh.toFixed(1)), true);
                          setState(PATH + 'Restladezeit', formatTime(restladezeitMin), true);
                          setState(PATH + 'Restladezeit_sec', Math.round(restladezeitSec), true);
                          setState(PATH + 'Restladezeit_final', fertigUm, true);
                          }

                          // Debounced Version (z.B. 300 ms): verhindert „Rechenspam“ bei schnell flackernden Werten
                          const calculateEnergyMasterDebounced = debounce(calculateEnergyMaster, 300);

                          // -------------------- Trigger & Tagesverbrauch --------------------

                          // Trigger erweitert: auch SOC und Speichergröße
                          on(
                          { id: [ID_PV_DACH_W, ID_SMARTMETER_W, ID_BATTERIE_W, ID_SOC, ID_SPEICHER_KWH], change: "any" },
                          calculateEnergyMasterDebounced
                          );

                          // Tagesverbrauch: Wh über echte Zeitdifferenz integrieren
                          let lastTs = Date.now();

                          setInterval(() => {
                          const now = Date.now();
                          const dtSec = (now - lastTs) / 1000;
                          lastTs = now;

                          // aktuelle Leistung in W
                          const hausW = readNumber(PATH + 'Hausverbrauch', 0);
                          const oldWh = readNumber(PATH + 'Tagesverbrauch', 0);

                          // Wh = W * Stunden ; Stunden = Sekunden / 3600
                          const addWh = hausW * (dtSec / 3600);

                          setState(PATH + 'Tagesverbrauch', oldWh + addWh, true);
                          }, 10000);

                          // Reset täglich 00:00
                          schedule("0 0 * * *", () => {
                          setState(PATH + 'Tagesverbrauch', 0, true);
                          });

                          // Initial
                          calculateEnergyMaster();

                          ⸻

                          Wenn du mir sagst, welcher Adapter/Wechselrichter/Smartmeter das genau ist (SolaX + Modbus ist klar, aber Smartmeter-Typ und ob „Netzleistung“ wirklich so rum gepolt ist), kann ich dir zusätzlich eine Plausibilitätsprüfung einbauen (z.B. „Hausverbrauch darf nicht kleiner als 0 sein“, „PV >= Eigenverbrauch“, Warn-Log wenn Vorzeichen nicht passen).

                          Zum Schluss hab ich noch gefragt, für was das Skript eigentlich da ist und als Antwort kam das folgende:

                          Das Skript dient dazu, alle Energieflüsse einer Photovoltaikanlage in Echtzeit rechnerisch korrekt aufzubereiten.
                          Es berechnet aus PV-Leistung, Netzbezug/-einspeisung und Batterieladung den tatsächlichen Hausverbrauch, die Autarkiequote sowie den Eigenverbrauch.
                          Zusätzlich ermittelt es den **aktuellen Ladezustand des Speichers inkl. Restladezeit („fertig um“) **.
                          Ein integrierter Tageszähler mit Mitternachts-Reset liefert saubere Verbrauchswerte für Grafana-Diagramme.

                          Da ich mich aktuell auf der anderen Seite der Erde befinde und mehr oder weniger nur das Tablett zur Verfügung hab, könnte ich das selber nicht ausprobieren ob das lauffähig ist zu vermuten ist, dass man da noch mal 2/3 Runden nachbessern müsste

                          Ps, sehe gerade, dass das Forum Zeichen verschluckt.(bspw backticks). Auch habe ich wohl irgendetwas zu viel kopiert. Diese Hinweise einfach ignorieren.

                          Meine Adapter und Widgets
                          TVProgram, SqueezeboxRPC, OpenLiga, RSSFeed, MyTime,, pi-hole2, vis-json-template, skiinfo, vis-mapwidgets, vis-2-widgets-rssfeed
                          Links im Profil

                          HomoranH crunchipC 2 Antworten Letzte Antwort
                          0
                          • OliverIOO OliverIO

                            Ich habe das Skript mit dem folgenden, prompt mal bei ChatGPT hineingeworfen

                            Bitte analysiere zunächst das Folgende Skript
                            Dann liefere mir bitte das Skript ergänzt mit Kommentaren, so dass es ein Anfänger verstehen kann. In einem weiteren Schritt liefere mir bitte ein verbessertes Skript mit der Analyse, warum du welche Punkte verbessert hast
                            

                            Als Ergebnis kam folgendes

                            1. Analyse: Warum „das Folgende“ so vermutlich nicht klappt

                            Ich gehe davon aus, dass das ein ioBroker-JavaScript (JS-Adapter) Script ist (wegen getState(), setState(), on(), schedule(), formatDate()).

                            A) Harte Syntaxfehler (Script startet dann gar nicht)
                            1. formatTime() gibt einen Template-String ohne Backticks zurück

                            return ${h}:${m < 10 ? '0' + m : m};

                            Das ist ungültiges JavaScript. Template-Literals brauchen Backticks:

                            return ${h}:${m < 10 ? '0' + m : m};

                            2.	In deinem Code sind fremde Textzeilen mitten im JS:
                            
                            •	Copy to Clipboard
                            •	Bullet-Lines wie •  // "Fertig um" Uhrzeit berechnen
                            

                            Das sind keine Kommentare, sondern normaler Text → Syntax Error.
                            Wenn du das behalten willst, muss es als Kommentar geschrieben werden (// ... oder /* ... */).

                            B) Logik-/Robustheitsprobleme (läuft ggf., aber liefert falsche/instabile Werte)
                            3. formatDate() ist nicht Standard-JS
                            Im ioBroker-JS-Adapter existiert formatDate() typischerweise, aber nur dort. Wenn du das Script woanders testest, knallt es. (In ioBroker ist es ok.)
                            4. Trigger reagieren nicht auf SOC/Speichergröße
                            Du berechnest Restladezeit mit soc und speicherMax, aber dein on() triggert nur auf:

                            •	PV, Smartmeter, Batterie-Leistung
                            

                            Wenn sich SOC ändert (häufig), kann die Anzeige „hinterherhinken“.

                            5.	Akkumulator „Tagesverbrauch“: fest 10s gerechnet, aber ohne Drift-Korrektur
                            

                            setInterval(..., 10000) ist nicht garantiert exakt. Wenn das System hängt, stimmt der Tageswert langsam nicht mehr. Besser: echte Zeitdifferenz messen.
                            6. getState(...).val || 0 kann echte 0 überdecken?
                            Hier ist es okay (0 bleibt 0), aber bei NaN/Strings wird es stillschweigend zu 0. Besser: sauber parsen und validieren.
                            7. Einheiten & Vorzeichen sind nur korrekt, wenn deine Quellen wirklich so liefern

                            •	netPower: positiv Bezug, negativ Einspeisung (du schreibst das so)
                            •	batPower: positiv Laden, negativ Entladen (du schreibst das so)
                            

                            Wenn ein Gerät das anders liefert, sind alle Flüsse „gespiegelt“.

                            ⸻

                            1. Dein Skript – ergänzt und so kommentiert, dass Anfänger es verstehen

                            Ich habe nur die offensichtlichen Syntaxprobleme repariert und Kommentare ergänzt, ohne die Struktur stark zu verändern.

                            /*
                            Name: PV-Energiemaster Pro
                            Zweck: Echtzeit-Berechnung von Hausverbrauch, Autarkie & Speicher-Logik
                            inkl. täglichem Reset für saubere Grafana-Balken
                            */

                            // --- KONFIGURATION: IDs ---
                            const ID_BATTERIE_W = 'modbus.0.inputRegisters.100.842_Battery_Power_(System)';
                            const ID_PV_DACH_W = 'solax.0.data.acpower';
                            const ID_SMARTMETER_W = 'smartmeter.0.1-0:16_7_0__255.value';
                            const ID_SOC = 'modbus.0.inputRegisters.100.843_Battery_State_of_Charge_(System)';
                            const ID_SPEICHER_KWH = '0_userdata.0.Energie.PV.Speichergroesse';

                            const PATH = '0_userdata.0.Energie.PV.';

                            // --- HILFSFUNKTIONEN ---

                            /**

                            • Wandelt Minuten (z.B. 85.3) in "1:25" um.
                            • Wenn Minuten nicht sinnvoll sind, geben wir "n. n." zurück.
                              */
                              function formatTime(minutes) {
                              if (isNaN(minutes) || minutes <= 0 || !isFinite(minutes)) return "n. n.";

                            const h = Math.floor(minutes / 60);
                            const m = Math.floor(minutes % 60);

                            // WICHTIG: Template-String braucht Backticks: ...
                            return ${h}:${m < 10 ? '0' + m : m};
                            }

                            /**

                            • Kern-Logik: Berechnet alle Energieflüsse
                              */
                              function calculateEnergyMaster() {
                              // 1) Rohdaten abrufen (Watt bzw. % / kWh)
                              const pvPower = getState(ID_PV_DACH_W).val || 0;

                            // Smartmeter: + = Netzbezug, - = Einspeisung (laut Kommentar)
                            const netPower = getState(ID_SMARTMETER_W).val || 0;

                            // Batterie: + = Laden, - = Entladen (laut Kommentar)
                            const batPower = getState(ID_BATTERIE_W).val || 0;

                            const soc = getState(ID_SOC).val || 0; // Prozent
                            const speicherMax = getState(ID_SPEICHER_KWH).val || 0; // kWh

                            // 2) Zerlegung der Flüsse in „nur positive“ Teilgrößen
                            const netzBezug = netPower > 0 ? netPower : 0;
                            const einspeisung = netPower < 0 ? Math.abs(netPower) : 0;

                            const batterieLaden = batPower > 0 ? batPower : 0;
                            const batterieEntladen = batPower < 0 ? Math.abs(batPower) : 0;

                            // 3) Hausverbrauch berechnen (physikalisch konsistent)
                            // Idee: Alles was ins Haus "rein kommt" minus alles was "raus geht"
                            // Formel: PV + Netzbezug + Batterie-Entladung - Batterie-Ladung - Einspeisung
                            let hausverbrauch = pvPower + netzBezug + batterieEntladen - batterieLaden - einspeisung;
                            if (hausverbrauch < 0) hausverbrauch = 0;

                            // 4) Autarkie & Eigenverbrauch
                            // Autarkie: wie viel % des Hausverbrauchs NICHT aus dem Netz kommt
                            let autarkie = 0;
                            if (hausverbrauch > 0) {
                            autarkie = Math.min(100, (1 - (netzBezug / hausverbrauch)) * 100);
                            }

                            // Eigenverbrauch: PV-Leistung, die nicht eingespeist wird (vereinfacht)
                            const eigenverbrauch = Math.max(0, pvPower - einspeisung);

                            // 5) Speicher-Restlaufzeit (wie lange bis Akku voll, wenn er lädt)
                            const ladestandKWh = (speicherMax * soc) / 100;
                            const leerspeicherKWh = Math.max(0, speicherMax - ladestandKWh);

                            let restladezeitMin = 0;
                            let restladezeitSec = 0;
                            let fertigUm = "n. n.";

                            // Nur berechnen, wenn wirklich geladen wird (und nicht nur „Rauschen“)
                            if (batterieLaden > 50) {
                            // batterieLaden ist Watt, daher /1000 => kW
                            // Zeit in Stunden = kWh / kW
                            // dann *60 für Minuten, *3600 für Sekunden
                            restladezeitMin = (leerspeicherKWh / (batterieLaden / 1000)) * 60;
                            restladezeitSec = (leerspeicherKWh / (batterieLaden / 1000)) * 3600;

                            // "Fertig um" Uhrzeit berechnen
                            // (formatDate ist im ioBroker-JS-Adapter verfügbar)
                            let now = new Date();
                            now.setSeconds(now.getSeconds() + restladezeitSec);
                            fertigUm = formatDate(now, "hh:mm");
                            

                            }

                            // 6) Datenpunkte schreiben (Echtzeit)
                            setState(PATH + 'Batterieleistung', batPower, true);
                            setState(PATH + 'PV_Dach', pvPower, true);
                            setState(PATH + 'L1_L3', netPower, true);
                            setState(PATH + 'Netzbezug', netzBezug, true);
                            setState(PATH + 'Einspeisung', einspeisung, true);
                            setState(PATH + 'Hausverbrauch', hausverbrauch, true);
                            setState(PATH + 'Autarkie', Math.round(autarkie), true);
                            setState(PATH + 'Eigenverbrauch', eigenverbrauch, true);

                            setState(PATH + 'lade_kwh', parseFloat(ladestandKWh.toFixed(1)), true);
                            setState(PATH + 'Restladezeit', formatTime(restladezeitMin), true);
                            setState(PATH + 'Restladezeit_sec', Math.round(restladezeitSec), true);
                            setState(PATH + 'Restladezeit_final', fertigUm, true);
                            }

                            // --- ZEITPLANUNG & TRIGGER ---

                            // Trigger: Sofort rechnen bei jeder Änderung der Hardware-Werte
                            on(
                            { id: [ID_PV_DACH_W, ID_SMARTMETER_W, ID_BATTERIE_W], change: "any" },
                            calculateEnergyMaster
                            );

                            // Zähler: Alle 10 Sekunden den Energie-Akkumulator füllen (Wh-Schritte)
                            setInterval(() => {
                            const haus = getState(PATH + 'Hausverbrauch').val || 0;
                            const oldVal = getState(PATH + 'Tagesverbrauch').val || 0;

                            // Watt / 360 = Wh-Anteil für 10 Sekunden (weil 10s = 1/360 h)
                            setState(PATH + 'Tagesverbrauch', oldVal + (haus / 360), true);
                            }, 10000);

                            // Reset: Jeden Tag um 00:00 Uhr den Tagesverbrauch für Grafana nullen
                            schedule("0 0 * * *", () => {
                            setState(PATH + 'Tagesverbrauch', 0, true);
                            });

                            // Initialer Start beim Skript-Speichern
                            calculateEnergyMaster();

                            ⸻

                            1. Verbessertes Skript + Analyse, warum diese Punkte besser sind

                            Was ich verbessert habe (kurz & konkret)
                            1. Sauberes Einlesen von Zahlen: readNumber() verhindert NaN, Strings, null.
                            2. Trigger erweitert: SOC und Speichergröße triggern ebenfalls → Anzeigen bleiben aktuell.
                            3. Debounce: Wenn PV/Smartmeter/Batterie sehr häufig ändern, wird nicht 50×/Sek gerechnet.
                            4. Tagesverbrauch korrekt nach echter Zeitdifferenz statt „fix 10 Sekunden“ → weniger Drift.
                            5. State-Initialisierung (setObjectNotExists) optional, aber extrem hilfreich, damit Grafana/Objekte sauber sind.
                            6. Schutz gegen Division durch 0 / unrealistische Werte (z.B. Speichergröße 0).

                            ⸻

                            Verbessertes Skript (robuster & „produktionsnäher“)

                            /*
                            PV-Energiemaster Pro (improved)

                            • Robustere Zahlenverarbeitung
                            • Aktuellere Trigger
                            • Debounce gegen Rechen-Spam
                            • Tagesverbrauch über echte Zeitdifferenz
                              */

                            const ID_BATTERIE_W = 'modbus.0.inputRegisters.100.842_Battery_Power_(System)';
                            const ID_PV_DACH_W = 'solax.0.data.acpower';
                            const ID_SMARTMETER_W = 'smartmeter.0.1-0:16_7_0__255.value';
                            const ID_SOC = 'modbus.0.inputRegisters.100.843_Battery_State_of_Charge_(System)';
                            const ID_SPEICHER_KWH = '0_userdata.0.Energie.PV.Speichergroesse';

                            const PATH = '0_userdata.0.Energie.PV.';

                            // -------------------- Hilfsfunktionen --------------------

                            /** Liest einen Datenpunkt als Zahl und liefert bei Problemen defaultValue zurück. */
                            function readNumber(id, defaultValue = 0) {
                            const st = getState(id);
                            const v = st ? st.val : defaultValue;
                            const n = Number(v);
                            return Number.isFinite(n) ? n : defaultValue;
                            }

                            /** Wie zuvor: Minuten -> "h:mm" */
                            function formatTime(minutes) {
                            if (!Number.isFinite(minutes) || minutes <= 0) return "n. n.";
                            const h = Math.floor(minutes / 60);
                            const m = Math.floor(minutes % 60);
                            return ${h}:${m < 10 ? '0' + m : m};
                            }

                            /** Kleiner Debounce: fasst viele Änderungen zusammen und rechnet max. alle X ms. */
                            function debounce(fn, waitMs) {
                            let t = null;
                            return function () {
                            if (t) clearTimeout(t);
                            t = setTimeout(() => fn(), waitMs);
                            };
                            }

                            // -------------------- (Optional) State-Objekte anlegen --------------------
                            // Vorteil: Du siehst die States sauber im Objektbaum, inkl. Typ/Unit/Role.
                            // Wenn du das nicht willst, kannst du diesen Block weglassen.
                            function ensureStates() {
                            setObjectNotExists(PATH + 'Batterieleistung', { type: 'state', common: { name: 'Batterieleistung', type: 'number', role: 'value.power', unit: 'W', read: true, write: true }, native: {} });
                            setObjectNotExists(PATH + 'PV_Dach', { type: 'state', common: { name: 'PV Dach', type: 'number', role: 'value.power', unit: 'W', read: true, write: true }, native: {} });
                            setObjectNotExists(PATH + 'L1_L3', { type: 'state', common: { name: 'Netzleistung', type: 'number', role: 'value.power', unit: 'W', read: true, write: true }, native: {} });
                            setObjectNotExists(PATH + 'Netzbezug', { type: 'state', common: { name: 'Netzbezug', type: 'number', role: 'value.power', unit: 'W', read: true, write: true }, native: {} });
                            setObjectNotExists(PATH + 'Einspeisung', { type: 'state', common: { name: 'Einspeisung', type: 'number', role: 'value.power', unit: 'W', read: true, write: true }, native: {} });
                            setObjectNotExists(PATH + 'Hausverbrauch', { type: 'state', common: { name: 'Hausverbrauch', type: 'number', role: 'value.power', unit: 'W', read: true, write: true }, native: {} });
                            setObjectNotExists(PATH + 'Autarkie', { type: 'state', common: { name: 'Autarkie', type: 'number', role: 'value', unit: '%', read: true, write: true }, native: {} });
                            setObjectNotExists(PATH + 'Eigenverbrauch', { type: 'state', common: { name: 'Eigenverbrauch', type: 'number', role: 'value.power', unit: 'W', read: true, write: true }, native: {} });
                            setObjectNotExists(PATH + 'lade_kwh', { type: 'state', common: { name: 'Ladestand', type: 'number', role: 'value.energy', unit: 'kWh', read: true, write: true }, native: {} });
                            setObjectNotExists(PATH + 'Restladezeit', { type: 'state', common: { name: 'Restladezeit', type: 'string', role: 'text', read: true, write: true }, native: {} });
                            setObjectNotExists(PATH + 'Restladezeit_sec', { type: 'state', common: { name: 'Restladezeit (s)', type: 'number', role: 'value', unit: 's', read: true, write: true }, native: {} });
                            setObjectNotExists(PATH + 'Restladezeit_final',{ type: 'state', common:{ name:'Fertig um', type:'string', role:'text', read:true, write:true }, native:{} });
                            setObjectNotExists(PATH + 'Tagesverbrauch', { type: 'state', common: { name: 'Tagesverbrauch', type: 'number', role: 'value.energy', unit: 'Wh', read: true, write: true }, native: {} });
                            }

                            ensureStates();

                            // -------------------- Kernlogik --------------------

                            function calculateEnergyMaster() {
                            // 1) Rohdaten (robust eingelesen)
                            const pvPower = readNumber(ID_PV_DACH_W, 0);
                            const netPower = readNumber(ID_SMARTMETER_W, 0); // + Bezug, - Einspeisung
                            const batPower = readNumber(ID_BATTERIE_W, 0); // + Laden, - Entladen
                            const soc = readNumber(ID_SOC, 0); // %
                            const speicherMax = readNumber(ID_SPEICHER_KWH, 0); // kWh

                            // 2) Fluss-Zerlegung
                            const netzBezug = netPower > 0 ? netPower : 0;
                            const einspeisung = netPower < 0 ? -netPower : 0;

                            const batterieLaden = batPower > 0 ? batPower : 0;
                            const batterieEntladen = batPower < 0 ? -batPower : 0;

                            // 3) Hausverbrauch
                            let hausverbrauch = pvPower + netzBezug + batterieEntladen - batterieLaden - einspeisung;
                            if (!Number.isFinite(hausverbrauch) || hausverbrauch < 0) hausverbrauch = 0;

                            // 4) Autarkie & Eigenverbrauch
                            const autarkie = hausverbrauch > 0
                            ? Math.max(0, Math.min(100, (1 - (netzBezug / hausverbrauch)) * 100))
                            : 0;

                            const eigenverbrauch = Math.max(0, pvPower - einspeisung);

                            // 5) Speicher-Restladezeit
                            const speicherOk = speicherMax > 0 && soc >= 0 && soc <= 100;

                            const ladestandKWh = speicherOk ? (speicherMax * soc) / 100 : 0;
                            const leerspeicherKWh = speicherOk ? Math.max(0, speicherMax - ladestandKWh) : 0;

                            let restladezeitMin = 0;
                            let restladezeitSec = 0;
                            let fertigUm = "n. n.";

                            if (batterieLaden > 50 && speicherOk) {
                            const ladeLeistungKW = batterieLaden / 1000;
                            // Verhindert Division durch 0
                            if (ladeLeistungKW > 0) {
                            const hours = leerspeicherKWh / ladeLeistungKW;
                            restladezeitMin = hours * 60;
                            restladezeitSec = hours * 3600;

                              const now = new Date();
                              now.setSeconds(now.getSeconds() + restladezeitSec);
                              fertigUm = formatDate(now, "hh:mm");
                            }
                            

                            }

                            // 6) Schreiben
                            setState(PATH + 'Batterieleistung', batPower, true);
                            setState(PATH + 'PV_Dach', pvPower, true);
                            setState(PATH + 'L1_L3', netPower, true);
                            setState(PATH + 'Netzbezug', netzBezug, true);
                            setState(PATH + 'Einspeisung', einspeisung, true);
                            setState(PATH + 'Hausverbrauch', hausverbrauch, true);
                            setState(PATH + 'Autarkie', Math.round(autarkie), true);
                            setState(PATH + 'Eigenverbrauch', eigenverbrauch, true);

                            setState(PATH + 'lade_kwh', Number(ladestandKWh.toFixed(1)), true);
                            setState(PATH + 'Restladezeit', formatTime(restladezeitMin), true);
                            setState(PATH + 'Restladezeit_sec', Math.round(restladezeitSec), true);
                            setState(PATH + 'Restladezeit_final', fertigUm, true);
                            }

                            // Debounced Version (z.B. 300 ms): verhindert „Rechenspam“ bei schnell flackernden Werten
                            const calculateEnergyMasterDebounced = debounce(calculateEnergyMaster, 300);

                            // -------------------- Trigger & Tagesverbrauch --------------------

                            // Trigger erweitert: auch SOC und Speichergröße
                            on(
                            { id: [ID_PV_DACH_W, ID_SMARTMETER_W, ID_BATTERIE_W, ID_SOC, ID_SPEICHER_KWH], change: "any" },
                            calculateEnergyMasterDebounced
                            );

                            // Tagesverbrauch: Wh über echte Zeitdifferenz integrieren
                            let lastTs = Date.now();

                            setInterval(() => {
                            const now = Date.now();
                            const dtSec = (now - lastTs) / 1000;
                            lastTs = now;

                            // aktuelle Leistung in W
                            const hausW = readNumber(PATH + 'Hausverbrauch', 0);
                            const oldWh = readNumber(PATH + 'Tagesverbrauch', 0);

                            // Wh = W * Stunden ; Stunden = Sekunden / 3600
                            const addWh = hausW * (dtSec / 3600);

                            setState(PATH + 'Tagesverbrauch', oldWh + addWh, true);
                            }, 10000);

                            // Reset täglich 00:00
                            schedule("0 0 * * *", () => {
                            setState(PATH + 'Tagesverbrauch', 0, true);
                            });

                            // Initial
                            calculateEnergyMaster();

                            ⸻

                            Wenn du mir sagst, welcher Adapter/Wechselrichter/Smartmeter das genau ist (SolaX + Modbus ist klar, aber Smartmeter-Typ und ob „Netzleistung“ wirklich so rum gepolt ist), kann ich dir zusätzlich eine Plausibilitätsprüfung einbauen (z.B. „Hausverbrauch darf nicht kleiner als 0 sein“, „PV >= Eigenverbrauch“, Warn-Log wenn Vorzeichen nicht passen).

                            Zum Schluss hab ich noch gefragt, für was das Skript eigentlich da ist und als Antwort kam das folgende:

                            Das Skript dient dazu, alle Energieflüsse einer Photovoltaikanlage in Echtzeit rechnerisch korrekt aufzubereiten.
                            Es berechnet aus PV-Leistung, Netzbezug/-einspeisung und Batterieladung den tatsächlichen Hausverbrauch, die Autarkiequote sowie den Eigenverbrauch.
                            Zusätzlich ermittelt es den **aktuellen Ladezustand des Speichers inkl. Restladezeit („fertig um“) **.
                            Ein integrierter Tageszähler mit Mitternachts-Reset liefert saubere Verbrauchswerte für Grafana-Diagramme.

                            Da ich mich aktuell auf der anderen Seite der Erde befinde und mehr oder weniger nur das Tablett zur Verfügung hab, könnte ich das selber nicht ausprobieren ob das lauffähig ist zu vermuten ist, dass man da noch mal 2/3 Runden nachbessern müsste

                            Ps, sehe gerade, dass das Forum Zeichen verschluckt.(bspw backticks). Auch habe ich wohl irgendetwas zu viel kopiert. Diese Hinweise einfach ignorieren.

                            HomoranH Nicht stören
                            HomoranH Nicht stören
                            Homoran
                            Global Moderator Administrators
                            schrieb am zuletzt editiert von Homoran
                            #23

                            @OliverIO sagte in Verbesserung erfahren Blockly/Javascript/KI/AI:

                            dass das Forum Zeichen verschluckt.(bspw backticks)

                            wo? aber doch nicht innerhalb von code-tags!?
                            steuerzeichen werden nicht so einfach angezeigt.
                            seh ich mir an, wenn du sagst wo

                            kein Support per PN! - Fragen im Forum stellen - es gibt fast nichts, was nicht auch für andere interessant ist.

                            Benutzt das Voting rechts unten im Beitrag wenn er euch geholfen hat.

                            der Installationsfixer: curl -fsL https://iobroker.net/fix.sh | bash -

                            OliverIOO 1 Antwort Letzte Antwort
                            0
                            • HomoranH Homoran

                              @OliverIO sagte in Verbesserung erfahren Blockly/Javascript/KI/AI:

                              dass das Forum Zeichen verschluckt.(bspw backticks)

                              wo? aber doch nicht innerhalb von code-tags!?
                              steuerzeichen werden nicht so einfach angezeigt.
                              seh ich mir an, wenn du sagst wo

                              OliverIOO Offline
                              OliverIOO Offline
                              OliverIO
                              schrieb am zuletzt editiert von
                              #24

                              @Homoran

                              Suche im korrigierten Skript nach der folgenden Zeile.
                              Auch danach fehlen die Backticks.
                              Das Problem kam aber eventuell schon vom ursprünglich geposteten Code, dass das Forum diese Zeichen verschluckt hat

                              Um den Markdown von ChatGPT nicht zu verlieren, habe ich das alles direkt gepostet, ohne Code Tags. Das sind dann wohl noch ein paar andere Zeichen uminterpretiert worden.

                              // WICHTIG: Template-String braucht Backticks: ...

                              Meine Adapter und Widgets
                              TVProgram, SqueezeboxRPC, OpenLiga, RSSFeed, MyTime,, pi-hole2, vis-json-template, skiinfo, vis-mapwidgets, vis-2-widgets-rssfeed
                              Links im Profil

                              HomoranH 1 Antwort Letzte Antwort
                              0
                              • NegaleinN Offline
                                NegaleinN Offline
                                Negalein
                                Global Moderator
                                schrieb am zuletzt editiert von Negalein
                                #25

                                @asgothian @oliverio
                                & Co.

                                mich würde eure ehrliche Meinung zu meinem Spoolman-Skript intressieren.
                                Es wurde mit ChatGPT erstellt.

                                Auf Erklärungem "im Script" hab ich bewusst verzichtet. Das hab ich wärend der Erstellung bereits erfragt.

                                /**
                                 * ============================================================
                                 * ioBroker – Klipper – Spoolman Integration
                                 * ============================================================
                                 *
                                 * Version:   1.0.0
                                 * Author:    <Negalein>
                                 * License:   MIT
                                 *
                                 * Description:
                                 * - Liest aktive Spulen aus Klipper (Moonraker)
                                 * - Holt Restfilament aus Spoolman (SQLite via SSH)
                                 * - Erstellt automatisch ioBroker-States
                                 * - 🟢🟡🔴 Ampel-Logik je Spule
                                 * - Telegram-Warnungen mit Zeit- & Drucklogik
                                 * ==========================================================
                                 */
                                
                                const { exec } = require('child_process');
                                
                                /* ==========================================================
                                   KONFIGURATION
                                   ========================================================== */
                                
                                const CONFIG = {
                                  spoolman: {
                                    sshHost: 'root@10.0.1.148',
                                    dbPath: '/root/.local/share/spoolman/spoolman.db'
                                  },
                                
                                  baseState: '0_userdata.0.3DDrucker.Spoolman',
                                
                                  limits: {
                                    warn: 300,
                                    empty: 100
                                  },
                                
                                  warnTimes: {
                                    weekday: { start: 7, end: 22 },
                                    weekend: { start: 10, end: 20 }
                                  },
                                
                                  extruders: [
                                    { name: 'T0', state: 'klipper-moonraker.0.gcode_macro T0.spool_id' },
                                    { name: 'T1', state: 'klipper-moonraker.0.gcode_macro T1.spool_id' },
                                    { name: 'T2', state: 'klipper-moonraker.0.gcode_macro T2.spool_id' },
                                    { name: 'T3', state: 'klipper-moonraker.0.gcode_macro T3.spool_id' }
                                  ],
                                
                                  schedule: '*/5 * * * *'
                                };
                                
                                /* ==========================================================
                                   STATE HELFER
                                   ========================================================== */
                                
                                function ensureState(id, val, type) {
                                  if (!existsState(id)) {
                                    createState(id, val, {
                                      type,
                                      read: true,
                                      write: false,
                                      role: 'value'
                                    });
                                  } else {
                                    setState(id, val, true);
                                  }
                                }
                                
                                /* ==========================================================
                                   ZEITFENSTER
                                   ========================================================== */
                                
                                function isInWarnTime() {
                                  const now = new Date();
                                  const hour = now.getHours();
                                  const day  = now.getDay(); // 0=So
                                
                                  const isWeekend = (day === 0 || day === 6);
                                  const cfg = isWeekend ? CONFIG.warnTimes.weekend : CONFIG.warnTimes.weekday;
                                
                                  return hour >= cfg.start && hour < cfg.end;
                                }
                                
                                /* ==========================================================
                                   DRUCKSTATUS
                                   ========================================================== */
                                
                                function isPrinting() {
                                  return getState('klipper-moonraker.0.print_stats.state')?.val === 'printing';
                                }
                                
                                /* ==========================================================
                                   SPOOLMAN DB LESEN
                                   ========================================================== */
                                
                                function readSpoolman(callback) {
                                  const cmd = `
                                ssh ${CONFIG.spoolman.sshHost} "sqlite3 -json ${CONFIG.spoolman.dbPath} '
                                SELECT
                                  spool.id AS spool_id,
                                  filament.name AS name,
                                  filament.material AS material,
                                  ROUND(spool.initial_weight - spool.used_weight, 1) AS remaining
                                FROM spool
                                JOIN filament ON filament.id = spool.filament_id
                                WHERE spool.archived IS NOT 1;
                                '"
                                `;
                                
                                  exec(cmd, (err, stdout) => {
                                    if (err) {
                                      log(`Spoolman SSH Fehler: ${err.message}`, 'error');
                                      callback([]);
                                      return;
                                    }
                                
                                    try {
                                      callback(JSON.parse(stdout));
                                    } catch {
                                      log('Spoolman JSON ungültig', 'error');
                                      callback([]);
                                    }
                                  });
                                }
                                
                                /* ==========================================================
                                   STATUS HELFER
                                   ========================================================== */
                                
                                function getStatus(remaining) {
                                  if (remaining < CONFIG.limits.empty) return 'LEER';
                                  if (remaining < CONFIG.limits.warn)  return 'WARN';
                                  return 'OK';
                                }
                                
                                /* ==========================================================
                                   HAUPTLOGIK
                                   ========================================================== */
                                
                                function update() {
                                
                                  // globale VIS-States
                                  ensureState(`${CONFIG.baseState}.warnzeit_aktiv`, isInWarnTime(), 'boolean');
                                  ensureState(`${CONFIG.baseState}.druck_laeuft`, isPrinting(), 'boolean');
                                
                                  readSpoolman(spools => {
                                
                                    CONFIG.extruders.forEach((ext, index) => {
                                
                                      const slot = `${CONFIG.baseState}.aktiv.${index + 1}`;
                                      const spoolId = getState(ext.state)?.val;
                                
                                      if (!spoolId || spoolId <= 0) {
                                        ensureState(`${slot}.active`, false, 'boolean');
                                        return;
                                      }
                                
                                      const spool = spools.find(s => s.spool_id == spoolId);
                                      if (!spool) {
                                        log(`Spule ${spoolId} nicht in Spoolman gefunden`, 'warn');
                                        return;
                                      }
                                
                                      /* Basisdaten */
                                      ensureState(`${slot}.active`, true, 'boolean');
                                      ensureState(`${slot}.extruder`, ext.name, 'string');
                                      ensureState(`${slot}.spool_id`, spoolId, 'number');
                                      ensureState(`${slot}.name`, spool.name, 'string');
                                      ensureState(`${slot}.material`, spool.material, 'string');
                                      ensureState(`${slot}.remaining_weight`, spool.remaining, 'number');
                                
                                      /* Status */
                                      const status = getStatus(spool.remaining);
                                      ensureState(`${slot}.status`, status, 'string');
                                
                                      const warnId  = `${slot}.warnung`;
                                      const alarmId = `${slot}.alarm`;
                                
                                      const warned  = getState(warnId)?.val || false;
                                      const alarmed = getState(alarmId)?.val || false;
                                
                                      /* 🟡 WARN */
                                      if (
                                        status === 'WARN' &&
                                        !warned &&
                                        isInWarnTime() &&
                                        isPrinting()
                                      ) {
                                        sendTo('telegram', 'send', {
                                          text:
                                `🟡 Filament wird knapp
                                
                                🖨 Extruder: ${ext.name}
                                🧵 ${spool.name}
                                🎨 ${spool.material}
                                📦 Rest: ${spool.remaining} g`
                                        });
                                        ensureState(warnId, true, 'boolean');
                                      }
                                
                                      /* 🔴 LEER */
                                      if (
                                        status === 'LEER' &&
                                        !alarmed &&
                                        isPrinting()
                                      ) {
                                        sendTo('telegram', 'send', {
                                          text:
                                `🔴 Filament leer!
                                
                                🖨 Extruder: ${ext.name}
                                🧵 ${spool.name}
                                🎨 ${spool.material}
                                📦 Rest: ${spool.remaining} g
                                
                                ⚠️ Filament wechseln!`
                                        });
                                        ensureState(alarmId, true, 'boolean');
                                      }
                                
                                      /* Reset */
                                      if (status === 'OK') {
                                        ensureState(warnId, false, 'boolean');
                                        ensureState(alarmId, false, 'boolean');
                                      }
                                    });
                                  });
                                }
                                
                                /* ==========================================================
                                   SCHEDULER
                                   ========================================================== */
                                
                                schedule(CONFIG.schedule, update);
                                update();
                                

                                ° Node.js & System Update ---> sudo apt update, iob stop, sudo apt full-upgrade
                                ° Node.js Fixer ---> iob nodejs-update
                                ° Fixer ---> iob fix

                                1 Antwort Letzte Antwort
                                0
                                • AsgothianA Asgothian

                                  @liv-in-sky sagte in Verbesserung erfahren Blockly/Javascript/KI/AI:

                                  ich finde es gut, sich mit ki und iobroker zu beschäftigen - iobroker ist eine hausautomatisierung und es sollte für user einfach sein, alles zu realisieren, was man sich vorstellt - ohne sich lange mit programmierung zu beschäftigen. man sollte ki momentan noch nicht als allwissend verstehen, aber auch nicht in den boden reden. wenn das projekt iobroker weiterhin erfolgreich sein möchte, wird man um ki nicht "rumkommen".

                                  Muss man auch nicht. KI Nutzung ist durchaus an vielen Stellen Sinnvoll. Ob es aber bei der Erzeugung von User-spezifischen Automatisierungen sinnvoll ist, wo der User im zweifelsfall gerade nicht bewerten kann was da heraus gekommen ist wage ich zu bezweifeln.

                                  stattdessen wäre es wohl besser eine empfehlungsliste oder sowas zu machen: z.b.

                                  • beginne nicht großen (langen) code zu generieren, sondern benutze es anfangs für funktionen
                                  • evtl kann man eine liste erstellen wie oben erwähnt (achte darauf, das du den heartbeat nicht zu hoch setzt, .....
                                  • was sind empfohlende ki's (claude code, gemini, ..) für die programmierung

                                  usw

                                  Da gehe ich mit. EIne Liste was sich wo und wofür am besten eignet kann helfen. Allerdings nur wenn da auch Hinweise auf die 'häufigsten Fehler' dabei sind.

                                  wenn ich mir ansehe, was openclaw kann, wird es nicht lange dauern, bis man ein system zur hausautomatisierung sehen wird - unsere adapter codes sind offenzugänglich - warum sollte ein neues "erfundenes" system das nicht nutzen können und iobroker einfach ersetzen ?

                                  Da bin ich eher skeptisch. Wenn ich mir anschaue was OpenClaw bisher so kann warte ich nur darauf das dieses System schlecht konfiguriert so grossen Schaden anrichtet das

                                  • der Gesetzgeber einschreitet
                                  • die Platformen einschreiten und die Nutzung von KI Agenten auf der Platform unter Strafe stellen (i.e. wenn Wir Platformbetreiber heraus finden das du User KI Agenten auf unserer Platform nutzt dann bist du nicht mehr User unserer Platform)
                                  • das Risiko es zu nutzen zu gross wird
                                  • es von der 'dunklen Seite' der Gesellschaft ausgenutzt wird.
                                  liv-in-skyL Offline
                                  liv-in-skyL Offline
                                  liv-in-sky
                                  schrieb am zuletzt editiert von
                                  #26

                                  @Asgothian sagte in Verbesserung erfahren Blockly/Javascript/KI/AI:

                                  der Gesetzgeber einschreitet

                                  ich habe mich eh schon gefragt, wenn openclaw anfängt zu "hacken" oder über whatsapp zu "mobben", wer dan strafrechtlich belangt wird und wann man das erste mal davon hören wird

                                  ich dachte halt, wenn es von programmierern wie euch kommt, die das system am besten kennen, und als richtlinie die user darauf vorbereiten (evtl mit einer beschreibung für eine ki, was sie darf bzw nicht darf), wäre das halt die sicherste variante für neue user und ki-interessierte (ich spreche ja nicht von sofort, sondern einfach mal im hinterkopf zu haben).

                                  wie cool wäre es, beim öffnen eines javascript-functions-blocks gleich zugang einem agenten zu haben und zu beschreiben, was die funktion machen soll - so als spinnerei :-)

                                  natürlich habt ihr recht skeptisch zu sein und ich könnte eure argumente auch nicht einfach abtun, sondern sehe die richtigkeit darin - aber es wird kommen - KI wird nicht verschwinden - und vorallem das code-generieren wird in zukunft besser werden

                                  nach einem gelösten Thread wäre es sinnvoll dies in der Überschrift des ersten Posts einzutragen [gelöst]-... Bitte benutzt das Voting rechts unten im Beitrag wenn er euch geholfen hat. Forum-Tools: PicPick https://picpick.app/en/download/ und ScreenToGif https://www.screentogif.com/downloads.html

                                  NegaleinN 1 Antwort Letzte Antwort
                                  1
                                  • OliverIOO OliverIO

                                    @Homoran

                                    Suche im korrigierten Skript nach der folgenden Zeile.
                                    Auch danach fehlen die Backticks.
                                    Das Problem kam aber eventuell schon vom ursprünglich geposteten Code, dass das Forum diese Zeichen verschluckt hat

                                    Um den Markdown von ChatGPT nicht zu verlieren, habe ich das alles direkt gepostet, ohne Code Tags. Das sind dann wohl noch ein paar andere Zeichen uminterpretiert worden.

                                    // WICHTIG: Template-String braucht Backticks: ...

                                    HomoranH Nicht stören
                                    HomoranH Nicht stören
                                    Homoran
                                    Global Moderator Administrators
                                    schrieb am zuletzt editiert von Homoran
                                    #27

                                    @OliverIO ok, das ist korrekt

                                    hier
                                    Screenshot_20260210-185212_DuckDuckGo.jpg

                                    müsstest du die backticks mit backslash escapen

                                    Screenshot_20260210-185254_DuckDuckGo.jpg

                                    was bei dem Text natürlich eine Arbeit für Herrn Sisyphos wäre

                                    Erklärung:
                                    zwischen zwei Backticks ist `inline code`
                                    = inline code

                                    kein Support per PN! - Fragen im Forum stellen - es gibt fast nichts, was nicht auch für andere interessant ist.

                                    Benutzt das Voting rechts unten im Beitrag wenn er euch geholfen hat.

                                    der Installationsfixer: curl -fsL https://iobroker.net/fix.sh | bash -

                                    1 Antwort Letzte Antwort
                                    0
                                    • liv-in-skyL liv-in-sky

                                      @Asgothian sagte in Verbesserung erfahren Blockly/Javascript/KI/AI:

                                      der Gesetzgeber einschreitet

                                      ich habe mich eh schon gefragt, wenn openclaw anfängt zu "hacken" oder über whatsapp zu "mobben", wer dan strafrechtlich belangt wird und wann man das erste mal davon hören wird

                                      ich dachte halt, wenn es von programmierern wie euch kommt, die das system am besten kennen, und als richtlinie die user darauf vorbereiten (evtl mit einer beschreibung für eine ki, was sie darf bzw nicht darf), wäre das halt die sicherste variante für neue user und ki-interessierte (ich spreche ja nicht von sofort, sondern einfach mal im hinterkopf zu haben).

                                      wie cool wäre es, beim öffnen eines javascript-functions-blocks gleich zugang einem agenten zu haben und zu beschreiben, was die funktion machen soll - so als spinnerei :-)

                                      natürlich habt ihr recht skeptisch zu sein und ich könnte eure argumente auch nicht einfach abtun, sondern sehe die richtigkeit darin - aber es wird kommen - KI wird nicht verschwinden - und vorallem das code-generieren wird in zukunft besser werden

                                      NegaleinN Offline
                                      NegaleinN Offline
                                      Negalein
                                      Global Moderator
                                      schrieb am zuletzt editiert von
                                      #28

                                      @liv-in-sky sagte in Verbesserung erfahren Blockly/Javascript/KI/AI:

                                      wer dan strafrechtlich belangt wird

                                      der User!
                                      wenn du ein Messer gratis bekommst und damit wen tötest, wirst auch du bestraft und nicht der Schenker.

                                      ° Node.js & System Update ---> sudo apt update, iob stop, sudo apt full-upgrade
                                      ° Node.js Fixer ---> iob nodejs-update
                                      ° Fixer ---> iob fix

                                      Meister MopperM 1 Antwort Letzte Antwort
                                      0
                                      • OliverIOO OliverIO

                                        Ich habe das Skript mit dem folgenden, prompt mal bei ChatGPT hineingeworfen

                                        Bitte analysiere zunächst das Folgende Skript
                                        Dann liefere mir bitte das Skript ergänzt mit Kommentaren, so dass es ein Anfänger verstehen kann. In einem weiteren Schritt liefere mir bitte ein verbessertes Skript mit der Analyse, warum du welche Punkte verbessert hast
                                        

                                        Als Ergebnis kam folgendes

                                        1. Analyse: Warum „das Folgende“ so vermutlich nicht klappt

                                        Ich gehe davon aus, dass das ein ioBroker-JavaScript (JS-Adapter) Script ist (wegen getState(), setState(), on(), schedule(), formatDate()).

                                        A) Harte Syntaxfehler (Script startet dann gar nicht)
                                        1. formatTime() gibt einen Template-String ohne Backticks zurück

                                        return ${h}:${m < 10 ? '0' + m : m};

                                        Das ist ungültiges JavaScript. Template-Literals brauchen Backticks:

                                        return ${h}:${m < 10 ? '0' + m : m};

                                        2.	In deinem Code sind fremde Textzeilen mitten im JS:
                                        
                                        •	Copy to Clipboard
                                        •	Bullet-Lines wie •  // "Fertig um" Uhrzeit berechnen
                                        

                                        Das sind keine Kommentare, sondern normaler Text → Syntax Error.
                                        Wenn du das behalten willst, muss es als Kommentar geschrieben werden (// ... oder /* ... */).

                                        B) Logik-/Robustheitsprobleme (läuft ggf., aber liefert falsche/instabile Werte)
                                        3. formatDate() ist nicht Standard-JS
                                        Im ioBroker-JS-Adapter existiert formatDate() typischerweise, aber nur dort. Wenn du das Script woanders testest, knallt es. (In ioBroker ist es ok.)
                                        4. Trigger reagieren nicht auf SOC/Speichergröße
                                        Du berechnest Restladezeit mit soc und speicherMax, aber dein on() triggert nur auf:

                                        •	PV, Smartmeter, Batterie-Leistung
                                        

                                        Wenn sich SOC ändert (häufig), kann die Anzeige „hinterherhinken“.

                                        5.	Akkumulator „Tagesverbrauch“: fest 10s gerechnet, aber ohne Drift-Korrektur
                                        

                                        setInterval(..., 10000) ist nicht garantiert exakt. Wenn das System hängt, stimmt der Tageswert langsam nicht mehr. Besser: echte Zeitdifferenz messen.
                                        6. getState(...).val || 0 kann echte 0 überdecken?
                                        Hier ist es okay (0 bleibt 0), aber bei NaN/Strings wird es stillschweigend zu 0. Besser: sauber parsen und validieren.
                                        7. Einheiten & Vorzeichen sind nur korrekt, wenn deine Quellen wirklich so liefern

                                        •	netPower: positiv Bezug, negativ Einspeisung (du schreibst das so)
                                        •	batPower: positiv Laden, negativ Entladen (du schreibst das so)
                                        

                                        Wenn ein Gerät das anders liefert, sind alle Flüsse „gespiegelt“.

                                        ⸻

                                        1. Dein Skript – ergänzt und so kommentiert, dass Anfänger es verstehen

                                        Ich habe nur die offensichtlichen Syntaxprobleme repariert und Kommentare ergänzt, ohne die Struktur stark zu verändern.

                                        /*
                                        Name: PV-Energiemaster Pro
                                        Zweck: Echtzeit-Berechnung von Hausverbrauch, Autarkie & Speicher-Logik
                                        inkl. täglichem Reset für saubere Grafana-Balken
                                        */

                                        // --- KONFIGURATION: IDs ---
                                        const ID_BATTERIE_W = 'modbus.0.inputRegisters.100.842_Battery_Power_(System)';
                                        const ID_PV_DACH_W = 'solax.0.data.acpower';
                                        const ID_SMARTMETER_W = 'smartmeter.0.1-0:16_7_0__255.value';
                                        const ID_SOC = 'modbus.0.inputRegisters.100.843_Battery_State_of_Charge_(System)';
                                        const ID_SPEICHER_KWH = '0_userdata.0.Energie.PV.Speichergroesse';

                                        const PATH = '0_userdata.0.Energie.PV.';

                                        // --- HILFSFUNKTIONEN ---

                                        /**

                                        • Wandelt Minuten (z.B. 85.3) in "1:25" um.
                                        • Wenn Minuten nicht sinnvoll sind, geben wir "n. n." zurück.
                                          */
                                          function formatTime(minutes) {
                                          if (isNaN(minutes) || minutes <= 0 || !isFinite(minutes)) return "n. n.";

                                        const h = Math.floor(minutes / 60);
                                        const m = Math.floor(minutes % 60);

                                        // WICHTIG: Template-String braucht Backticks: ...
                                        return ${h}:${m < 10 ? '0' + m : m};
                                        }

                                        /**

                                        • Kern-Logik: Berechnet alle Energieflüsse
                                          */
                                          function calculateEnergyMaster() {
                                          // 1) Rohdaten abrufen (Watt bzw. % / kWh)
                                          const pvPower = getState(ID_PV_DACH_W).val || 0;

                                        // Smartmeter: + = Netzbezug, - = Einspeisung (laut Kommentar)
                                        const netPower = getState(ID_SMARTMETER_W).val || 0;

                                        // Batterie: + = Laden, - = Entladen (laut Kommentar)
                                        const batPower = getState(ID_BATTERIE_W).val || 0;

                                        const soc = getState(ID_SOC).val || 0; // Prozent
                                        const speicherMax = getState(ID_SPEICHER_KWH).val || 0; // kWh

                                        // 2) Zerlegung der Flüsse in „nur positive“ Teilgrößen
                                        const netzBezug = netPower > 0 ? netPower : 0;
                                        const einspeisung = netPower < 0 ? Math.abs(netPower) : 0;

                                        const batterieLaden = batPower > 0 ? batPower : 0;
                                        const batterieEntladen = batPower < 0 ? Math.abs(batPower) : 0;

                                        // 3) Hausverbrauch berechnen (physikalisch konsistent)
                                        // Idee: Alles was ins Haus "rein kommt" minus alles was "raus geht"
                                        // Formel: PV + Netzbezug + Batterie-Entladung - Batterie-Ladung - Einspeisung
                                        let hausverbrauch = pvPower + netzBezug + batterieEntladen - batterieLaden - einspeisung;
                                        if (hausverbrauch < 0) hausverbrauch = 0;

                                        // 4) Autarkie & Eigenverbrauch
                                        // Autarkie: wie viel % des Hausverbrauchs NICHT aus dem Netz kommt
                                        let autarkie = 0;
                                        if (hausverbrauch > 0) {
                                        autarkie = Math.min(100, (1 - (netzBezug / hausverbrauch)) * 100);
                                        }

                                        // Eigenverbrauch: PV-Leistung, die nicht eingespeist wird (vereinfacht)
                                        const eigenverbrauch = Math.max(0, pvPower - einspeisung);

                                        // 5) Speicher-Restlaufzeit (wie lange bis Akku voll, wenn er lädt)
                                        const ladestandKWh = (speicherMax * soc) / 100;
                                        const leerspeicherKWh = Math.max(0, speicherMax - ladestandKWh);

                                        let restladezeitMin = 0;
                                        let restladezeitSec = 0;
                                        let fertigUm = "n. n.";

                                        // Nur berechnen, wenn wirklich geladen wird (und nicht nur „Rauschen“)
                                        if (batterieLaden > 50) {
                                        // batterieLaden ist Watt, daher /1000 => kW
                                        // Zeit in Stunden = kWh / kW
                                        // dann *60 für Minuten, *3600 für Sekunden
                                        restladezeitMin = (leerspeicherKWh / (batterieLaden / 1000)) * 60;
                                        restladezeitSec = (leerspeicherKWh / (batterieLaden / 1000)) * 3600;

                                        // "Fertig um" Uhrzeit berechnen
                                        // (formatDate ist im ioBroker-JS-Adapter verfügbar)
                                        let now = new Date();
                                        now.setSeconds(now.getSeconds() + restladezeitSec);
                                        fertigUm = formatDate(now, "hh:mm");
                                        

                                        }

                                        // 6) Datenpunkte schreiben (Echtzeit)
                                        setState(PATH + 'Batterieleistung', batPower, true);
                                        setState(PATH + 'PV_Dach', pvPower, true);
                                        setState(PATH + 'L1_L3', netPower, true);
                                        setState(PATH + 'Netzbezug', netzBezug, true);
                                        setState(PATH + 'Einspeisung', einspeisung, true);
                                        setState(PATH + 'Hausverbrauch', hausverbrauch, true);
                                        setState(PATH + 'Autarkie', Math.round(autarkie), true);
                                        setState(PATH + 'Eigenverbrauch', eigenverbrauch, true);

                                        setState(PATH + 'lade_kwh', parseFloat(ladestandKWh.toFixed(1)), true);
                                        setState(PATH + 'Restladezeit', formatTime(restladezeitMin), true);
                                        setState(PATH + 'Restladezeit_sec', Math.round(restladezeitSec), true);
                                        setState(PATH + 'Restladezeit_final', fertigUm, true);
                                        }

                                        // --- ZEITPLANUNG & TRIGGER ---

                                        // Trigger: Sofort rechnen bei jeder Änderung der Hardware-Werte
                                        on(
                                        { id: [ID_PV_DACH_W, ID_SMARTMETER_W, ID_BATTERIE_W], change: "any" },
                                        calculateEnergyMaster
                                        );

                                        // Zähler: Alle 10 Sekunden den Energie-Akkumulator füllen (Wh-Schritte)
                                        setInterval(() => {
                                        const haus = getState(PATH + 'Hausverbrauch').val || 0;
                                        const oldVal = getState(PATH + 'Tagesverbrauch').val || 0;

                                        // Watt / 360 = Wh-Anteil für 10 Sekunden (weil 10s = 1/360 h)
                                        setState(PATH + 'Tagesverbrauch', oldVal + (haus / 360), true);
                                        }, 10000);

                                        // Reset: Jeden Tag um 00:00 Uhr den Tagesverbrauch für Grafana nullen
                                        schedule("0 0 * * *", () => {
                                        setState(PATH + 'Tagesverbrauch', 0, true);
                                        });

                                        // Initialer Start beim Skript-Speichern
                                        calculateEnergyMaster();

                                        ⸻

                                        1. Verbessertes Skript + Analyse, warum diese Punkte besser sind

                                        Was ich verbessert habe (kurz & konkret)
                                        1. Sauberes Einlesen von Zahlen: readNumber() verhindert NaN, Strings, null.
                                        2. Trigger erweitert: SOC und Speichergröße triggern ebenfalls → Anzeigen bleiben aktuell.
                                        3. Debounce: Wenn PV/Smartmeter/Batterie sehr häufig ändern, wird nicht 50×/Sek gerechnet.
                                        4. Tagesverbrauch korrekt nach echter Zeitdifferenz statt „fix 10 Sekunden“ → weniger Drift.
                                        5. State-Initialisierung (setObjectNotExists) optional, aber extrem hilfreich, damit Grafana/Objekte sauber sind.
                                        6. Schutz gegen Division durch 0 / unrealistische Werte (z.B. Speichergröße 0).

                                        ⸻

                                        Verbessertes Skript (robuster & „produktionsnäher“)

                                        /*
                                        PV-Energiemaster Pro (improved)

                                        • Robustere Zahlenverarbeitung
                                        • Aktuellere Trigger
                                        • Debounce gegen Rechen-Spam
                                        • Tagesverbrauch über echte Zeitdifferenz
                                          */

                                        const ID_BATTERIE_W = 'modbus.0.inputRegisters.100.842_Battery_Power_(System)';
                                        const ID_PV_DACH_W = 'solax.0.data.acpower';
                                        const ID_SMARTMETER_W = 'smartmeter.0.1-0:16_7_0__255.value';
                                        const ID_SOC = 'modbus.0.inputRegisters.100.843_Battery_State_of_Charge_(System)';
                                        const ID_SPEICHER_KWH = '0_userdata.0.Energie.PV.Speichergroesse';

                                        const PATH = '0_userdata.0.Energie.PV.';

                                        // -------------------- Hilfsfunktionen --------------------

                                        /** Liest einen Datenpunkt als Zahl und liefert bei Problemen defaultValue zurück. */
                                        function readNumber(id, defaultValue = 0) {
                                        const st = getState(id);
                                        const v = st ? st.val : defaultValue;
                                        const n = Number(v);
                                        return Number.isFinite(n) ? n : defaultValue;
                                        }

                                        /** Wie zuvor: Minuten -> "h:mm" */
                                        function formatTime(minutes) {
                                        if (!Number.isFinite(minutes) || minutes <= 0) return "n. n.";
                                        const h = Math.floor(minutes / 60);
                                        const m = Math.floor(minutes % 60);
                                        return ${h}:${m < 10 ? '0' + m : m};
                                        }

                                        /** Kleiner Debounce: fasst viele Änderungen zusammen und rechnet max. alle X ms. */
                                        function debounce(fn, waitMs) {
                                        let t = null;
                                        return function () {
                                        if (t) clearTimeout(t);
                                        t = setTimeout(() => fn(), waitMs);
                                        };
                                        }

                                        // -------------------- (Optional) State-Objekte anlegen --------------------
                                        // Vorteil: Du siehst die States sauber im Objektbaum, inkl. Typ/Unit/Role.
                                        // Wenn du das nicht willst, kannst du diesen Block weglassen.
                                        function ensureStates() {
                                        setObjectNotExists(PATH + 'Batterieleistung', { type: 'state', common: { name: 'Batterieleistung', type: 'number', role: 'value.power', unit: 'W', read: true, write: true }, native: {} });
                                        setObjectNotExists(PATH + 'PV_Dach', { type: 'state', common: { name: 'PV Dach', type: 'number', role: 'value.power', unit: 'W', read: true, write: true }, native: {} });
                                        setObjectNotExists(PATH + 'L1_L3', { type: 'state', common: { name: 'Netzleistung', type: 'number', role: 'value.power', unit: 'W', read: true, write: true }, native: {} });
                                        setObjectNotExists(PATH + 'Netzbezug', { type: 'state', common: { name: 'Netzbezug', type: 'number', role: 'value.power', unit: 'W', read: true, write: true }, native: {} });
                                        setObjectNotExists(PATH + 'Einspeisung', { type: 'state', common: { name: 'Einspeisung', type: 'number', role: 'value.power', unit: 'W', read: true, write: true }, native: {} });
                                        setObjectNotExists(PATH + 'Hausverbrauch', { type: 'state', common: { name: 'Hausverbrauch', type: 'number', role: 'value.power', unit: 'W', read: true, write: true }, native: {} });
                                        setObjectNotExists(PATH + 'Autarkie', { type: 'state', common: { name: 'Autarkie', type: 'number', role: 'value', unit: '%', read: true, write: true }, native: {} });
                                        setObjectNotExists(PATH + 'Eigenverbrauch', { type: 'state', common: { name: 'Eigenverbrauch', type: 'number', role: 'value.power', unit: 'W', read: true, write: true }, native: {} });
                                        setObjectNotExists(PATH + 'lade_kwh', { type: 'state', common: { name: 'Ladestand', type: 'number', role: 'value.energy', unit: 'kWh', read: true, write: true }, native: {} });
                                        setObjectNotExists(PATH + 'Restladezeit', { type: 'state', common: { name: 'Restladezeit', type: 'string', role: 'text', read: true, write: true }, native: {} });
                                        setObjectNotExists(PATH + 'Restladezeit_sec', { type: 'state', common: { name: 'Restladezeit (s)', type: 'number', role: 'value', unit: 's', read: true, write: true }, native: {} });
                                        setObjectNotExists(PATH + 'Restladezeit_final',{ type: 'state', common:{ name:'Fertig um', type:'string', role:'text', read:true, write:true }, native:{} });
                                        setObjectNotExists(PATH + 'Tagesverbrauch', { type: 'state', common: { name: 'Tagesverbrauch', type: 'number', role: 'value.energy', unit: 'Wh', read: true, write: true }, native: {} });
                                        }

                                        ensureStates();

                                        // -------------------- Kernlogik --------------------

                                        function calculateEnergyMaster() {
                                        // 1) Rohdaten (robust eingelesen)
                                        const pvPower = readNumber(ID_PV_DACH_W, 0);
                                        const netPower = readNumber(ID_SMARTMETER_W, 0); // + Bezug, - Einspeisung
                                        const batPower = readNumber(ID_BATTERIE_W, 0); // + Laden, - Entladen
                                        const soc = readNumber(ID_SOC, 0); // %
                                        const speicherMax = readNumber(ID_SPEICHER_KWH, 0); // kWh

                                        // 2) Fluss-Zerlegung
                                        const netzBezug = netPower > 0 ? netPower : 0;
                                        const einspeisung = netPower < 0 ? -netPower : 0;

                                        const batterieLaden = batPower > 0 ? batPower : 0;
                                        const batterieEntladen = batPower < 0 ? -batPower : 0;

                                        // 3) Hausverbrauch
                                        let hausverbrauch = pvPower + netzBezug + batterieEntladen - batterieLaden - einspeisung;
                                        if (!Number.isFinite(hausverbrauch) || hausverbrauch < 0) hausverbrauch = 0;

                                        // 4) Autarkie & Eigenverbrauch
                                        const autarkie = hausverbrauch > 0
                                        ? Math.max(0, Math.min(100, (1 - (netzBezug / hausverbrauch)) * 100))
                                        : 0;

                                        const eigenverbrauch = Math.max(0, pvPower - einspeisung);

                                        // 5) Speicher-Restladezeit
                                        const speicherOk = speicherMax > 0 && soc >= 0 && soc <= 100;

                                        const ladestandKWh = speicherOk ? (speicherMax * soc) / 100 : 0;
                                        const leerspeicherKWh = speicherOk ? Math.max(0, speicherMax - ladestandKWh) : 0;

                                        let restladezeitMin = 0;
                                        let restladezeitSec = 0;
                                        let fertigUm = "n. n.";

                                        if (batterieLaden > 50 && speicherOk) {
                                        const ladeLeistungKW = batterieLaden / 1000;
                                        // Verhindert Division durch 0
                                        if (ladeLeistungKW > 0) {
                                        const hours = leerspeicherKWh / ladeLeistungKW;
                                        restladezeitMin = hours * 60;
                                        restladezeitSec = hours * 3600;

                                          const now = new Date();
                                          now.setSeconds(now.getSeconds() + restladezeitSec);
                                          fertigUm = formatDate(now, "hh:mm");
                                        }
                                        

                                        }

                                        // 6) Schreiben
                                        setState(PATH + 'Batterieleistung', batPower, true);
                                        setState(PATH + 'PV_Dach', pvPower, true);
                                        setState(PATH + 'L1_L3', netPower, true);
                                        setState(PATH + 'Netzbezug', netzBezug, true);
                                        setState(PATH + 'Einspeisung', einspeisung, true);
                                        setState(PATH + 'Hausverbrauch', hausverbrauch, true);
                                        setState(PATH + 'Autarkie', Math.round(autarkie), true);
                                        setState(PATH + 'Eigenverbrauch', eigenverbrauch, true);

                                        setState(PATH + 'lade_kwh', Number(ladestandKWh.toFixed(1)), true);
                                        setState(PATH + 'Restladezeit', formatTime(restladezeitMin), true);
                                        setState(PATH + 'Restladezeit_sec', Math.round(restladezeitSec), true);
                                        setState(PATH + 'Restladezeit_final', fertigUm, true);
                                        }

                                        // Debounced Version (z.B. 300 ms): verhindert „Rechenspam“ bei schnell flackernden Werten
                                        const calculateEnergyMasterDebounced = debounce(calculateEnergyMaster, 300);

                                        // -------------------- Trigger & Tagesverbrauch --------------------

                                        // Trigger erweitert: auch SOC und Speichergröße
                                        on(
                                        { id: [ID_PV_DACH_W, ID_SMARTMETER_W, ID_BATTERIE_W, ID_SOC, ID_SPEICHER_KWH], change: "any" },
                                        calculateEnergyMasterDebounced
                                        );

                                        // Tagesverbrauch: Wh über echte Zeitdifferenz integrieren
                                        let lastTs = Date.now();

                                        setInterval(() => {
                                        const now = Date.now();
                                        const dtSec = (now - lastTs) / 1000;
                                        lastTs = now;

                                        // aktuelle Leistung in W
                                        const hausW = readNumber(PATH + 'Hausverbrauch', 0);
                                        const oldWh = readNumber(PATH + 'Tagesverbrauch', 0);

                                        // Wh = W * Stunden ; Stunden = Sekunden / 3600
                                        const addWh = hausW * (dtSec / 3600);

                                        setState(PATH + 'Tagesverbrauch', oldWh + addWh, true);
                                        }, 10000);

                                        // Reset täglich 00:00
                                        schedule("0 0 * * *", () => {
                                        setState(PATH + 'Tagesverbrauch', 0, true);
                                        });

                                        // Initial
                                        calculateEnergyMaster();

                                        ⸻

                                        Wenn du mir sagst, welcher Adapter/Wechselrichter/Smartmeter das genau ist (SolaX + Modbus ist klar, aber Smartmeter-Typ und ob „Netzleistung“ wirklich so rum gepolt ist), kann ich dir zusätzlich eine Plausibilitätsprüfung einbauen (z.B. „Hausverbrauch darf nicht kleiner als 0 sein“, „PV >= Eigenverbrauch“, Warn-Log wenn Vorzeichen nicht passen).

                                        Zum Schluss hab ich noch gefragt, für was das Skript eigentlich da ist und als Antwort kam das folgende:

                                        Das Skript dient dazu, alle Energieflüsse einer Photovoltaikanlage in Echtzeit rechnerisch korrekt aufzubereiten.
                                        Es berechnet aus PV-Leistung, Netzbezug/-einspeisung und Batterieladung den tatsächlichen Hausverbrauch, die Autarkiequote sowie den Eigenverbrauch.
                                        Zusätzlich ermittelt es den **aktuellen Ladezustand des Speichers inkl. Restladezeit („fertig um“) **.
                                        Ein integrierter Tageszähler mit Mitternachts-Reset liefert saubere Verbrauchswerte für Grafana-Diagramme.

                                        Da ich mich aktuell auf der anderen Seite der Erde befinde und mehr oder weniger nur das Tablett zur Verfügung hab, könnte ich das selber nicht ausprobieren ob das lauffähig ist zu vermuten ist, dass man da noch mal 2/3 Runden nachbessern müsste

                                        Ps, sehe gerade, dass das Forum Zeichen verschluckt.(bspw backticks). Auch habe ich wohl irgendetwas zu viel kopiert. Diese Hinweise einfach ignorieren.

                                        crunchipC Offline
                                        crunchipC Offline
                                        crunchip
                                        Forum Testing Most Active
                                        schrieb am zuletzt editiert von
                                        #29

                                        @OliverIO sagte in Verbesserung erfahren Blockly/Javascript/KI/AI:

                                        Ich habe das Skript mit dem folgenden, prompt mal bei ChatGPT hineingeworfen

                                        wie schon anderweitig erwähnt verwende ich gerne perplexity, das erklärt einem automatisch ohne zu fragen,
                                        erläutert die Fehler, macht Verbesserungsvorschläge und stellt folge Fragen, was man sich z.b eventuell noch wünschen/Erweitern könnte. Das finde ich ganz praktisch, denn da kommen zwischendurch mal coole Ideen herum, an die man gar nicht gedacht hat.

                                        umgestiegen von Proxmox auf Unraid

                                        NegaleinN 1 Antwort Letzte Antwort
                                        0
                                        • crunchipC crunchip

                                          @OliverIO sagte in Verbesserung erfahren Blockly/Javascript/KI/AI:

                                          Ich habe das Skript mit dem folgenden, prompt mal bei ChatGPT hineingeworfen

                                          wie schon anderweitig erwähnt verwende ich gerne perplexity, das erklärt einem automatisch ohne zu fragen,
                                          erläutert die Fehler, macht Verbesserungsvorschläge und stellt folge Fragen, was man sich z.b eventuell noch wünschen/Erweitern könnte. Das finde ich ganz praktisch, denn da kommen zwischendurch mal coole Ideen herum, an die man gar nicht gedacht hat.

                                          NegaleinN Offline
                                          NegaleinN Offline
                                          Negalein
                                          Global Moderator
                                          schrieb am zuletzt editiert von
                                          #30

                                          @crunchip sagte in Verbesserung erfahren Blockly/Javascript/KI/AI:

                                          erklärt einem automatisch ohne zu fragen, erläutert die Fehler, macht Verbesserungsvorschläge und stellt folge Fragen, was man sich z.b eventuell noch wünschen/Erweitern könnte. Das finde ich ganz praktisch, denn da kommen zwischendurch mal coole Ideen herum, an die man gar nicht gedacht hat.

                                          ähnlich ChatGPT.
                                          hab da auch Fehler erklärt bekommen, Tipps, usw.
                                          Werde mir jetzt mal Perplexity anschaun. Ist das für Scripte echt viel besser? Hab noch einige Projekte vor.

                                          ° Node.js & System Update ---> sudo apt update, iob stop, sudo apt full-upgrade
                                          ° Node.js Fixer ---> iob nodejs-update
                                          ° Fixer ---> iob fix

                                          liv-in-skyL 1 Antwort Letzte Antwort
                                          0
                                          Antworten
                                          • In einem neuen Thema antworten
                                          Anmelden zum Antworten
                                          • Älteste zuerst
                                          • Neuste zuerst
                                          • Meiste Stimmen


                                          Support us

                                          ioBroker
                                          Community Adapters
                                          Donate

                                          648

                                          Online

                                          32.6k

                                          Benutzer

                                          82.3k

                                          Themen

                                          1.3m

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

                                          • Du hast noch kein Konto? Registrieren

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