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. JavaScript
  5. Skript läuft plötzlich nicht mehr

NEWS

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

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

  • Weihnachtsangebot 2025! 🎄
    BluefoxB
    Bluefox
    25
    1
    2.1k

Skript läuft plötzlich nicht mehr

Geplant Angeheftet Gesperrt Verschoben JavaScript
28 Beiträge 6 Kommentatoren 1.3k Aufrufe 3 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.
  • hotspot_2H Online
    hotspot_2H Online
    hotspot_2
    schrieb am zuletzt editiert von
    #1

    Hallo zusammen,

    ich habe ein Javascript geschrieben das mir die aktuelle Leistung von zwei BKWs von Shelly Adaptern abruft (1 x pro Sekunde) und dann die Stromerzeugung pro Tag usw. berechnet und auch noch die Summer über die BKWs errechnet.

    Das Skript hat auch ein paar Tage funktioniert aber nun hört es plötzlich damit auf. Ich habe an den power_net Werten bei den zwei BKWs und in der Summe der beiden den History Adapter aktiviert um damit dann mit Grafena das ganze darstellen zu können. Im Javascript Adapter läuft das Skript aber ganz normal und im Log sehe ich keine Hinweise. Ich sehe aber das keine Daten mehr zu einem bestimmeten Zeitpunkt in die influx DB geschrieben werden und auch die Objekte ab dem Zeitpunkt nicht mehr geändert wurden. Starte ich das Skript neu funktioniert alles normal bis es dann wieder abbricht (aber nicht wirklich sichtbar).

    Habt ihr eine Idee was ich hier tun kann. Das Skript habe ich mal eingefügt.

    // ===== BKW_Runtime – schreibt nur Werte, legt NIE States an =====
    const PATH_BKW1 = '0_userdata.0.pvundstrom.bkws.1';
    const PATH_BKW2 = '0_userdata.0.pvundstrom.bkws.2';
    const AGG_BASE  = '0_userdata.0.pvundstrom.bkws.all';
    
    const DEVICES = [
      {
        name: 'bkw1',
        POWER: '0_userdata.0.shellies.sonstiges.bkw1.apower',        // W
        TOTAL: '0_userdata.0.shellies.sonstiges.bkw1.aenergy_total', // Wh
        BASE: PATH_BKW1
      },
      {
        name: 'bkw2',
        POWER: '0_userdata.0.shellies.sonstiges.bkw2.apower',
        TOTAL: '0_userdata.0.shellies.sonstiges.bkw2.aenergy_total',
        BASE: PATH_BKW2
      }
    ];
    
    function S(dev){
      const b = dev.BASE;
      return {
        self_w:        `${b}.wr_selfconsumption_w`,
        power_w:       `${b}.power_w`,
        power_net_w:   `${b}.power_net_w`,
        producing:     `${b}.producing`,
        dt_wh:         `${b}.energy_today_net_wh`,
        mt_wh:         `${b}.energy_month_net_wh`,
        yt_wh:         `${b}.energy_year_net_wh`,
        dt_kwh:        `${b}.energy_today_net_kwh`,
        mt_kwh:        `${b}.energy_month_net_kwh`,
        yt_kwh:        `${b}.energy_year_net_kwh`,
        lf_wh:         `${b}.energy_lifetime_net_wh`,
        lf_kwh:        `${b}.energy_lifetime_net_kwh`,
        int_last_total:`${b}.int_total_wh_last`,
        int_net_eff:   `${b}.int_neteffective_wh`,
        int_bd:        `${b}.int_baseline_day_net_wh`,
        int_bm:        `${b}.int_baseline_month_net_wh`,
        int_by:        `${b}.int_baseline_year_net_wh`,
      };
    }
    const n = (v, fb=0) => Number.isFinite(Number(v)) ? Number(v) : fb;
    const toKWh = (wh) => Math.round((wh/1000)*1000)/1000;
    
    async function updateProducingFlags(dev, apNow){
      const s = S(dev);
      const ap = apNow != null ? apNow : n((await getStateAsync(dev.POWER))?.val, 0);
      const selfW = n((await getStateAsync(s.self_w))?.val, 0);
      const producing = ap > selfW;
      await setStateAsync(s.power_w, ap, true);
      await setStateAsync(s.power_net_w, Math.max(0, ap - selfW), true);
      await setStateAsync(s.producing, producing, true);
    }
    
    async function writeNet(dev){
      const s = S(dev);
      const netEff = n((await getStateAsync(s.int_net_eff))?.val, 0);
      const bd = n((await getStateAsync(s.int_bd))?.val, 0);
      const bm = n((await getStateAsync(s.int_bm))?.val, 0);
      const by = n((await getStateAsync(s.int_by))?.val, 0);
      const d = Math.max(0, netEff - bd);
      const m = Math.max(0, netEff - bm);
      const y = Math.max(0, netEff - by);
    
      await setStateAsync(s.dt_wh, d, true);
      await setStateAsync(s.mt_wh, m, true);
      await setStateAsync(s.yt_wh, y, true);
      await setStateAsync(s.dt_kwh, toKWh(d), true);
      await setStateAsync(s.mt_kwh, toKWh(m), true);
      await setStateAsync(s.yt_kwh, toKWh(y), true);
      await setStateAsync(s.lf_wh,  netEff, true);
      await setStateAsync(s.lf_kwh, toKWh(netEff), true);
    }
    
    async function initDevice(dev){
      const s = S(dev);
    
      // Initial
      await updateProducingFlags(dev);
      const totalNow = n((await getStateAsync(dev.TOTAL))?.val, 0);
      const lastInit = n((await getStateAsync(s.int_last_total))?.val, NaN);
      if (!Number.isFinite(lastInit)) await setStateAsync(s.int_last_total, totalNow, true);
    
      const netEffInit = n((await getStateAsync(s.int_net_eff))?.val, NaN);
      if (!Number.isFinite(netEffInit)) await setStateAsync(s.int_net_eff, 0, true);
    
      const netEff = n((await getStateAsync(s.int_net_eff))?.val, 0);
      if (!Number.isFinite(n((await getStateAsync(s.int_bd))?.val, NaN))) await setStateAsync(s.int_bd, netEff, true);
      if (!Number.isFinite(n((await getStateAsync(s.int_bm))?.val, NaN))) await setStateAsync(s.int_bm, netEff, true);
      if (!Number.isFinite(n((await getStateAsync(s.int_by))?.val, NaN))) await setStateAsync(s.int_by, netEff, true);
    
      await writeNet(dev);
    
      // Listener
      on({ id: dev.POWER, change: 'ne' }, async obj => {
        await updateProducingFlags(dev, n(obj.state.val, 0));
      });
    
      on({ id: dev.TOTAL, change: 'ne' }, async obj => {
        const total = n(obj.state.val, 0);
        const last  = n((await getStateAsync(s.int_last_total))?.val, 0);
        let delta = 0;
        if (total < last) delta = total; else delta = total - last;
        await setStateAsync(s.int_last_total, total, true);
    
        const ap = n((await getStateAsync(dev.POWER))?.val, 0);
        const selfW = n((await getStateAsync(s.self_w))?.val, 0);
        if (ap > selfW && delta > 0) {
          const netEffNew = n((await getStateAsync(s.int_net_eff))?.val, 0) + delta;
          await setStateAsync(s.int_net_eff, netEffNew, true);
          await writeNet(dev);
        }
        await updateProducingFlags(dev, ap);
        await updateAggregates();
      });
    
      on({ id: s.self_w, change: 'ne' }, async () => {
        await updateProducingFlags(dev);
      });
    }
    
    // Baselines (Mitternacht/Monat/Jahr)
    async function baselineDay(dev){  const s=S(dev); const v=n((await getStateAsync(s.int_net_eff))?.val,0); await setStateAsync(s.int_bd, v, true); await writeNet(dev); }
    async function baselineMonth(dev){const s=S(dev); const v=n((await getStateAsync(s.int_net_eff))?.val,0); await setStateAsync(s.int_bm, v, true); await writeNet(dev); }
    async function baselineYear(dev){ const s=S(dev); const v=n((await getStateAsync(s.int_net_eff))?.val,0); await setStateAsync(s.int_by, v, true); await writeNet(dev); }
    
    // Aggregat
    function val(id){ const s = getState(id); return s ? Number(s.val)||0 : 0; }
    async function updateAggregates(){
      let pRaw=0, pNet=0, d=0, m=0, y=0, lf=0;
      for (const dev of DEVICES) {
        const s = S(dev);
        pRaw += val(s.power_w);
        pNet += val(s.power_net_w);
        d    += val(s.dt_wh);
        m    += val(s.mt_wh);
        y    += val(s.yt_wh);
        lf   += val(s.lf_wh);
      }
      await setStateAsync(`${AGG_BASE}.power_w`, pRaw, true);
      await setStateAsync(`${AGG_BASE}.power_net_w`, pNet, true);
      await setStateAsync(`${AGG_BASE}.producing`, pNet > 0, true);
      await setStateAsync(`${AGG_BASE}.energy_today_net_wh`, d, true);
      await setStateAsync(`${AGG_BASE}.energy_month_net_wh`, m, true);
      await setStateAsync(`${AGG_BASE}.energy_year_net_wh`,  y, true);
      await setStateAsync(`${AGG_BASE}.energy_today_net_kwh`, toKWh(d), true);
      await setStateAsync(`${AGG_BASE}.energy_month_net_kwh`, toKWh(m), true);
      await setStateAsync(`${AGG_BASE}.energy_year_net_kwh`,  toKWh(y), true);
      await setStateAsync(`${AGG_BASE}.energy_lifetime_net_wh`,  lf, true);
      await setStateAsync(`${AGG_BASE}.energy_lifetime_net_kwh`, toKWh(lf), true);
    }
    
    // Start + Zeitpläne
    (async () => {
      for (const d of DEVICES) await initDevice(d);
    
      schedule('0 0 * * *',      async () => { for (const d of DEVICES) await baselineDay(d);   });
      schedule('0 0 1 * *',      async () => { for (const d of DEVICES) await baselineMonth(d); });
      schedule('0 0 1 1 *',      async () => { for (const d of DEVICES) await baselineYear(d);  });
    
      schedule('*/1 * * * *', updateAggregates);
    })();
    
    HomoranH AsgothianA 3 Antworten Letzte Antwort
    0
    • arteckA Offline
      arteckA Offline
      arteck
      Developer Most Active
      schrieb am zuletzt editiert von arteck
      #2

      @hotspot_2 sagte in Skript läuft plötzlich nicht mehr:

      Habt ihr eine Idee was ich hier tun kann. Das Skript habe ich mal eingefügt.

      und wo ist das LOG davon

      bis es dann wieder abbricht

      was heisst das.. ??

      vor allem wo hast du das Script her...das hast du nicht selbst geschrieben ... so wie es da steht..

      sonst debug Informationen einbauen.. und schauen wo der durchrennt

      zigbee hab ich, zwave auch, nuc's genauso und HA auch

      1 Antwort Letzte Antwort
      0
      • hotspot_2H hotspot_2

        Hallo zusammen,

        ich habe ein Javascript geschrieben das mir die aktuelle Leistung von zwei BKWs von Shelly Adaptern abruft (1 x pro Sekunde) und dann die Stromerzeugung pro Tag usw. berechnet und auch noch die Summer über die BKWs errechnet.

        Das Skript hat auch ein paar Tage funktioniert aber nun hört es plötzlich damit auf. Ich habe an den power_net Werten bei den zwei BKWs und in der Summe der beiden den History Adapter aktiviert um damit dann mit Grafena das ganze darstellen zu können. Im Javascript Adapter läuft das Skript aber ganz normal und im Log sehe ich keine Hinweise. Ich sehe aber das keine Daten mehr zu einem bestimmeten Zeitpunkt in die influx DB geschrieben werden und auch die Objekte ab dem Zeitpunkt nicht mehr geändert wurden. Starte ich das Skript neu funktioniert alles normal bis es dann wieder abbricht (aber nicht wirklich sichtbar).

        Habt ihr eine Idee was ich hier tun kann. Das Skript habe ich mal eingefügt.

        // ===== BKW_Runtime – schreibt nur Werte, legt NIE States an =====
        const PATH_BKW1 = '0_userdata.0.pvundstrom.bkws.1';
        const PATH_BKW2 = '0_userdata.0.pvundstrom.bkws.2';
        const AGG_BASE  = '0_userdata.0.pvundstrom.bkws.all';
        
        const DEVICES = [
          {
            name: 'bkw1',
            POWER: '0_userdata.0.shellies.sonstiges.bkw1.apower',        // W
            TOTAL: '0_userdata.0.shellies.sonstiges.bkw1.aenergy_total', // Wh
            BASE: PATH_BKW1
          },
          {
            name: 'bkw2',
            POWER: '0_userdata.0.shellies.sonstiges.bkw2.apower',
            TOTAL: '0_userdata.0.shellies.sonstiges.bkw2.aenergy_total',
            BASE: PATH_BKW2
          }
        ];
        
        function S(dev){
          const b = dev.BASE;
          return {
            self_w:        `${b}.wr_selfconsumption_w`,
            power_w:       `${b}.power_w`,
            power_net_w:   `${b}.power_net_w`,
            producing:     `${b}.producing`,
            dt_wh:         `${b}.energy_today_net_wh`,
            mt_wh:         `${b}.energy_month_net_wh`,
            yt_wh:         `${b}.energy_year_net_wh`,
            dt_kwh:        `${b}.energy_today_net_kwh`,
            mt_kwh:        `${b}.energy_month_net_kwh`,
            yt_kwh:        `${b}.energy_year_net_kwh`,
            lf_wh:         `${b}.energy_lifetime_net_wh`,
            lf_kwh:        `${b}.energy_lifetime_net_kwh`,
            int_last_total:`${b}.int_total_wh_last`,
            int_net_eff:   `${b}.int_neteffective_wh`,
            int_bd:        `${b}.int_baseline_day_net_wh`,
            int_bm:        `${b}.int_baseline_month_net_wh`,
            int_by:        `${b}.int_baseline_year_net_wh`,
          };
        }
        const n = (v, fb=0) => Number.isFinite(Number(v)) ? Number(v) : fb;
        const toKWh = (wh) => Math.round((wh/1000)*1000)/1000;
        
        async function updateProducingFlags(dev, apNow){
          const s = S(dev);
          const ap = apNow != null ? apNow : n((await getStateAsync(dev.POWER))?.val, 0);
          const selfW = n((await getStateAsync(s.self_w))?.val, 0);
          const producing = ap > selfW;
          await setStateAsync(s.power_w, ap, true);
          await setStateAsync(s.power_net_w, Math.max(0, ap - selfW), true);
          await setStateAsync(s.producing, producing, true);
        }
        
        async function writeNet(dev){
          const s = S(dev);
          const netEff = n((await getStateAsync(s.int_net_eff))?.val, 0);
          const bd = n((await getStateAsync(s.int_bd))?.val, 0);
          const bm = n((await getStateAsync(s.int_bm))?.val, 0);
          const by = n((await getStateAsync(s.int_by))?.val, 0);
          const d = Math.max(0, netEff - bd);
          const m = Math.max(0, netEff - bm);
          const y = Math.max(0, netEff - by);
        
          await setStateAsync(s.dt_wh, d, true);
          await setStateAsync(s.mt_wh, m, true);
          await setStateAsync(s.yt_wh, y, true);
          await setStateAsync(s.dt_kwh, toKWh(d), true);
          await setStateAsync(s.mt_kwh, toKWh(m), true);
          await setStateAsync(s.yt_kwh, toKWh(y), true);
          await setStateAsync(s.lf_wh,  netEff, true);
          await setStateAsync(s.lf_kwh, toKWh(netEff), true);
        }
        
        async function initDevice(dev){
          const s = S(dev);
        
          // Initial
          await updateProducingFlags(dev);
          const totalNow = n((await getStateAsync(dev.TOTAL))?.val, 0);
          const lastInit = n((await getStateAsync(s.int_last_total))?.val, NaN);
          if (!Number.isFinite(lastInit)) await setStateAsync(s.int_last_total, totalNow, true);
        
          const netEffInit = n((await getStateAsync(s.int_net_eff))?.val, NaN);
          if (!Number.isFinite(netEffInit)) await setStateAsync(s.int_net_eff, 0, true);
        
          const netEff = n((await getStateAsync(s.int_net_eff))?.val, 0);
          if (!Number.isFinite(n((await getStateAsync(s.int_bd))?.val, NaN))) await setStateAsync(s.int_bd, netEff, true);
          if (!Number.isFinite(n((await getStateAsync(s.int_bm))?.val, NaN))) await setStateAsync(s.int_bm, netEff, true);
          if (!Number.isFinite(n((await getStateAsync(s.int_by))?.val, NaN))) await setStateAsync(s.int_by, netEff, true);
        
          await writeNet(dev);
        
          // Listener
          on({ id: dev.POWER, change: 'ne' }, async obj => {
            await updateProducingFlags(dev, n(obj.state.val, 0));
          });
        
          on({ id: dev.TOTAL, change: 'ne' }, async obj => {
            const total = n(obj.state.val, 0);
            const last  = n((await getStateAsync(s.int_last_total))?.val, 0);
            let delta = 0;
            if (total < last) delta = total; else delta = total - last;
            await setStateAsync(s.int_last_total, total, true);
        
            const ap = n((await getStateAsync(dev.POWER))?.val, 0);
            const selfW = n((await getStateAsync(s.self_w))?.val, 0);
            if (ap > selfW && delta > 0) {
              const netEffNew = n((await getStateAsync(s.int_net_eff))?.val, 0) + delta;
              await setStateAsync(s.int_net_eff, netEffNew, true);
              await writeNet(dev);
            }
            await updateProducingFlags(dev, ap);
            await updateAggregates();
          });
        
          on({ id: s.self_w, change: 'ne' }, async () => {
            await updateProducingFlags(dev);
          });
        }
        
        // Baselines (Mitternacht/Monat/Jahr)
        async function baselineDay(dev){  const s=S(dev); const v=n((await getStateAsync(s.int_net_eff))?.val,0); await setStateAsync(s.int_bd, v, true); await writeNet(dev); }
        async function baselineMonth(dev){const s=S(dev); const v=n((await getStateAsync(s.int_net_eff))?.val,0); await setStateAsync(s.int_bm, v, true); await writeNet(dev); }
        async function baselineYear(dev){ const s=S(dev); const v=n((await getStateAsync(s.int_net_eff))?.val,0); await setStateAsync(s.int_by, v, true); await writeNet(dev); }
        
        // Aggregat
        function val(id){ const s = getState(id); return s ? Number(s.val)||0 : 0; }
        async function updateAggregates(){
          let pRaw=0, pNet=0, d=0, m=0, y=0, lf=0;
          for (const dev of DEVICES) {
            const s = S(dev);
            pRaw += val(s.power_w);
            pNet += val(s.power_net_w);
            d    += val(s.dt_wh);
            m    += val(s.mt_wh);
            y    += val(s.yt_wh);
            lf   += val(s.lf_wh);
          }
          await setStateAsync(`${AGG_BASE}.power_w`, pRaw, true);
          await setStateAsync(`${AGG_BASE}.power_net_w`, pNet, true);
          await setStateAsync(`${AGG_BASE}.producing`, pNet > 0, true);
          await setStateAsync(`${AGG_BASE}.energy_today_net_wh`, d, true);
          await setStateAsync(`${AGG_BASE}.energy_month_net_wh`, m, true);
          await setStateAsync(`${AGG_BASE}.energy_year_net_wh`,  y, true);
          await setStateAsync(`${AGG_BASE}.energy_today_net_kwh`, toKWh(d), true);
          await setStateAsync(`${AGG_BASE}.energy_month_net_kwh`, toKWh(m), true);
          await setStateAsync(`${AGG_BASE}.energy_year_net_kwh`,  toKWh(y), true);
          await setStateAsync(`${AGG_BASE}.energy_lifetime_net_wh`,  lf, true);
          await setStateAsync(`${AGG_BASE}.energy_lifetime_net_kwh`, toKWh(lf), true);
        }
        
        // Start + Zeitpläne
        (async () => {
          for (const d of DEVICES) await initDevice(d);
        
          schedule('0 0 * * *',      async () => { for (const d of DEVICES) await baselineDay(d);   });
          schedule('0 0 1 * *',      async () => { for (const d of DEVICES) await baselineMonth(d); });
          schedule('0 0 1 1 *',      async () => { for (const d of DEVICES) await baselineYear(d);  });
        
          schedule('*/1 * * * *', updateAggregates);
        })();
        
        HomoranH Nicht stören
        HomoranH Nicht stören
        Homoran
        Global Moderator Administrators
        schrieb am zuletzt editiert von
        #3

        @hotspot_2 sagte in Skript läuft plötzlich nicht mehr:

        Javascript Adapter läuft das Skript aber ganz normal

        @hotspot_2 sagte in Skript läuft plötzlich nicht mehr:

        Ich sehe aber das keine Daten mehr zu einem bestimmeten Zeitpunkt in die influx DB geschrieben werden

        was denn jetzt?

        läuft das Skript nicht, oder werden nur keine Daten geschrieben?

        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
        • T Nicht stören
          T Nicht stören
          ticaki
          schrieb am zuletzt editiert von
          #4

          Hab im Skript zumindest mal keinen offenensichtlichen "Fehler" gefunden.

          Ich würde als erstes mal die await getStateAsync() durch getState() (ebenso setState...) tauschen - das verbraucht weniger Ressourcen und verringert das Problem das sich durch asynchrone Zugriffe ergibt. Der Cache im javascript-adapter ist eigentlich immer die schnellste und beste Zugriffslösung.

          Außerdem würde ich da mehr log einbringen, das man sieht obs tatsächlich hängt.

          Weather-Warnings Espresense NSPanel-Lovelace-ui Tagesschau

          Spenden

          hotspot_2H 1 Antwort Letzte Antwort
          1
          • T ticaki

            Hab im Skript zumindest mal keinen offenensichtlichen "Fehler" gefunden.

            Ich würde als erstes mal die await getStateAsync() durch getState() (ebenso setState...) tauschen - das verbraucht weniger Ressourcen und verringert das Problem das sich durch asynchrone Zugriffe ergibt. Der Cache im javascript-adapter ist eigentlich immer die schnellste und beste Zugriffslösung.

            Außerdem würde ich da mehr log einbringen, das man sieht obs tatsächlich hängt.

            hotspot_2H Online
            hotspot_2H Online
            hotspot_2
            schrieb am zuletzt editiert von hotspot_2
            #5

            Hallo zusammen,

            Das Skript ist in Zusammenarbeit mit mir und ChatGPT entstanden. Ich denke in der heutigen Zeit eine Herangehensweise die man durchaus machen kann. Da die Idee von mir ist, ich mit ChatGPT im Dialog Hinweise gegeben habe und wir dann nach einiger Zeit zu diesem aktuellen Ergebnis gekommen sind habe ich mal völlig selbstbewusst geschrieben das es ich es geschrieben habe. Wenn Dir @arteck völlig klar ist das dieses Skript gar nicht von mir sein kann dann finde ich das erstmal interessant, aber daher habe ich die Entstehungsgeschichte nun mal präzisiert und: für mich ist das völlig fein erstmal.

            @Homoran Das Skript ist ein paar Tage gelaufen. Nach meiner Wahrnehmung hat das Problem begonnen nachdem ich in iobroker für die drei Objekte den History Adapter aktiviert habe. Das Skript, scheint für meine Augen, weiter zu laufen da es im Javascript Adapter nicht gestoppt ist und es keine Log Einträge gibt. Es werden keine Daten mehr in die Objekte geschrieben und damit auch in die influxDB nach unterschiedlichen Zeitabständen nach dem Start. Ich meine das an den geändert Informationen in den drei Objekten zu erkennen und das ab dem gleichen Zeitpunkt die Einträge in der influxDB enden.

            @ticaki Vielen Dank für deinen Input ich werde das mal mit ChatGPT besprechen ;-). Ich habe bereits mal gestern Abend ChatGPT gebeten mal zu prüfen was man tun kann um zu verhindern das das Skript seine Arbeit einstellt (oder was auch immer genau im Detail) und dabei ist das hier dann rausgekommen:

            1// ===============================================
            // BKW_Runtime (no-create version)
            // - Legt KEINE States an
            // - Schreibt NUR in bestehende States (IDs konfigurierbar)
            // - Watchdog/Heartbeat nur per Log (keine Meta-States)
            // ===============================================
            
            // --------------- CONFIG -----------------
            const CONFIG = {
              DEVICES: [
                {
                  name: 'bkw1',
                  // Eingangswerte (müssen existieren)
                  POWER: '0_userdata.0.shellies.sonstiges.bkw1.apower',        // W (aktuelle Leistung)
                  TOTAL: '0_userdata.0.shellies.sonstiges.bkw1.aenergy_total', // Wh (kumulativ)
            
                  // Basis-Pfad für Ziel-/Interimswerte (müssen existieren!)
                  BASE:  '0_userdata.0.pvundstrom.bkws.1',
                },
                {
                  name: 'bkw2',
                  POWER: '0_userdata.0.shellies.sonstiges.bkw2.apower',
                  TOTAL: '0_userdata.0.shellies.sonstiges.bkw2.aenergy_total',
                  BASE:  '0_userdata.0.pvundstrom.bkws.2',
                }
              ],
            
              // Aggregat-Zielpfad (muss existieren!)
              AGG_BASE: '0_userdata.0.pvundstrom.bkws.all',
            
              // Watchdog: Re-Init wenn x Minuten keine Events
              WATCHDOG_IDLE_MIN: 1,
            };
            // ------------- END CONFIG ---------------
            
            
            // ---- State-Builder pro Device (nur IDs, keine Anlage) ----
            function S(dev){
              const b = dev.BASE;
              return {
                // Eingänge:
                self_w:        `${b}.wr_selfconsumption_w`,
            
                // Outputs:
                power_w:       `${b}.power_w`,
                power_net_w:   `${b}.power_net_w`,
                producing:     `${b}.producing`,
            
                dt_wh:         `${b}.energy_today_net_wh`,
                mt_wh:         `${b}.energy_month_net_wh`,
                yt_wh:         `${b}.energy_year_net_wh`,
                dt_kwh:        `${b}.energy_today_net_kwh`,
                mt_kwh:        `${b}.energy_month_net_kwh`,
                yt_kwh:        `${b}.energy_year_net_kwh`,
                lf_wh:         `${b}.energy_lifetime_net_wh`,
                lf_kwh:        `${b}.energy_lifetime_net_kwh`,
            
                // interne Marker (müssen existieren!):
                int_last_total:`${b}.int_total_wh_last`,     // letzter TOTAL (Wh)
                int_net_eff:   `${b}.int_neteffective_wh`,   // effektiv eingespeiste Wh (nur wenn ap>self)
                int_bd:        `${b}.int_baseline_day_net_wh`,
                int_bm:        `${b}.int_baseline_month_net_wh`,
                int_by:        `${b}.int_baseline_year_net_wh`,
              };
            }
            
            // ---- Helpers ----
            const n = (v, fb=0) => Number.isFinite(Number(v)) ? Number(v) : fb;
            const toKWh = (wh) => Math.round((wh/1000)*1000)/1000;
            function val(id){ const s = getState(id); return s ? Number(s.val)||0 : 0; }
            
            // ---- Logging / Watchdog (OHNE States) ----
            let ERRCOUNT = 0;
            let lastEvent = Date.now();
            const WD_MAX_IDLE_MS = CONFIG.WATCHDOG_IDLE_MIN * 60 * 1000;
            
            function iso(ts=Date.now()){ return new Date(ts).toISOString(); }
            async function safe(label, fn){
              try { return await fn(); }
              catch(e){
                ERRCOUNT++;
                log(`[BKW] ${label} FAILED: ${e && e.message ? e.message : e}`, 'warn');
              }
            }
            async function touchEvent(){ lastEvent = Date.now(); }
            schedule('*/1 * * * *', () => log(`[BKW] heartbeat ${iso()}`, 'debug'));
            schedule('*/2 * * * *', async () => {
              const idle = Date.now() - lastEvent;
              if (idle > WD_MAX_IDLE_MS) {
                log(`[BKW] Watchdog: idle ${Math.round(idle/1000)}s → re-init listeners`, 'warn');
                for (const d of CONFIG.DEVICES) await safe(`reinit.${d.name}`, async () => initDevice(d));
                await safe('updateAggregates.watchdog', updateAggregates);
                lastEvent = Date.now();
              }
            });
            
            // ---- Kernlogik ----
            async function updateProducingFlags(dev, apNow){
              const s = S(dev);
              const ap = apNow != null ? apNow : n((await getStateAsync(dev.POWER))?.val, 0);
              const selfW = n((await getStateAsync(s.self_w))?.val, 0);
              const producing = ap > selfW;
            
              await setStateAsync(s.power_w, ap, true);
              await setStateAsync(s.power_net_w, Math.max(0, ap - selfW), true);
              await setStateAsync(s.producing, producing, true);
            }
            
            async function writeNet(dev){
              const s = S(dev);
              const netEff = n((await getStateAsync(s.int_net_eff))?.val, 0);
              const bd = n((await getStateAsync(s.int_bd))?.val, 0);
              const bm = n((await getStateAsync(s.int_bm))?.val, 0);
              const by = n((await getStateAsync(s.int_by))?.val, 0);
            
              const d = Math.max(0, netEff - bd);
              const m = Math.max(0, netEff - bm);
              const y = Math.max(0, netEff - by);
            
              await setStateAsync(s.dt_wh, d, true);
              await setStateAsync(s.mt_wh, m, true);
              await setStateAsync(s.yt_wh, y, true);
              await setStateAsync(s.dt_kwh, toKWh(d), true);
              await setStateAsync(s.mt_kwh, toKWh(m), true);
              await setStateAsync(s.yt_kwh, toKWh(y), true);
              await setStateAsync(s.lf_wh,  netEff, true);
              await setStateAsync(s.lf_kwh, toKWh(netEff), true);
            }
            
            async function initDevice(dev){
              const s = S(dev);
            
              // Initiale Flags
              await safe(`init.updateProducingFlags.${dev.name}`, async () => updateProducingFlags(dev));
            
              // Merker laden
              const totalNow = n((await getStateAsync(dev.TOTAL))?.val, 0);
              const lastInit = n((await getStateAsync(s.int_last_total))?.val, NaN);
              if (!Number.isFinite(lastInit)) {
                // NICHT anlegen – vorausgesetzt, der State existiert
                await setStateAsync(s.int_last_total, totalNow, true);
              }
            
              const netEffInit = n((await getStateAsync(s.int_net_eff))?.val, NaN);
              if (!Number.isFinite(netEffInit)) {
                await setStateAsync(s.int_net_eff, 0, true);
              }
            
              const netEff = n((await getStateAsync(s.int_net_eff))?.val, 0);
              if (!Number.isFinite(n((await getStateAsync(s.int_bd))?.val, NaN))) await setStateAsync(s.int_bd, netEff, true);
              if (!Number.isFinite(n((await getStateAsync(s.int_bm))?.val, NaN))) await setStateAsync(s.int_bm, netEff, true);
              if (!Number.isFinite(n((await getStateAsync(s.int_by))?.val, NaN))) await setStateAsync(s.int_by, netEff, true);
            
              await safe(`init.writeNet.${dev.name}`, async () => writeNet(dev));
            
              // Listener neu registrieren (auch bei Re-Init)
              on({ id: dev.POWER, change: 'ne' }, async obj => {
                await touchEvent();
                await safe(`POWER:${dev.name}`, async () => {
                  await updateProducingFlags(dev, n(obj.state.val, 0));
                });
              });
            
              on({ id: dev.TOTAL, change: 'ne' }, async obj => {
                await touchEvent();
                await safe(`TOTAL:${dev.name}`, async () => {
                  const total = n(obj.state.val, 0);
                  const last  = n((await getStateAsync(s.int_last_total))?.val, 0);
            
                  // Robust gegen Reset: wenn TOTAL kleiner als last → Basis neu setzen, KEIN Delta
                  if (total < last) {
                    await setStateAsync(s.int_last_total, total, true);
                  } else {
                    const delta = total - last;
                    await setStateAsync(s.int_last_total, total, true);
            
                    const ap = n((await getStateAsync(dev.POWER))?.val, 0);
                    const selfW = n((await getStateAsync(s.self_w))?.val, 0);
                    if (ap > selfW && delta > 0) {
                      const netEffNew = n((await getStateAsync(s.int_net_eff))?.val, 0) + delta;
                      await setStateAsync(s.int_net_eff, netEffNew, true);
                      await writeNet(dev);
                    }
            
                    await updateProducingFlags(dev, ap);
                    await updateAggregates();
                  }
                });
              });
            
              on({ id: s.self_w, change: 'ne' }, async () => {
                await touchEvent();
                await safe(`SELF_W:${dev.name}`, async () => updateProducingFlags(dev));
              });
            }
            
            // Baselines (Mitternacht/Monat/Jahr) – schreiben nur in bestehende States
            async function baselineDay(dev){
              const s=S(dev);
              const v=n((await getStateAsync(s.int_net_eff))?.val,0);
              await setStateAsync(s.int_bd, v, true);
              await writeNet(dev);
            }
            async function baselineMonth(dev){
              const s=S(dev);
              const v=n((await getStateAsync(s.int_net_eff))?.val,0);
              await setStateAsync(s.int_bm, v, true);
              await writeNet(dev);
            }
            async function baselineYear(dev){
              const s=S(dev);
              const v=n((await getStateAsync(s.int_net_eff))?.val,0);
              await setStateAsync(s.int_by, v, true);
              await writeNet(dev);
            }
            
            // Aggregat
            async function updateAggregates(){
              const AGG = CONFIG.AGG_BASE;
              let pRaw=0, pNet=0, d=0, m=0, y=0, lf=0;
              for (const dev of CONFIG.DEVICES) {
                const s = S(dev);
                pRaw += val(s.power_w);
                pNet += val(s.power_net_w);
                d    += val(s.dt_wh);
                m    += val(s.mt_wh);
                y    += val(s.yt_wh);
                lf   += val(s.lf_wh);
              }
              await setStateAsync(`${AGG}.power_w`, pRaw, true);
              await setStateAsync(`${AGG}.power_net_w`, pNet, true);
              await setStateAsync(`${AGG}.producing`, pNet > 0, true);
              await setStateAsync(`${AGG}.energy_today_net_wh`, d, true);
              await setStateAsync(`${AGG}.energy_month_net_wh`, m, true);
              await setStateAsync(`${AGG}.energy_year_net_wh`,  y, true);
              await setStateAsync(`${AGG}.energy_today_net_kwh`, toKWh(d), true);
              await setStateAsync(`${AGG}.energy_month_net_kwh`, toKWh(m), true);
              await setStateAsync(`${AGG}.energy_year_net_kwh`,  toKWh(y), true);
              await setStateAsync(`${AGG}.energy_lifetime_net_wh`,  lf, true);
              await setStateAsync(`${AGG}.energy_lifetime_net_kwh`, toKWh(lf), true);
            }
            
            // ===== Start + Zeitpläne =====
            (async () => {
              // Init Geräte & Listener
              for (const d of CONFIG.DEVICES) await safe(`initDevice.${d.name}`, async () => initDevice(d));
            
              // Baselines
              schedule('0 0 * * *',      async () => { for (const d of CONFIG.DEVICES) await safe(`baselineDay.${d.name}`,   async () => baselineDay(d));   });
              schedule('0 0 1 * *',      async () => { for (const d of CONFIG.DEVICES) await safe(`baselineMonth.${d.name}`, async () => baselineMonth(d)); });
              schedule('0 0 1 1 *',      async () => { for (const d of CONFIG.DEVICES) await safe(`baselineYear.${d.name}`,  async () => baselineYear(d));  });
            
              // Aggregat zyklisch zusätzlich
              schedule('*/1 * * * *', async () => safe('updateAggregates.cron', updateAggregates));
            
              log('[BKW] Script started (no-create mode).', 'info');
            })();
            
            1 Antwort Letzte Antwort
            0
            • hotspot_2H hotspot_2

              Hallo zusammen,

              ich habe ein Javascript geschrieben das mir die aktuelle Leistung von zwei BKWs von Shelly Adaptern abruft (1 x pro Sekunde) und dann die Stromerzeugung pro Tag usw. berechnet und auch noch die Summer über die BKWs errechnet.

              Das Skript hat auch ein paar Tage funktioniert aber nun hört es plötzlich damit auf. Ich habe an den power_net Werten bei den zwei BKWs und in der Summe der beiden den History Adapter aktiviert um damit dann mit Grafena das ganze darstellen zu können. Im Javascript Adapter läuft das Skript aber ganz normal und im Log sehe ich keine Hinweise. Ich sehe aber das keine Daten mehr zu einem bestimmeten Zeitpunkt in die influx DB geschrieben werden und auch die Objekte ab dem Zeitpunkt nicht mehr geändert wurden. Starte ich das Skript neu funktioniert alles normal bis es dann wieder abbricht (aber nicht wirklich sichtbar).

              Habt ihr eine Idee was ich hier tun kann. Das Skript habe ich mal eingefügt.

              // ===== BKW_Runtime – schreibt nur Werte, legt NIE States an =====
              const PATH_BKW1 = '0_userdata.0.pvundstrom.bkws.1';
              const PATH_BKW2 = '0_userdata.0.pvundstrom.bkws.2';
              const AGG_BASE  = '0_userdata.0.pvundstrom.bkws.all';
              
              const DEVICES = [
                {
                  name: 'bkw1',
                  POWER: '0_userdata.0.shellies.sonstiges.bkw1.apower',        // W
                  TOTAL: '0_userdata.0.shellies.sonstiges.bkw1.aenergy_total', // Wh
                  BASE: PATH_BKW1
                },
                {
                  name: 'bkw2',
                  POWER: '0_userdata.0.shellies.sonstiges.bkw2.apower',
                  TOTAL: '0_userdata.0.shellies.sonstiges.bkw2.aenergy_total',
                  BASE: PATH_BKW2
                }
              ];
              
              function S(dev){
                const b = dev.BASE;
                return {
                  self_w:        `${b}.wr_selfconsumption_w`,
                  power_w:       `${b}.power_w`,
                  power_net_w:   `${b}.power_net_w`,
                  producing:     `${b}.producing`,
                  dt_wh:         `${b}.energy_today_net_wh`,
                  mt_wh:         `${b}.energy_month_net_wh`,
                  yt_wh:         `${b}.energy_year_net_wh`,
                  dt_kwh:        `${b}.energy_today_net_kwh`,
                  mt_kwh:        `${b}.energy_month_net_kwh`,
                  yt_kwh:        `${b}.energy_year_net_kwh`,
                  lf_wh:         `${b}.energy_lifetime_net_wh`,
                  lf_kwh:        `${b}.energy_lifetime_net_kwh`,
                  int_last_total:`${b}.int_total_wh_last`,
                  int_net_eff:   `${b}.int_neteffective_wh`,
                  int_bd:        `${b}.int_baseline_day_net_wh`,
                  int_bm:        `${b}.int_baseline_month_net_wh`,
                  int_by:        `${b}.int_baseline_year_net_wh`,
                };
              }
              const n = (v, fb=0) => Number.isFinite(Number(v)) ? Number(v) : fb;
              const toKWh = (wh) => Math.round((wh/1000)*1000)/1000;
              
              async function updateProducingFlags(dev, apNow){
                const s = S(dev);
                const ap = apNow != null ? apNow : n((await getStateAsync(dev.POWER))?.val, 0);
                const selfW = n((await getStateAsync(s.self_w))?.val, 0);
                const producing = ap > selfW;
                await setStateAsync(s.power_w, ap, true);
                await setStateAsync(s.power_net_w, Math.max(0, ap - selfW), true);
                await setStateAsync(s.producing, producing, true);
              }
              
              async function writeNet(dev){
                const s = S(dev);
                const netEff = n((await getStateAsync(s.int_net_eff))?.val, 0);
                const bd = n((await getStateAsync(s.int_bd))?.val, 0);
                const bm = n((await getStateAsync(s.int_bm))?.val, 0);
                const by = n((await getStateAsync(s.int_by))?.val, 0);
                const d = Math.max(0, netEff - bd);
                const m = Math.max(0, netEff - bm);
                const y = Math.max(0, netEff - by);
              
                await setStateAsync(s.dt_wh, d, true);
                await setStateAsync(s.mt_wh, m, true);
                await setStateAsync(s.yt_wh, y, true);
                await setStateAsync(s.dt_kwh, toKWh(d), true);
                await setStateAsync(s.mt_kwh, toKWh(m), true);
                await setStateAsync(s.yt_kwh, toKWh(y), true);
                await setStateAsync(s.lf_wh,  netEff, true);
                await setStateAsync(s.lf_kwh, toKWh(netEff), true);
              }
              
              async function initDevice(dev){
                const s = S(dev);
              
                // Initial
                await updateProducingFlags(dev);
                const totalNow = n((await getStateAsync(dev.TOTAL))?.val, 0);
                const lastInit = n((await getStateAsync(s.int_last_total))?.val, NaN);
                if (!Number.isFinite(lastInit)) await setStateAsync(s.int_last_total, totalNow, true);
              
                const netEffInit = n((await getStateAsync(s.int_net_eff))?.val, NaN);
                if (!Number.isFinite(netEffInit)) await setStateAsync(s.int_net_eff, 0, true);
              
                const netEff = n((await getStateAsync(s.int_net_eff))?.val, 0);
                if (!Number.isFinite(n((await getStateAsync(s.int_bd))?.val, NaN))) await setStateAsync(s.int_bd, netEff, true);
                if (!Number.isFinite(n((await getStateAsync(s.int_bm))?.val, NaN))) await setStateAsync(s.int_bm, netEff, true);
                if (!Number.isFinite(n((await getStateAsync(s.int_by))?.val, NaN))) await setStateAsync(s.int_by, netEff, true);
              
                await writeNet(dev);
              
                // Listener
                on({ id: dev.POWER, change: 'ne' }, async obj => {
                  await updateProducingFlags(dev, n(obj.state.val, 0));
                });
              
                on({ id: dev.TOTAL, change: 'ne' }, async obj => {
                  const total = n(obj.state.val, 0);
                  const last  = n((await getStateAsync(s.int_last_total))?.val, 0);
                  let delta = 0;
                  if (total < last) delta = total; else delta = total - last;
                  await setStateAsync(s.int_last_total, total, true);
              
                  const ap = n((await getStateAsync(dev.POWER))?.val, 0);
                  const selfW = n((await getStateAsync(s.self_w))?.val, 0);
                  if (ap > selfW && delta > 0) {
                    const netEffNew = n((await getStateAsync(s.int_net_eff))?.val, 0) + delta;
                    await setStateAsync(s.int_net_eff, netEffNew, true);
                    await writeNet(dev);
                  }
                  await updateProducingFlags(dev, ap);
                  await updateAggregates();
                });
              
                on({ id: s.self_w, change: 'ne' }, async () => {
                  await updateProducingFlags(dev);
                });
              }
              
              // Baselines (Mitternacht/Monat/Jahr)
              async function baselineDay(dev){  const s=S(dev); const v=n((await getStateAsync(s.int_net_eff))?.val,0); await setStateAsync(s.int_bd, v, true); await writeNet(dev); }
              async function baselineMonth(dev){const s=S(dev); const v=n((await getStateAsync(s.int_net_eff))?.val,0); await setStateAsync(s.int_bm, v, true); await writeNet(dev); }
              async function baselineYear(dev){ const s=S(dev); const v=n((await getStateAsync(s.int_net_eff))?.val,0); await setStateAsync(s.int_by, v, true); await writeNet(dev); }
              
              // Aggregat
              function val(id){ const s = getState(id); return s ? Number(s.val)||0 : 0; }
              async function updateAggregates(){
                let pRaw=0, pNet=0, d=0, m=0, y=0, lf=0;
                for (const dev of DEVICES) {
                  const s = S(dev);
                  pRaw += val(s.power_w);
                  pNet += val(s.power_net_w);
                  d    += val(s.dt_wh);
                  m    += val(s.mt_wh);
                  y    += val(s.yt_wh);
                  lf   += val(s.lf_wh);
                }
                await setStateAsync(`${AGG_BASE}.power_w`, pRaw, true);
                await setStateAsync(`${AGG_BASE}.power_net_w`, pNet, true);
                await setStateAsync(`${AGG_BASE}.producing`, pNet > 0, true);
                await setStateAsync(`${AGG_BASE}.energy_today_net_wh`, d, true);
                await setStateAsync(`${AGG_BASE}.energy_month_net_wh`, m, true);
                await setStateAsync(`${AGG_BASE}.energy_year_net_wh`,  y, true);
                await setStateAsync(`${AGG_BASE}.energy_today_net_kwh`, toKWh(d), true);
                await setStateAsync(`${AGG_BASE}.energy_month_net_kwh`, toKWh(m), true);
                await setStateAsync(`${AGG_BASE}.energy_year_net_kwh`,  toKWh(y), true);
                await setStateAsync(`${AGG_BASE}.energy_lifetime_net_wh`,  lf, true);
                await setStateAsync(`${AGG_BASE}.energy_lifetime_net_kwh`, toKWh(lf), true);
              }
              
              // Start + Zeitpläne
              (async () => {
                for (const d of DEVICES) await initDevice(d);
              
                schedule('0 0 * * *',      async () => { for (const d of DEVICES) await baselineDay(d);   });
                schedule('0 0 1 * *',      async () => { for (const d of DEVICES) await baselineMonth(d); });
                schedule('0 0 1 1 *',      async () => { for (const d of DEVICES) await baselineYear(d);  });
              
                schedule('*/1 * * * *', updateAggregates);
              })();
              
              AsgothianA Offline
              AsgothianA Offline
              Asgothian
              Developer
              schrieb am zuletzt editiert von Asgothian
              #6

              @hotspot_2 sagte in Skript läuft plötzlich nicht mehr:

              ich habe ein Javascript geschrieben das mir die aktuelle Leistung von zwei BKWs von Shelly Adaptern abruft (1 x pro Sekunde) und dann die Stromerzeugung pro Tag usw. berechnet und auch noch die Summer über die BKWs errechnet.

              • Warum machst du diesen Unsinn mit dem 1s heartbeat, wenn die Shellies ihre Werte wohl eher nicht in dieser frequenz geändert werden ?
              • bist du sicher das sich die Heartbeats nicht 'aufstauen', so das die vielen einzelnen 'write' events in die DB das ganze blockieren ?
              • Warum holst du den 'letzten' wert jedesmal neu, anstelle diesen in einer lokalen Variablen zu speichern, damit du nicht extra zugriffe auf die DB hast ?
              • Warum speicherst du die Werte auf die du triggerst nicht in lokale variablen, und holst die dann im Skript immer wieder neu ?

              Insgesamt glaube ich das die Abläufe sich über die Zeit aufstauen, so das das Skript wegen mangelnder Reentranz von Funktionen nicht mehr stabil läuft.

              Du solltest Deinen Ansatz mal grundsätzlich überdenken. Wozu brauchst du jede Sekunde jeden der berechneten Werte ?

              A.
              p.s. Das Skript mag keine 'syntaktischen' Fehler haben - danach habe ich nicht geschaut. Die verwendete Logik kann aber auf jeden Fall eine Optimierung vertragen - und eine Begrenzung auf 'sinnvolle' Datenmengen.

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

              HomoranH 1 Antwort Letzte Antwort
              1
              • AsgothianA Asgothian

                @hotspot_2 sagte in Skript läuft plötzlich nicht mehr:

                ich habe ein Javascript geschrieben das mir die aktuelle Leistung von zwei BKWs von Shelly Adaptern abruft (1 x pro Sekunde) und dann die Stromerzeugung pro Tag usw. berechnet und auch noch die Summer über die BKWs errechnet.

                • Warum machst du diesen Unsinn mit dem 1s heartbeat, wenn die Shellies ihre Werte wohl eher nicht in dieser frequenz geändert werden ?
                • bist du sicher das sich die Heartbeats nicht 'aufstauen', so das die vielen einzelnen 'write' events in die DB das ganze blockieren ?
                • Warum holst du den 'letzten' wert jedesmal neu, anstelle diesen in einer lokalen Variablen zu speichern, damit du nicht extra zugriffe auf die DB hast ?
                • Warum speicherst du die Werte auf die du triggerst nicht in lokale variablen, und holst die dann im Skript immer wieder neu ?

                Insgesamt glaube ich das die Abläufe sich über die Zeit aufstauen, so das das Skript wegen mangelnder Reentranz von Funktionen nicht mehr stabil läuft.

                Du solltest Deinen Ansatz mal grundsätzlich überdenken. Wozu brauchst du jede Sekunde jeden der berechneten Werte ?

                A.
                p.s. Das Skript mag keine 'syntaktischen' Fehler haben - danach habe ich nicht geschaut. Die verwendete Logik kann aber auf jeden Fall eine Optimierung vertragen - und eine Begrenzung auf 'sinnvolle' Datenmengen.

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

                @asgothian sagte in Skript läuft plötzlich nicht mehr:

                Warum machst du diesen Unsinn mit dem 1s heartbeat, wenn die Shellies ihre Werte wohl eher nicht in dieser frequenz geändert werden ?

                @hotspot_2 sagte in Skript läuft plötzlich nicht mehr:

                Das Skript ist in Zusammenarbeit mit mir und ChatGPT entstanden. Ich denke in der heutigen Zeit eine Herangehensweise die man durchaus machen kann.

                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 -

                AsgothianA 1 Antwort Letzte Antwort
                0
                • HomoranH Homoran

                  @asgothian sagte in Skript läuft plötzlich nicht mehr:

                  Warum machst du diesen Unsinn mit dem 1s heartbeat, wenn die Shellies ihre Werte wohl eher nicht in dieser frequenz geändert werden ?

                  @hotspot_2 sagte in Skript läuft plötzlich nicht mehr:

                  Das Skript ist in Zusammenarbeit mit mir und ChatGPT entstanden. Ich denke in der heutigen Zeit eine Herangehensweise die man durchaus machen kann.

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

                  @homoran sagte in Skript läuft plötzlich nicht mehr:

                  @asgothian sagte in Skript läuft plötzlich nicht mehr:

                  Warum machst du diesen Unsinn mit dem 1s heartbeat, wenn die Shellies ihre Werte wohl eher nicht in dieser frequenz geändert werden ?

                  @hotspot_2 sagte in Skript läuft plötzlich nicht mehr:

                  Das Skript ist in Zusammenarbeit mit mir und ChatGPT entstanden. Ich denke in der heutigen Zeit eine Herangehensweise die man durchaus machen kann.

                  ich denke da ist ChatGPT unschuldig :) Das war fast sicher vorgegeben.

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

                  HomoranH 1 Antwort Letzte Antwort
                  0
                  • AsgothianA Asgothian

                    @homoran sagte in Skript läuft plötzlich nicht mehr:

                    @asgothian sagte in Skript läuft plötzlich nicht mehr:

                    Warum machst du diesen Unsinn mit dem 1s heartbeat, wenn die Shellies ihre Werte wohl eher nicht in dieser frequenz geändert werden ?

                    @hotspot_2 sagte in Skript läuft plötzlich nicht mehr:

                    Das Skript ist in Zusammenarbeit mit mir und ChatGPT entstanden. Ich denke in der heutigen Zeit eine Herangehensweise die man durchaus machen kann.

                    ich denke da ist ChatGPT unschuldig :) Das war fast sicher vorgegeben.

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

                    @asgothian sagte in Skript läuft plötzlich nicht mehr:

                    Das war fast sicher vorgegeben.

                    gehe ich auch von aus.
                    Aber KI tut nur was man sagt, und das muss ausreichend wohlüberlegt sein.

                    Eine Korrektur in "bessere Programmierung" findet eben nicht statt

                    Der Aufwand der KI gut strukturierte, sinnvolle Anweisungen zu geben, ist der selbe, den man für die eigene Programmierung benötigt.
                    Dann kan man auch den letzten Schritt noch selber machen.

                    Wenn man, wie ich, kein js beherrsct, macht man es eben mit Blockly

                    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 -

                    AsgothianA 1 Antwort Letzte Antwort
                    0
                    • T Nicht stören
                      T Nicht stören
                      ticaki
                      schrieb am zuletzt editiert von
                      #10

                      Im Skript gibt’s keinen 1 Sekunden schedule, außer ich hab mich gestern verzählt 5 Felder sind Minuten 6 Sekunden… oder?

                      Weather-Warnings Espresense NSPanel-Lovelace-ui Tagesschau

                      Spenden

                      AsgothianA 1 Antwort Letzte Antwort
                      0
                      • T ticaki

                        Im Skript gibt’s keinen 1 Sekunden schedule, außer ich hab mich gestern verzählt 5 Felder sind Minuten 6 Sekunden… oder?

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

                        @ticaki sagte in Skript läuft plötzlich nicht mehr:

                        Im Skript gibt’s keinen 1 Sekunden schedule, außer ich hab mich gestern verzählt 5 Felder sind Minuten 6 Sekunden… oder?

                        Denkbar, ich bin nicht vom Code im Skript ausgegangen, sondern von dieser Aussage :

                        @hotspot_2 sagte in Skript läuft plötzlich nicht mehr:

                        ich habe ein Javascript geschrieben das mir die aktuelle Leistung von zwei BKWs von Shelly Adaptern abruft (1 x pro Sekunde) und dann die Stromerzeugung pro Tag usw. berechnet und auch noch die Summer über die BKWs errechnet.

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

                        1 Antwort Letzte Antwort
                        0
                        • HomoranH Homoran

                          @asgothian sagte in Skript läuft plötzlich nicht mehr:

                          Das war fast sicher vorgegeben.

                          gehe ich auch von aus.
                          Aber KI tut nur was man sagt, und das muss ausreichend wohlüberlegt sein.

                          Eine Korrektur in "bessere Programmierung" findet eben nicht statt

                          Der Aufwand der KI gut strukturierte, sinnvolle Anweisungen zu geben, ist der selbe, den man für die eigene Programmierung benötigt.
                          Dann kan man auch den letzten Schritt noch selber machen.

                          Wenn man, wie ich, kein js beherrsct, macht man es eben mit Blockly

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

                          @homoran sagte in Skript läuft plötzlich nicht mehr:

                          Aber KI tut nur was man sagt, und das muss ausreichend wohlüberlegt sein.
                          Eine Korrektur in "bessere Programmierung" findet eben nicht statt
                          Der Aufwand der KI gut strukturierte, sinnvolle Anweisungen zu geben, ist der selbe, den man für die eigene Programmierung benötigt.
                          Dann kan man auch den letzten Schritt noch selber machen.
                          Wenn man, wie ich, kein js beherrsct, macht man es eben mit Blockly

                          Dem würde ich so nicht zu 100% zustimmen. Es ist für mich ok wenn man KI dafür benutzt einen Algorithmus in ausführbaren Code zu giessen.

                          Das Problem sehe ich eher im Algorithmus hinter dem Skript, und der Idee hinter dem Algorithmus.

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

                          1 Antwort Letzte Antwort
                          1
                          • hotspot_2H hotspot_2

                            Hallo zusammen,

                            ich habe ein Javascript geschrieben das mir die aktuelle Leistung von zwei BKWs von Shelly Adaptern abruft (1 x pro Sekunde) und dann die Stromerzeugung pro Tag usw. berechnet und auch noch die Summer über die BKWs errechnet.

                            Das Skript hat auch ein paar Tage funktioniert aber nun hört es plötzlich damit auf. Ich habe an den power_net Werten bei den zwei BKWs und in der Summe der beiden den History Adapter aktiviert um damit dann mit Grafena das ganze darstellen zu können. Im Javascript Adapter läuft das Skript aber ganz normal und im Log sehe ich keine Hinweise. Ich sehe aber das keine Daten mehr zu einem bestimmeten Zeitpunkt in die influx DB geschrieben werden und auch die Objekte ab dem Zeitpunkt nicht mehr geändert wurden. Starte ich das Skript neu funktioniert alles normal bis es dann wieder abbricht (aber nicht wirklich sichtbar).

                            Habt ihr eine Idee was ich hier tun kann. Das Skript habe ich mal eingefügt.

                            // ===== BKW_Runtime – schreibt nur Werte, legt NIE States an =====
                            const PATH_BKW1 = '0_userdata.0.pvundstrom.bkws.1';
                            const PATH_BKW2 = '0_userdata.0.pvundstrom.bkws.2';
                            const AGG_BASE  = '0_userdata.0.pvundstrom.bkws.all';
                            
                            const DEVICES = [
                              {
                                name: 'bkw1',
                                POWER: '0_userdata.0.shellies.sonstiges.bkw1.apower',        // W
                                TOTAL: '0_userdata.0.shellies.sonstiges.bkw1.aenergy_total', // Wh
                                BASE: PATH_BKW1
                              },
                              {
                                name: 'bkw2',
                                POWER: '0_userdata.0.shellies.sonstiges.bkw2.apower',
                                TOTAL: '0_userdata.0.shellies.sonstiges.bkw2.aenergy_total',
                                BASE: PATH_BKW2
                              }
                            ];
                            
                            function S(dev){
                              const b = dev.BASE;
                              return {
                                self_w:        `${b}.wr_selfconsumption_w`,
                                power_w:       `${b}.power_w`,
                                power_net_w:   `${b}.power_net_w`,
                                producing:     `${b}.producing`,
                                dt_wh:         `${b}.energy_today_net_wh`,
                                mt_wh:         `${b}.energy_month_net_wh`,
                                yt_wh:         `${b}.energy_year_net_wh`,
                                dt_kwh:        `${b}.energy_today_net_kwh`,
                                mt_kwh:        `${b}.energy_month_net_kwh`,
                                yt_kwh:        `${b}.energy_year_net_kwh`,
                                lf_wh:         `${b}.energy_lifetime_net_wh`,
                                lf_kwh:        `${b}.energy_lifetime_net_kwh`,
                                int_last_total:`${b}.int_total_wh_last`,
                                int_net_eff:   `${b}.int_neteffective_wh`,
                                int_bd:        `${b}.int_baseline_day_net_wh`,
                                int_bm:        `${b}.int_baseline_month_net_wh`,
                                int_by:        `${b}.int_baseline_year_net_wh`,
                              };
                            }
                            const n = (v, fb=0) => Number.isFinite(Number(v)) ? Number(v) : fb;
                            const toKWh = (wh) => Math.round((wh/1000)*1000)/1000;
                            
                            async function updateProducingFlags(dev, apNow){
                              const s = S(dev);
                              const ap = apNow != null ? apNow : n((await getStateAsync(dev.POWER))?.val, 0);
                              const selfW = n((await getStateAsync(s.self_w))?.val, 0);
                              const producing = ap > selfW;
                              await setStateAsync(s.power_w, ap, true);
                              await setStateAsync(s.power_net_w, Math.max(0, ap - selfW), true);
                              await setStateAsync(s.producing, producing, true);
                            }
                            
                            async function writeNet(dev){
                              const s = S(dev);
                              const netEff = n((await getStateAsync(s.int_net_eff))?.val, 0);
                              const bd = n((await getStateAsync(s.int_bd))?.val, 0);
                              const bm = n((await getStateAsync(s.int_bm))?.val, 0);
                              const by = n((await getStateAsync(s.int_by))?.val, 0);
                              const d = Math.max(0, netEff - bd);
                              const m = Math.max(0, netEff - bm);
                              const y = Math.max(0, netEff - by);
                            
                              await setStateAsync(s.dt_wh, d, true);
                              await setStateAsync(s.mt_wh, m, true);
                              await setStateAsync(s.yt_wh, y, true);
                              await setStateAsync(s.dt_kwh, toKWh(d), true);
                              await setStateAsync(s.mt_kwh, toKWh(m), true);
                              await setStateAsync(s.yt_kwh, toKWh(y), true);
                              await setStateAsync(s.lf_wh,  netEff, true);
                              await setStateAsync(s.lf_kwh, toKWh(netEff), true);
                            }
                            
                            async function initDevice(dev){
                              const s = S(dev);
                            
                              // Initial
                              await updateProducingFlags(dev);
                              const totalNow = n((await getStateAsync(dev.TOTAL))?.val, 0);
                              const lastInit = n((await getStateAsync(s.int_last_total))?.val, NaN);
                              if (!Number.isFinite(lastInit)) await setStateAsync(s.int_last_total, totalNow, true);
                            
                              const netEffInit = n((await getStateAsync(s.int_net_eff))?.val, NaN);
                              if (!Number.isFinite(netEffInit)) await setStateAsync(s.int_net_eff, 0, true);
                            
                              const netEff = n((await getStateAsync(s.int_net_eff))?.val, 0);
                              if (!Number.isFinite(n((await getStateAsync(s.int_bd))?.val, NaN))) await setStateAsync(s.int_bd, netEff, true);
                              if (!Number.isFinite(n((await getStateAsync(s.int_bm))?.val, NaN))) await setStateAsync(s.int_bm, netEff, true);
                              if (!Number.isFinite(n((await getStateAsync(s.int_by))?.val, NaN))) await setStateAsync(s.int_by, netEff, true);
                            
                              await writeNet(dev);
                            
                              // Listener
                              on({ id: dev.POWER, change: 'ne' }, async obj => {
                                await updateProducingFlags(dev, n(obj.state.val, 0));
                              });
                            
                              on({ id: dev.TOTAL, change: 'ne' }, async obj => {
                                const total = n(obj.state.val, 0);
                                const last  = n((await getStateAsync(s.int_last_total))?.val, 0);
                                let delta = 0;
                                if (total < last) delta = total; else delta = total - last;
                                await setStateAsync(s.int_last_total, total, true);
                            
                                const ap = n((await getStateAsync(dev.POWER))?.val, 0);
                                const selfW = n((await getStateAsync(s.self_w))?.val, 0);
                                if (ap > selfW && delta > 0) {
                                  const netEffNew = n((await getStateAsync(s.int_net_eff))?.val, 0) + delta;
                                  await setStateAsync(s.int_net_eff, netEffNew, true);
                                  await writeNet(dev);
                                }
                                await updateProducingFlags(dev, ap);
                                await updateAggregates();
                              });
                            
                              on({ id: s.self_w, change: 'ne' }, async () => {
                                await updateProducingFlags(dev);
                              });
                            }
                            
                            // Baselines (Mitternacht/Monat/Jahr)
                            async function baselineDay(dev){  const s=S(dev); const v=n((await getStateAsync(s.int_net_eff))?.val,0); await setStateAsync(s.int_bd, v, true); await writeNet(dev); }
                            async function baselineMonth(dev){const s=S(dev); const v=n((await getStateAsync(s.int_net_eff))?.val,0); await setStateAsync(s.int_bm, v, true); await writeNet(dev); }
                            async function baselineYear(dev){ const s=S(dev); const v=n((await getStateAsync(s.int_net_eff))?.val,0); await setStateAsync(s.int_by, v, true); await writeNet(dev); }
                            
                            // Aggregat
                            function val(id){ const s = getState(id); return s ? Number(s.val)||0 : 0; }
                            async function updateAggregates(){
                              let pRaw=0, pNet=0, d=0, m=0, y=0, lf=0;
                              for (const dev of DEVICES) {
                                const s = S(dev);
                                pRaw += val(s.power_w);
                                pNet += val(s.power_net_w);
                                d    += val(s.dt_wh);
                                m    += val(s.mt_wh);
                                y    += val(s.yt_wh);
                                lf   += val(s.lf_wh);
                              }
                              await setStateAsync(`${AGG_BASE}.power_w`, pRaw, true);
                              await setStateAsync(`${AGG_BASE}.power_net_w`, pNet, true);
                              await setStateAsync(`${AGG_BASE}.producing`, pNet > 0, true);
                              await setStateAsync(`${AGG_BASE}.energy_today_net_wh`, d, true);
                              await setStateAsync(`${AGG_BASE}.energy_month_net_wh`, m, true);
                              await setStateAsync(`${AGG_BASE}.energy_year_net_wh`,  y, true);
                              await setStateAsync(`${AGG_BASE}.energy_today_net_kwh`, toKWh(d), true);
                              await setStateAsync(`${AGG_BASE}.energy_month_net_kwh`, toKWh(m), true);
                              await setStateAsync(`${AGG_BASE}.energy_year_net_kwh`,  toKWh(y), true);
                              await setStateAsync(`${AGG_BASE}.energy_lifetime_net_wh`,  lf, true);
                              await setStateAsync(`${AGG_BASE}.energy_lifetime_net_kwh`, toKWh(lf), true);
                            }
                            
                            // Start + Zeitpläne
                            (async () => {
                              for (const d of DEVICES) await initDevice(d);
                            
                              schedule('0 0 * * *',      async () => { for (const d of DEVICES) await baselineDay(d);   });
                              schedule('0 0 1 * *',      async () => { for (const d of DEVICES) await baselineMonth(d); });
                              schedule('0 0 1 1 *',      async () => { for (const d of DEVICES) await baselineYear(d);  });
                            
                              schedule('*/1 * * * *', updateAggregates);
                            })();
                            
                            AsgothianA Offline
                            AsgothianA Offline
                            Asgothian
                            Developer
                            schrieb am zuletzt editiert von Asgothian
                            #13

                            @hotspot_2 Hier stand was falsches - ich hatte eine Klammer uebersehen.

                            • Du hast einen heartbeat pro programmiertem Device, an Statt eines Heartbeat welcher beide programmierten Devices behandelt
                            • du hast pro device einen Heartbeat jede Minute, und einen 2. jede 2. Minute, Anstatt einen Heratbeat zu nutzen, der die Funktion des 2 Minuten ablaufs jedes 2. mal ausführt.
                            • Du hast im 2. Watchdog eine re-Init Funktionalität, die letztendlich keinen Sinn macht. Warum ? du versuchst dinge neu zu initialisieren die aber nicht Ursache des ausbleiben eines Events sind. Wenn sich der Ausgangs-DP zu lange nicht ändert (>1 minute) kommt kein Event, und es wird ein re-init angestossen. Dieser dupliziert alle Shedules, ohne zu prüfen ob diese noch existieren.

                            Unterm Strich ist das Skript so eher unbrauchbar. Beschreib doch mal die Basis auf der das ganze beruht - dann kann da ein Vorschlag gemacht werden wie das sauber umgesetzt werden sollte.

                            A.

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

                            hotspot_2H 1 Antwort Letzte Antwort
                            0
                            • AsgothianA Asgothian

                              @hotspot_2 Hier stand was falsches - ich hatte eine Klammer uebersehen.

                              • Du hast einen heartbeat pro programmiertem Device, an Statt eines Heartbeat welcher beide programmierten Devices behandelt
                              • du hast pro device einen Heartbeat jede Minute, und einen 2. jede 2. Minute, Anstatt einen Heratbeat zu nutzen, der die Funktion des 2 Minuten ablaufs jedes 2. mal ausführt.
                              • Du hast im 2. Watchdog eine re-Init Funktionalität, die letztendlich keinen Sinn macht. Warum ? du versuchst dinge neu zu initialisieren die aber nicht Ursache des ausbleiben eines Events sind. Wenn sich der Ausgangs-DP zu lange nicht ändert (>1 minute) kommt kein Event, und es wird ein re-init angestossen. Dieser dupliziert alle Shedules, ohne zu prüfen ob diese noch existieren.

                              Unterm Strich ist das Skript so eher unbrauchbar. Beschreib doch mal die Basis auf der das ganze beruht - dann kann da ein Vorschlag gemacht werden wie das sauber umgesetzt werden sollte.

                              A.

                              hotspot_2H Online
                              hotspot_2H Online
                              hotspot_2
                              schrieb am zuletzt editiert von
                              #14

                              @asgothian Alles klar, vielen vielen Dank für eure Hinweise! Ich finde das super wie gut das hier funktioniert das mal ganz am Rande ;-).

                              Ich habe jetzt mal meine Methode etwas abgeändert. Ich erstelle gerade mit ChatGPT ein Skript was mal auf MQTT Push umstellt und testet wie oft werden die Werte denn aktualisiert. Ist das erfolgreich dann würde ich das Skript mal dahingehend umstellen nur noch auf Änderungen der Werte zu reagieren. Auch die anderen und zahlreichen Hinweise von euch werde ich mal einfließen lassen.

                              Ist es mal ok das ich das mal weiter verfolge und euch dann den Entwurf mal präsentiere. In dem Zug würde ich dann auch meine Idee den Ansatz mal aufzeigen.

                              arteckA 1 Antwort Letzte Antwort
                              0
                              • hotspot_2H hotspot_2

                                @asgothian Alles klar, vielen vielen Dank für eure Hinweise! Ich finde das super wie gut das hier funktioniert das mal ganz am Rande ;-).

                                Ich habe jetzt mal meine Methode etwas abgeändert. Ich erstelle gerade mit ChatGPT ein Skript was mal auf MQTT Push umstellt und testet wie oft werden die Werte denn aktualisiert. Ist das erfolgreich dann würde ich das Skript mal dahingehend umstellen nur noch auf Änderungen der Werte zu reagieren. Auch die anderen und zahlreichen Hinweise von euch werde ich mal einfließen lassen.

                                Ist es mal ok das ich das mal weiter verfolge und euch dann den Entwurf mal präsentiere. In dem Zug würde ich dann auch meine Idee den Ansatz mal aufzeigen.

                                arteckA Offline
                                arteckA Offline
                                arteck
                                Developer Most Active
                                schrieb am zuletzt editiert von arteck
                                #15

                                @hotspot_2 wie währe es mit einer einfachen LOG ausgabe.. was durchlaufen wurde..

                                zigbee hab ich, zwave auch, nuc's genauso und HA auch

                                hotspot_2H 1 Antwort Letzte Antwort
                                0
                                • arteckA arteck

                                  @hotspot_2 wie währe es mit einer einfachen LOG ausgabe.. was durchlaufen wurde..

                                  hotspot_2H Online
                                  hotspot_2H Online
                                  hotspot_2
                                  schrieb am zuletzt editiert von
                                  #16

                                  @arteck Wie meinst Du das konkret?

                                  arteckA 1 Antwort Letzte Antwort
                                  0
                                  • hotspot_2H hotspot_2

                                    @arteck Wie meinst Du das konkret?

                                    arteckA Offline
                                    arteckA Offline
                                    arteck
                                    Developer Most Active
                                    schrieb am zuletzt editiert von
                                    #17

                                    @hotspot_2 siehste das ist der unterschied zwichen einem der Programmiert und programmieren lässt..

                                    in jeder function halt eine console.log('ist durchlaufen ') .. so siehst du wo der hängen bleibt.

                                    zigbee hab ich, zwave auch, nuc's genauso und HA auch

                                    hotspot_2H 1 Antwort Letzte Antwort
                                    0
                                    • arteckA arteck

                                      @hotspot_2 siehste das ist der unterschied zwichen einem der Programmiert und programmieren lässt..

                                      in jeder function halt eine console.log('ist durchlaufen ') .. so siehst du wo der hängen bleibt.

                                      hotspot_2H Online
                                      hotspot_2H Online
                                      hotspot_2
                                      schrieb am zuletzt editiert von
                                      #18

                                      So, ich habe jetzt mal etwas optimiert. Das MQTT Push Thema ist sehr interessant! Das hatte ich bisher so nicht auf dem Schirm. Das eröffnet auch Möglichkeiten mit manchen Dingen ganz anders umzugehen als bisher (Node-Red MQTT abfragen, in Objekte schreiben und dann mit den Objekten arbeiten so bin ich gerade eher unterwegs. Auch mehr mit Blockly und Node Red). Aber Javascript hat mein Interesse geweckt und da ich schon mal Turbo Pascal und Delphi programmiert habe ich etwas Grundwissen Programmierung. Will mich mit ChatGPT Unterstützung da auf jeden Fall weiter einarbeiten.

                                      Hier mal das optimierte Script, wer nochmal drüberschauen möchte und kann ist gerne eingeladen.

                                      1// ===============================================
                                      // BKW_Runtime (no-create version)
                                      // - Legt KEINE States an
                                      // - Schreibt NUR in bestehende States (IDs konfigurierbar)
                                      // - Watchdog/Heartbeat nur per Log (keine Meta-States)
                                      // ===============================================
                                      
                                      // --------------- CONFIG -----------------
                                      const CONFIG = {
                                        DEVICES: [
                                          {
                                            name: 'bkw1',
                                            // Eingangswerte (müssen existieren)
                                            POWER: '0_userdata.0.shellies.sonstiges.bkw1.apower',        // W (aktuelle Leistung)
                                            TOTAL: '0_userdata.0.shellies.sonstiges.bkw1.aenergy_total', // Wh (kumulativ)
                                      
                                            // Basis-Pfad für Ziel-/Interimswerte (müssen existieren!)
                                            BASE:  '0_userdata.0.pvundstrom.bkws.1',
                                          },
                                          {
                                            name: 'bkw2',
                                            POWER: '0_userdata.0.shellies.sonstiges.bkw2.apower',
                                            TOTAL: '0_userdata.0.shellies.sonstiges.bkw2.aenergy_total',
                                            BASE:  '0_userdata.0.pvundstrom.bkws.2',
                                          }
                                        ],
                                      
                                        // Aggregat-Zielpfad (muss existieren!)
                                        AGG_BASE: '0_userdata.0.pvundstrom.bkws.all',
                                      
                                        // Watchdog: Re-Init wenn x Minuten keine Events
                                        WATCHDOG_IDLE_MIN: 1,
                                      };
                                      // ------------- END CONFIG ---------------
                                      
                                      
                                      // ---- State-Builder pro Device (nur IDs, keine Anlage) ----
                                      function S(dev){
                                        const b = dev.BASE;
                                        return {
                                          // Eingänge:
                                          self_w:        `${b}.wr_selfconsumption_w`,
                                      
                                          // Outputs:
                                          power_w:       `${b}.power_w`,
                                          power_net_w:   `${b}.power_net_w`,
                                          producing:     `${b}.producing`,
                                      
                                          dt_wh:         `${b}.energy_today_net_wh`,
                                          mt_wh:         `${b}.energy_month_net_wh`,
                                          yt_wh:         `${b}.energy_year_net_wh`,
                                          dt_kwh:        `${b}.energy_today_net_kwh`,
                                          mt_kwh:        `${b}.energy_month_net_kwh`,
                                          yt_kwh:        `${b}.energy_year_net_kwh`,
                                          lf_wh:         `${b}.energy_lifetime_net_wh`,
                                          lf_kwh:        `${b}.energy_lifetime_net_kwh`,
                                      
                                          // interne Marker (müssen existieren!):
                                          int_last_total:`${b}.int_total_wh_last`,     // letzter TOTAL (Wh)
                                          int_net_eff:   `${b}.int_neteffective_wh`,   // effektiv eingespeiste Wh (nur wenn ap>self)
                                          int_bd:        `${b}.int_baseline_day_net_wh`,
                                          int_bm:        `${b}.int_baseline_month_net_wh`,
                                          int_by:        `${b}.int_baseline_year_net_wh`,
                                        };
                                      }
                                      
                                      // ---- Helpers ----
                                      const n = (v, fb=0) => Number.isFinite(Number(v)) ? Number(v) : fb;
                                      const toKWh = (wh) => Math.round((wh/1000)*1000)/1000;
                                      function val(id){ const s = getState(id); return s ? Number(s.val)||0 : 0; }
                                      
                                      // ---- Logging / Watchdog (OHNE States) ----
                                      let ERRCOUNT = 0;
                                      let lastEvent = Date.now();
                                      const WD_MAX_IDLE_MS = CONFIG.WATCHDOG_IDLE_MIN * 60 * 1000;
                                      
                                      function iso(ts=Date.now()){ return new Date(ts).toISOString(); }
                                      async function safe(label, fn){
                                        try { return await fn(); }
                                        catch(e){
                                          ERRCOUNT++;
                                          log(`[BKW] ${label} FAILED: ${e && e.message ? e.message : e}`, 'warn');
                                        }
                                      }
                                      async function touchEvent(){ lastEvent = Date.now(); }
                                      schedule('*/1 * * * *', () => log(`[BKW] heartbeat ${iso()}`, 'debug'));
                                      schedule('*/2 * * * *', async () => {
                                        const idle = Date.now() - lastEvent;
                                        if (idle > WD_MAX_IDLE_MS) {
                                          log(`[BKW] Watchdog: idle ${Math.round(idle/1000)}s → re-init listeners`, 'warn');
                                          for (const d of CONFIG.DEVICES) await safe(`reinit.${d.name}`, async () => initDevice(d));
                                          await safe('updateAggregates.watchdog', updateAggregates);
                                          lastEvent = Date.now();
                                        }
                                      });
                                      
                                      // ---- Kernlogik ----
                                      async function updateProducingFlags(dev, apNow){
                                        const s = S(dev);
                                        const ap = apNow != null ? apNow : n((await getStateAsync(dev.POWER))?.val, 0);
                                        const selfW = n((await getStateAsync(s.self_w))?.val, 0);
                                        const producing = ap > selfW;
                                      
                                        await setStateAsync(s.power_w, ap, true);
                                        await setStateAsync(s.power_net_w, Math.max(0, ap - selfW), true);
                                        await setStateAsync(s.producing, producing, true);
                                      }
                                      
                                      async function writeNet(dev){
                                        const s = S(dev);
                                        const netEff = n((await getStateAsync(s.int_net_eff))?.val, 0);
                                        const bd = n((await getStateAsync(s.int_bd))?.val, 0);
                                        const bm = n((await getStateAsync(s.int_bm))?.val, 0);
                                        const by = n((await getStateAsync(s.int_by))?.val, 0);
                                      
                                        const d = Math.max(0, netEff - bd);
                                        const m = Math.max(0, netEff - bm);
                                        const y = Math.max(0, netEff - by);
                                      
                                        await setStateAsync(s.dt_wh, d, true);
                                        await setStateAsync(s.mt_wh, m, true);
                                        await setStateAsync(s.yt_wh, y, true);
                                        await setStateAsync(s.dt_kwh, toKWh(d), true);
                                        await setStateAsync(s.mt_kwh, toKWh(m), true);
                                        await setStateAsync(s.yt_kwh, toKWh(y), true);
                                        await setStateAsync(s.lf_wh,  netEff, true);
                                        await setStateAsync(s.lf_kwh, toKWh(netEff), true);
                                      }
                                      
                                      async function initDevice(dev){
                                        const s = S(dev);
                                      
                                        // Initiale Flags
                                        await safe(`init.updateProducingFlags.${dev.name}`, async () => updateProducingFlags(dev));
                                      
                                        // Merker laden
                                        const totalNow = n((await getStateAsync(dev.TOTAL))?.val, 0);
                                        const lastInit = n((await getStateAsync(s.int_last_total))?.val, NaN);
                                        if (!Number.isFinite(lastInit)) {
                                          // NICHT anlegen – vorausgesetzt, der State existiert
                                          await setStateAsync(s.int_last_total, totalNow, true);
                                        }
                                      
                                        const netEffInit = n((await getStateAsync(s.int_net_eff))?.val, NaN);
                                        if (!Number.isFinite(netEffInit)) {
                                          await setStateAsync(s.int_net_eff, 0, true);
                                        }
                                      
                                        const netEff = n((await getStateAsync(s.int_net_eff))?.val, 0);
                                        if (!Number.isFinite(n((await getStateAsync(s.int_bd))?.val, NaN))) await setStateAsync(s.int_bd, netEff, true);
                                        if (!Number.isFinite(n((await getStateAsync(s.int_bm))?.val, NaN))) await setStateAsync(s.int_bm, netEff, true);
                                        if (!Number.isFinite(n((await getStateAsync(s.int_by))?.val, NaN))) await setStateAsync(s.int_by, netEff, true);
                                      
                                        await safe(`init.writeNet.${dev.name}`, async () => writeNet(dev));
                                      
                                        // Listener neu registrieren (auch bei Re-Init)
                                        on({ id: dev.POWER, change: 'ne' }, async obj => {
                                          await touchEvent();
                                          await safe(`POWER:${dev.name}`, async () => {
                                            await updateProducingFlags(dev, n(obj.state.val, 0));
                                          });
                                        });
                                      
                                        on({ id: dev.TOTAL, change: 'ne' }, async obj => {
                                          await touchEvent();
                                          await safe(`TOTAL:${dev.name}`, async () => {
                                            const total = n(obj.state.val, 0);
                                            const last  = n((await getStateAsync(s.int_last_total))?.val, 0);
                                      
                                            // Robust gegen Reset: wenn TOTAL kleiner als last → Basis neu setzen, KEIN Delta
                                            if (total < last) {
                                              await setStateAsync(s.int_last_total, total, true);
                                            } else {
                                              const delta = total - last;
                                              await setStateAsync(s.int_last_total, total, true);
                                      
                                              const ap = n((await getStateAsync(dev.POWER))?.val, 0);
                                              const selfW = n((await getStateAsync(s.self_w))?.val, 0);
                                              if (ap > selfW && delta > 0) {
                                                const netEffNew = n((await getStateAsync(s.int_net_eff))?.val, 0) + delta;
                                                await setStateAsync(s.int_net_eff, netEffNew, true);
                                                await writeNet(dev);
                                              }
                                      
                                              await updateProducingFlags(dev, ap);
                                              await updateAggregates();
                                            }
                                          });
                                        });
                                      
                                        on({ id: s.self_w, change: 'ne' }, async () => {
                                          await touchEvent();
                                          await safe(`SELF_W:${dev.name}`, async () => updateProducingFlags(dev));
                                        });
                                      }
                                      
                                      // Baselines (Mitternacht/Monat/Jahr) – schreiben nur in bestehende States
                                      async function baselineDay(dev){
                                        const s=S(dev);
                                        const v=n((await getStateAsync(s.int_net_eff))?.val,0);
                                        await setStateAsync(s.int_bd, v, true);
                                        await writeNet(dev);
                                      }
                                      async function baselineMonth(dev){
                                        const s=S(dev);
                                        const v=n((await getStateAsync(s.int_net_eff))?.val,0);
                                        await setStateAsync(s.int_bm, v, true);
                                        await writeNet(dev);
                                      }
                                      async function baselineYear(dev){
                                        const s=S(dev);
                                        const v=n((await getStateAsync(s.int_net_eff))?.val,0);
                                        await setStateAsync(s.int_by, v, true);
                                        await writeNet(dev);
                                      }
                                      
                                      // Aggregat
                                      async function updateAggregates(){
                                        const AGG = CONFIG.AGG_BASE;
                                        let pRaw=0, pNet=0, d=0, m=0, y=0, lf=0;
                                        for (const dev of CONFIG.DEVICES) {
                                          const s = S(dev);
                                          pRaw += val(s.power_w);
                                          pNet += val(s.power_net_w);
                                          d    += val(s.dt_wh);
                                          m    += val(s.mt_wh);
                                          y    += val(s.yt_wh);
                                          lf   += val(s.lf_wh);
                                        }
                                        await setStateAsync(`${AGG}.power_w`, pRaw, true);
                                        await setStateAsync(`${AGG}.power_net_w`, pNet, true);
                                        await setStateAsync(`${AGG}.producing`, pNet > 0, true);
                                        await setStateAsync(`${AGG}.energy_today_net_wh`, d, true);
                                        await setStateAsync(`${AGG}.energy_month_net_wh`, m, true);
                                        await setStateAsync(`${AGG}.energy_year_net_wh`,  y, true);
                                        await setStateAsync(`${AGG}.energy_today_net_kwh`, toKWh(d), true);
                                        await setStateAsync(`${AGG}.energy_month_net_kwh`, toKWh(m), true);
                                        await setStateAsync(`${AGG}.energy_year_net_kwh`,  toKWh(y), true);
                                        await setStateAsync(`${AGG}.energy_lifetime_net_wh`,  lf, true);
                                        await setStateAsync(`${AGG}.energy_lifetime_net_kwh`, toKWh(lf), true);
                                      }
                                      
                                      // ===== Start + Zeitpläne =====
                                      (async () => {
                                        // Init Geräte & Listener
                                        for (const d of CONFIG.DEVICES) await safe(`initDevice.${d.name}`, async () => initDevice(d));
                                      
                                        // Baselines
                                        schedule('0 0 * * *',      async () => { for (const d of CONFIG.DEVICES) await safe(`baselineDay.${d.name}`,   async () => baselineDay(d));   });
                                        schedule('0 0 1 * *',      async () => { for (const d of CONFIG.DEVICES) await safe(`baselineMonth.${d.name}`, async () => baselineMonth(d)); });
                                        schedule('0 0 1 1 *',      async () => { for (const d of CONFIG.DEVICES) await safe(`baselineYear.${d.name}`,  async () => baselineYear(d));  });
                                      
                                        // Aggregat zyklisch zusätzlich
                                        schedule('*/1 * * * *', async () => safe('updateAggregates.cron', updateAggregates));
                                      
                                        log('[BKW] Script started (no-create mode).', 'info');
                                      })();
                                      
                                      AsgothianA 1 Antwort Letzte Antwort
                                      0
                                      • hotspot_2H hotspot_2

                                        So, ich habe jetzt mal etwas optimiert. Das MQTT Push Thema ist sehr interessant! Das hatte ich bisher so nicht auf dem Schirm. Das eröffnet auch Möglichkeiten mit manchen Dingen ganz anders umzugehen als bisher (Node-Red MQTT abfragen, in Objekte schreiben und dann mit den Objekten arbeiten so bin ich gerade eher unterwegs. Auch mehr mit Blockly und Node Red). Aber Javascript hat mein Interesse geweckt und da ich schon mal Turbo Pascal und Delphi programmiert habe ich etwas Grundwissen Programmierung. Will mich mit ChatGPT Unterstützung da auf jeden Fall weiter einarbeiten.

                                        Hier mal das optimierte Script, wer nochmal drüberschauen möchte und kann ist gerne eingeladen.

                                        1// ===============================================
                                        // BKW_Runtime (no-create version)
                                        // - Legt KEINE States an
                                        // - Schreibt NUR in bestehende States (IDs konfigurierbar)
                                        // - Watchdog/Heartbeat nur per Log (keine Meta-States)
                                        // ===============================================
                                        
                                        // --------------- CONFIG -----------------
                                        const CONFIG = {
                                          DEVICES: [
                                            {
                                              name: 'bkw1',
                                              // Eingangswerte (müssen existieren)
                                              POWER: '0_userdata.0.shellies.sonstiges.bkw1.apower',        // W (aktuelle Leistung)
                                              TOTAL: '0_userdata.0.shellies.sonstiges.bkw1.aenergy_total', // Wh (kumulativ)
                                        
                                              // Basis-Pfad für Ziel-/Interimswerte (müssen existieren!)
                                              BASE:  '0_userdata.0.pvundstrom.bkws.1',
                                            },
                                            {
                                              name: 'bkw2',
                                              POWER: '0_userdata.0.shellies.sonstiges.bkw2.apower',
                                              TOTAL: '0_userdata.0.shellies.sonstiges.bkw2.aenergy_total',
                                              BASE:  '0_userdata.0.pvundstrom.bkws.2',
                                            }
                                          ],
                                        
                                          // Aggregat-Zielpfad (muss existieren!)
                                          AGG_BASE: '0_userdata.0.pvundstrom.bkws.all',
                                        
                                          // Watchdog: Re-Init wenn x Minuten keine Events
                                          WATCHDOG_IDLE_MIN: 1,
                                        };
                                        // ------------- END CONFIG ---------------
                                        
                                        
                                        // ---- State-Builder pro Device (nur IDs, keine Anlage) ----
                                        function S(dev){
                                          const b = dev.BASE;
                                          return {
                                            // Eingänge:
                                            self_w:        `${b}.wr_selfconsumption_w`,
                                        
                                            // Outputs:
                                            power_w:       `${b}.power_w`,
                                            power_net_w:   `${b}.power_net_w`,
                                            producing:     `${b}.producing`,
                                        
                                            dt_wh:         `${b}.energy_today_net_wh`,
                                            mt_wh:         `${b}.energy_month_net_wh`,
                                            yt_wh:         `${b}.energy_year_net_wh`,
                                            dt_kwh:        `${b}.energy_today_net_kwh`,
                                            mt_kwh:        `${b}.energy_month_net_kwh`,
                                            yt_kwh:        `${b}.energy_year_net_kwh`,
                                            lf_wh:         `${b}.energy_lifetime_net_wh`,
                                            lf_kwh:        `${b}.energy_lifetime_net_kwh`,
                                        
                                            // interne Marker (müssen existieren!):
                                            int_last_total:`${b}.int_total_wh_last`,     // letzter TOTAL (Wh)
                                            int_net_eff:   `${b}.int_neteffective_wh`,   // effektiv eingespeiste Wh (nur wenn ap>self)
                                            int_bd:        `${b}.int_baseline_day_net_wh`,
                                            int_bm:        `${b}.int_baseline_month_net_wh`,
                                            int_by:        `${b}.int_baseline_year_net_wh`,
                                          };
                                        }
                                        
                                        // ---- Helpers ----
                                        const n = (v, fb=0) => Number.isFinite(Number(v)) ? Number(v) : fb;
                                        const toKWh = (wh) => Math.round((wh/1000)*1000)/1000;
                                        function val(id){ const s = getState(id); return s ? Number(s.val)||0 : 0; }
                                        
                                        // ---- Logging / Watchdog (OHNE States) ----
                                        let ERRCOUNT = 0;
                                        let lastEvent = Date.now();
                                        const WD_MAX_IDLE_MS = CONFIG.WATCHDOG_IDLE_MIN * 60 * 1000;
                                        
                                        function iso(ts=Date.now()){ return new Date(ts).toISOString(); }
                                        async function safe(label, fn){
                                          try { return await fn(); }
                                          catch(e){
                                            ERRCOUNT++;
                                            log(`[BKW] ${label} FAILED: ${e && e.message ? e.message : e}`, 'warn');
                                          }
                                        }
                                        async function touchEvent(){ lastEvent = Date.now(); }
                                        schedule('*/1 * * * *', () => log(`[BKW] heartbeat ${iso()}`, 'debug'));
                                        schedule('*/2 * * * *', async () => {
                                          const idle = Date.now() - lastEvent;
                                          if (idle > WD_MAX_IDLE_MS) {
                                            log(`[BKW] Watchdog: idle ${Math.round(idle/1000)}s → re-init listeners`, 'warn');
                                            for (const d of CONFIG.DEVICES) await safe(`reinit.${d.name}`, async () => initDevice(d));
                                            await safe('updateAggregates.watchdog', updateAggregates);
                                            lastEvent = Date.now();
                                          }
                                        });
                                        
                                        // ---- Kernlogik ----
                                        async function updateProducingFlags(dev, apNow){
                                          const s = S(dev);
                                          const ap = apNow != null ? apNow : n((await getStateAsync(dev.POWER))?.val, 0);
                                          const selfW = n((await getStateAsync(s.self_w))?.val, 0);
                                          const producing = ap > selfW;
                                        
                                          await setStateAsync(s.power_w, ap, true);
                                          await setStateAsync(s.power_net_w, Math.max(0, ap - selfW), true);
                                          await setStateAsync(s.producing, producing, true);
                                        }
                                        
                                        async function writeNet(dev){
                                          const s = S(dev);
                                          const netEff = n((await getStateAsync(s.int_net_eff))?.val, 0);
                                          const bd = n((await getStateAsync(s.int_bd))?.val, 0);
                                          const bm = n((await getStateAsync(s.int_bm))?.val, 0);
                                          const by = n((await getStateAsync(s.int_by))?.val, 0);
                                        
                                          const d = Math.max(0, netEff - bd);
                                          const m = Math.max(0, netEff - bm);
                                          const y = Math.max(0, netEff - by);
                                        
                                          await setStateAsync(s.dt_wh, d, true);
                                          await setStateAsync(s.mt_wh, m, true);
                                          await setStateAsync(s.yt_wh, y, true);
                                          await setStateAsync(s.dt_kwh, toKWh(d), true);
                                          await setStateAsync(s.mt_kwh, toKWh(m), true);
                                          await setStateAsync(s.yt_kwh, toKWh(y), true);
                                          await setStateAsync(s.lf_wh,  netEff, true);
                                          await setStateAsync(s.lf_kwh, toKWh(netEff), true);
                                        }
                                        
                                        async function initDevice(dev){
                                          const s = S(dev);
                                        
                                          // Initiale Flags
                                          await safe(`init.updateProducingFlags.${dev.name}`, async () => updateProducingFlags(dev));
                                        
                                          // Merker laden
                                          const totalNow = n((await getStateAsync(dev.TOTAL))?.val, 0);
                                          const lastInit = n((await getStateAsync(s.int_last_total))?.val, NaN);
                                          if (!Number.isFinite(lastInit)) {
                                            // NICHT anlegen – vorausgesetzt, der State existiert
                                            await setStateAsync(s.int_last_total, totalNow, true);
                                          }
                                        
                                          const netEffInit = n((await getStateAsync(s.int_net_eff))?.val, NaN);
                                          if (!Number.isFinite(netEffInit)) {
                                            await setStateAsync(s.int_net_eff, 0, true);
                                          }
                                        
                                          const netEff = n((await getStateAsync(s.int_net_eff))?.val, 0);
                                          if (!Number.isFinite(n((await getStateAsync(s.int_bd))?.val, NaN))) await setStateAsync(s.int_bd, netEff, true);
                                          if (!Number.isFinite(n((await getStateAsync(s.int_bm))?.val, NaN))) await setStateAsync(s.int_bm, netEff, true);
                                          if (!Number.isFinite(n((await getStateAsync(s.int_by))?.val, NaN))) await setStateAsync(s.int_by, netEff, true);
                                        
                                          await safe(`init.writeNet.${dev.name}`, async () => writeNet(dev));
                                        
                                          // Listener neu registrieren (auch bei Re-Init)
                                          on({ id: dev.POWER, change: 'ne' }, async obj => {
                                            await touchEvent();
                                            await safe(`POWER:${dev.name}`, async () => {
                                              await updateProducingFlags(dev, n(obj.state.val, 0));
                                            });
                                          });
                                        
                                          on({ id: dev.TOTAL, change: 'ne' }, async obj => {
                                            await touchEvent();
                                            await safe(`TOTAL:${dev.name}`, async () => {
                                              const total = n(obj.state.val, 0);
                                              const last  = n((await getStateAsync(s.int_last_total))?.val, 0);
                                        
                                              // Robust gegen Reset: wenn TOTAL kleiner als last → Basis neu setzen, KEIN Delta
                                              if (total < last) {
                                                await setStateAsync(s.int_last_total, total, true);
                                              } else {
                                                const delta = total - last;
                                                await setStateAsync(s.int_last_total, total, true);
                                        
                                                const ap = n((await getStateAsync(dev.POWER))?.val, 0);
                                                const selfW = n((await getStateAsync(s.self_w))?.val, 0);
                                                if (ap > selfW && delta > 0) {
                                                  const netEffNew = n((await getStateAsync(s.int_net_eff))?.val, 0) + delta;
                                                  await setStateAsync(s.int_net_eff, netEffNew, true);
                                                  await writeNet(dev);
                                                }
                                        
                                                await updateProducingFlags(dev, ap);
                                                await updateAggregates();
                                              }
                                            });
                                          });
                                        
                                          on({ id: s.self_w, change: 'ne' }, async () => {
                                            await touchEvent();
                                            await safe(`SELF_W:${dev.name}`, async () => updateProducingFlags(dev));
                                          });
                                        }
                                        
                                        // Baselines (Mitternacht/Monat/Jahr) – schreiben nur in bestehende States
                                        async function baselineDay(dev){
                                          const s=S(dev);
                                          const v=n((await getStateAsync(s.int_net_eff))?.val,0);
                                          await setStateAsync(s.int_bd, v, true);
                                          await writeNet(dev);
                                        }
                                        async function baselineMonth(dev){
                                          const s=S(dev);
                                          const v=n((await getStateAsync(s.int_net_eff))?.val,0);
                                          await setStateAsync(s.int_bm, v, true);
                                          await writeNet(dev);
                                        }
                                        async function baselineYear(dev){
                                          const s=S(dev);
                                          const v=n((await getStateAsync(s.int_net_eff))?.val,0);
                                          await setStateAsync(s.int_by, v, true);
                                          await writeNet(dev);
                                        }
                                        
                                        // Aggregat
                                        async function updateAggregates(){
                                          const AGG = CONFIG.AGG_BASE;
                                          let pRaw=0, pNet=0, d=0, m=0, y=0, lf=0;
                                          for (const dev of CONFIG.DEVICES) {
                                            const s = S(dev);
                                            pRaw += val(s.power_w);
                                            pNet += val(s.power_net_w);
                                            d    += val(s.dt_wh);
                                            m    += val(s.mt_wh);
                                            y    += val(s.yt_wh);
                                            lf   += val(s.lf_wh);
                                          }
                                          await setStateAsync(`${AGG}.power_w`, pRaw, true);
                                          await setStateAsync(`${AGG}.power_net_w`, pNet, true);
                                          await setStateAsync(`${AGG}.producing`, pNet > 0, true);
                                          await setStateAsync(`${AGG}.energy_today_net_wh`, d, true);
                                          await setStateAsync(`${AGG}.energy_month_net_wh`, m, true);
                                          await setStateAsync(`${AGG}.energy_year_net_wh`,  y, true);
                                          await setStateAsync(`${AGG}.energy_today_net_kwh`, toKWh(d), true);
                                          await setStateAsync(`${AGG}.energy_month_net_kwh`, toKWh(m), true);
                                          await setStateAsync(`${AGG}.energy_year_net_kwh`,  toKWh(y), true);
                                          await setStateAsync(`${AGG}.energy_lifetime_net_wh`,  lf, true);
                                          await setStateAsync(`${AGG}.energy_lifetime_net_kwh`, toKWh(lf), true);
                                        }
                                        
                                        // ===== Start + Zeitpläne =====
                                        (async () => {
                                          // Init Geräte & Listener
                                          for (const d of CONFIG.DEVICES) await safe(`initDevice.${d.name}`, async () => initDevice(d));
                                        
                                          // Baselines
                                          schedule('0 0 * * *',      async () => { for (const d of CONFIG.DEVICES) await safe(`baselineDay.${d.name}`,   async () => baselineDay(d));   });
                                          schedule('0 0 1 * *',      async () => { for (const d of CONFIG.DEVICES) await safe(`baselineMonth.${d.name}`, async () => baselineMonth(d)); });
                                          schedule('0 0 1 1 *',      async () => { for (const d of CONFIG.DEVICES) await safe(`baselineYear.${d.name}`,  async () => baselineYear(d));  });
                                        
                                          // Aggregat zyklisch zusätzlich
                                          schedule('*/1 * * * *', async () => safe('updateAggregates.cron', updateAggregates));
                                        
                                          log('[BKW] Script started (no-create mode).', 'info');
                                        })();
                                        
                                        AsgothianA Offline
                                        AsgothianA Offline
                                        Asgothian
                                        Developer
                                        schrieb am zuletzt editiert von
                                        #19

                                        @hotspot_2 Was ist da optimiert ? Ich sehe keine Unterschiede zum oben geposteten skript.

                                        Hast du das alte Skript gepostet, oder war die Optimierung eher extern vom Skript ?

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

                                        hotspot_2H 1 Antwort Letzte Antwort
                                        0
                                        • AsgothianA Asgothian

                                          @hotspot_2 Was ist da optimiert ? Ich sehe keine Unterschiede zum oben geposteten skript.

                                          Hast du das alte Skript gepostet, oder war die Optimierung eher extern vom Skript ?

                                          hotspot_2H Online
                                          hotspot_2H Online
                                          hotspot_2
                                          schrieb am zuletzt editiert von
                                          #20

                                          @asgothian Ok. Ich habe jetzt nochmal von vorne gestartet und reagiere jetzt auf MQTT Push bei Änderungen von den Leistungswerten und schreibe nur das mal in Objekte. Leistung BKW1, Leistung BKW2 und Gesamtleistung.

                                          Jetzt schau ich mir mal an wie stabil das läuft und dann gehe ich weiter um die Tages-, Monats- und Jahresleistung zu berechnen.

                                          // ===============================================
                                          // BKW Live Power (MQTT JSON parse, no-create, sync)
                                          // - Liest MQTT-JSON aus status.switch:0 (Shelly Plus Plug S)
                                          // - Netto-Leistung je BKW = max(0, apower - wr_selfconsumption_w)
                                          // - Gesamtleistung = Summe der Netto-Leistungen
                                          // - Legt KEINE States an (schreibt nur in vorhandene Objekte)
                                          // - Nutzt getState/setState (ressourcenschonend)
                                          // - Schreibt nur bei echter Änderung (mit Toleranz) + bündelt Aggregat
                                          // ===============================================
                                          
                                          // ---------- KONSTANTEN: HIER ANPASSEN ----------
                                          const MQTT_JSON_BKW1 = 'mqtt.0.shellies.sonstiges.bkw1.status.switch:0';
                                          const MQTT_JSON_BKW2 = 'mqtt.0.shellies.sonstiges.bkw2.status.switch:0';
                                          
                                          // Eigenverbrauch (W) je BKW (Objekte existieren bereits; sonst wird nur gewarnt)
                                          const SELF_BKW1      = '0_userdata.0.pvundstrom.bkws.1.wr_selfconsumption_w';
                                          const SELF_BKW2      = '0_userdata.0.pvundstrom.bkws.2.wr_selfconsumption_w';
                                          
                                          // Ziel-States (müssen existieren; number, role=value.power, unit=W)
                                          const OUT_PWR_BKW1   = '0_userdata.0.pvundstrom.bkws.1.power_w';
                                          const OUT_PWR_BKW2   = '0_userdata.0.pvundstrom.bkws.2.power_w';
                                          const OUT_PWR_ALL    = '0_userdata.0.pvundstrom.bkws.all.power_w';
                                          
                                          // Toleranz & Aggregat-Entprellung
                                          const EPS_W = 1;              // nur schreiben, wenn Änderung > 1 W
                                          const AGG_DEBOUNCE_MS = 300;  // bündelt schnelle Mehrfachänderungen
                                          
                                          // ---------- interner Aufbau ----------
                                          const DEVICES = [
                                            { name: 'bkw1', inJsonId: MQTT_JSON_BKW1, selfId: SELF_BKW1, outId: OUT_PWR_BKW1 },
                                            { name: 'bkw2', inJsonId: MQTT_JSON_BKW2, selfId: SELF_BKW2, outId: OUT_PWR_BKW2 },
                                          ];
                                          
                                          // ---------- Helpers ----------
                                          const n = (v, fb=0) => Number.isFinite(Number(v)) ? Number(v) : fb;
                                          
                                          const _existCache = new Map();
                                          function objExists(id) {
                                            if (_existCache.has(id)) return _existCache.get(id);
                                            const ok = !!getObject(id);
                                            _existCache.set(id, ok);
                                            if (!ok) log(`[BKW] Objekt existiert nicht: ${id}`, 'warn');
                                            return ok;
                                          }
                                          
                                          // schreibt nur, wenn Ziel existiert UND sich der Wert (mit EPS) geändert hat
                                          function setChangedNoCreate(id, nextVal, eps = 0, ack = true) {
                                            if (!objExists(id)) return; // KEINE Anlage
                                            const cur = getState(id);
                                            const curVal = cur ? cur.val : undefined;
                                          
                                            let same = false;
                                            if (typeof nextVal === 'number') {
                                              same = Number.isFinite(Number(curVal)) && Math.abs(Number(curVal) - Number(nextVal)) <= eps;
                                            } else {
                                              same = curVal === nextVal;
                                            }
                                            if (same) return;
                                          
                                            setState(id, nextVal, ack);
                                          }
                                          
                                          // robustes JSON-Parsing für status.switch:0 → apower (W)
                                          function parseApowerFromState(stateObj) {
                                            if (!stateObj || typeof stateObj.val !== 'string') return 0;
                                            try {
                                              const json = JSON.parse(stateObj.val);
                                              const ap = Number(json?.apower);
                                              return Number.isFinite(ap) ? ap : 0;
                                            } catch (e) {
                                              const sample = typeof stateObj.val === 'string' ? stateObj.val.slice(0, 120) : '<non-string>';
                                              log(`[BKW] JSON parse failed (${sample}): ${e.message}`, 'warn');
                                              return 0;
                                            }
                                          }
                                          
                                          // Netto-Leistung: max(0, apower - self)
                                          function computeNetPower(dev) {
                                            const sJson = getState(dev.inJsonId);
                                            const sSelf = getState(dev.selfId);
                                            const ap    = parseApowerFromState(sJson);
                                            const self  = n(sSelf?.val, 0);
                                            const net   = Math.max(0, ap - self);
                                            return { ap, self, net };
                                          }
                                          
                                          // ---------- Aggregat ----------
                                          let aggTimer = null;
                                          function scheduleAgg() {
                                            if (aggTimer) return;
                                            aggTimer = setTimeout(() => {
                                              aggTimer = null;
                                              try {
                                                let sum = 0;
                                                for (const d of DEVICES) {
                                                  if (!objExists(d.outId)) continue;
                                                  const s = getState(d.outId);
                                                  sum += s ? n(s.val, 0) : 0;
                                                }
                                                setChangedNoCreate(OUT_PWR_ALL, sum, EPS_W, true);
                                              } catch (e) {
                                                log(`[BKW] update aggregate failed: ${e && e.message ? e.message : e}`, 'warn');
                                              }
                                            }, AGG_DEBOUNCE_MS);
                                          }
                                          
                                          // ---------- Start ----------
                                          (() => {
                                            try {
                                              // Existenz der benutzten IDs einmalig prüfen (ohne Anlegen)
                                              for (const d of DEVICES) {
                                                objExists(d.inJsonId);
                                                objExists(d.selfId);
                                                objExists(d.outId);
                                              }
                                              objExists(OUT_PWR_ALL);
                                          
                                              // Initiale Übernahme (rein aus ioBroker-States, kein Gerät-Poll)
                                              for (const d of DEVICES) {
                                                if (!objExists(d.inJsonId) || !objExists(d.outId)) continue;
                                                if (!objExists(d.selfId)) log(`[BKW] Hinweis: Eigenverbrauchs-Objekt fehlt für ${d.name} → wird als 0 W behandelt`, 'warn');
                                          
                                                const { net } = computeNetPower(d);
                                                setChangedNoCreate(d.outId, net, EPS_W, true);
                                              }
                                              scheduleAgg();
                                          
                                              // Event-Listener: auf Änderungen am JSON ODER am Eigenverbrauch reagieren
                                              for (const d of DEVICES) {
                                                // MQTT JSON (status.switch:0)
                                                if (objExists(d.inJsonId)) {
                                                  on({ id: d.inJsonId, change: 'ne' }, (obj) => {
                                                    try {
                                                      const ap = parseApowerFromState(obj.state);
                                                      const selfS = getState(d.selfId);
                                                      const self = n(selfS?.val, 0);
                                                      const net = Math.max(0, ap - self);
                                                      setChangedNoCreate(d.outId, net, EPS_W, true);
                                                      scheduleAgg();
                                                    } catch (e) {
                                                      log(`[BKW] onJSON ${d.name} failed: ${e && e.message ? e.message : e}`, 'warn');
                                                    }
                                                  });
                                                }
                                                // Eigenverbrauch
                                                if (objExists(d.selfId)) {
                                                  on({ id: d.selfId, change: 'ne' }, () => {
                                                    try {
                                                      const { net } = computeNetPower(d);
                                                      setChangedNoCreate(d.outId, net, EPS_W, true);
                                                      scheduleAgg();
                                                    } catch (e) {
                                                      log(`[BKW] onSelf ${d.name} failed: ${e && e.message ? e.message : e}`, 'warn');
                                                    }
                                                  });
                                                }
                                              }
                                          
                                              log('[BKW] Live-Power Script gestartet (MQTT JSON, no-create, sync).', 'info');
                                            } catch (e) {
                                              log(`[BKW] init failed: ${e && e.message ? e.message : e}`, 'error');
                                            }
                                          })();
                                          
                                          arteckA 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

                                          783

                                          Online

                                          32.6k

                                          Benutzer

                                          82.1k

                                          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