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. Entwicklung
  4. [Neuer Adapter] Senec Home Adapter

NEWS

  • UPDATE 31.10.: Amazon Alexa - ioBroker Skill läuft aus ?
    apollon77A
    apollon77
    48
    3
    8.6k

  • Monatsrückblick – September 2025
    BluefoxB
    Bluefox
    13
    1
    2.1k

  • Neues Video "KI im Smart Home" - ioBroker plus n8n
    BluefoxB
    Bluefox
    16
    1
    2.8k

[Neuer Adapter] Senec Home Adapter

Geplant Angeheftet Gesperrt Verschoben Entwicklung
photovoltaiksenecadapter
386 Beiträge 70 Kommentatoren 92.5k Aufrufe 67 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.
  • S Semmy

    @icebear Ich bekomme den gleichen Fehler.

    D Offline
    D Offline
    dispo112
    schrieb am zuletzt editiert von
    #359

    @oxident
    Wenn ihr das Skript nochmal startet - taucht der Fehler dann wieder auf? Oder nur beim Initial Start?

    icebearI S 2 Antworten Letzte Antwort
    0
    • D dispo112

      @oxident
      Wenn ihr das Skript nochmal startet - taucht der Fehler dann wieder auf? Oder nur beim Initial Start?

      icebearI Offline
      icebearI Offline
      icebear
      schrieb am zuletzt editiert von
      #360

      @dispo112

      Der Fehler kommt auch nach einem erneuten Start des Script.

      1 Antwort Letzte Antwort
      0
      • D dispo112

        @oxident
        Wenn ihr das Skript nochmal startet - taucht der Fehler dann wieder auf? Oder nur beim Initial Start?

        S Offline
        S Offline
        Semmy
        schrieb am zuletzt editiert von
        #361

        @dispo112 Der Fehler kommt immer wieder.

        D 1 Antwort Letzte Antwort
        0
        • S Semmy

          @dispo112 Der Fehler kommt immer wieder.

          D Offline
          D Offline
          dispo112
          schrieb am zuletzt editiert von
          #362

          @semmy Seltsam, hatte alle Fehler behoben und es jetzt 1:1 bei mir herauskopiert. 🤔

          Schaue ich mir nachher an!

          icebearI 1 Antwort Letzte Antwort
          0
          • D dispo112

            @semmy Seltsam, hatte alle Fehler behoben und es jetzt 1:1 bei mir herauskopiert. 🤔

            Schaue ich mir nachher an!

            icebearI Offline
            icebearI Offline
            icebear
            schrieb am zuletzt editiert von
            #363

            @dispo112

            Ich glaub es reicht wenn du 'createChannel' durch 'createState' ersetzt.

            // --- Ordner (Channel) anlegen, falls nicht vorhanden ---
            if (!existsObject(BASE_DP_PATH)) {
               createState(BASE_DP_PATH, 'Ordner für Energie-Datenpunkte', (err) => {
                   if (err) {
                       log(`Fehler beim Erstellen des Ordners ${BASE_DP_PATH}: ${err}`, 'error');
                   } else {
                       log(`Ordner ${BASE_DP_PATH} erfolgreich erstellt`, 'info');
                   }
               });
            }
            
            1 Antwort Letzte Antwort
            0
            • S Offline
              S Offline
              Semmy
              schrieb am zuletzt editiert von
              #364

              Ok, funktioniert jetzt. Wie bekommt man die Datenpunkte in Home Assistant?

              Viele Grüße
              Semmy

              icebearI 1 Antwort Letzte Antwort
              0
              • S Semmy

                Ok, funktioniert jetzt. Wie bekommt man die Datenpunkte in Home Assistant?

                Viele Grüße
                Semmy

                icebearI Offline
                icebearI Offline
                icebear
                schrieb am zuletzt editiert von
                #365

                @semmy said in [Neuer Adapter] Senec Home Adapter:

                Wie bekommt man die Datenpunkte in Home Assistant?

                Also ich mach das bei einem anderen Projekt mit MQTT.

                1 Antwort Letzte Antwort
                0
                • icebearI Offline
                  icebearI Offline
                  icebear
                  schrieb am zuletzt editiert von icebear
                  #366

                  @dispo112 said in [Neuer Adapter] Senec Home Adapter:

                  So, bitte schön. Die Ordnerpfade sind alle standard. Theoretisch könnt ihr das Skript importieren und starten, fertig. Alle neuen Datenpunkte werden im Userdata erzeugt und können dann via Lovelace / VIS abgegriffen werden.

                  Nochmal vielen Dank für deine Arbeit. Läuft bei mir seit gestern und die Werte sind soweit völlig O.K.

                  Ich hab mich jetzt auch entschieden, nicht mehr darauf zu Warten ob irgendeiner etwas bereitstellt das die API oder die Werte über mein-senec abgegriffen werden. Die Klimzüge über HA sind mir zu aufwendig und keiner weiß wie lange das dann funktioniert bevor Senec da wieder den Riegel vorschiebt.
                  Solange wie der Adapter mir die Live-Daten zur Verfügung stellt reicht mir das.

                  Ich hab deshalb zusätzlich zu dem Script von @dispo112 noch drei weitere Scripte bei mir implementiert, die laufen seit gestern und liefern meines Erachtens ausreichend genaue Werte, so das sich eine gewisse Statistik aufrechterhalten lässt.

                  Hier die drei Scripte die ich zusätzlich noch implementiert hab:

                  1. Hausverbrauch (schreibt die Werte in zwei DP's , einmal Wh und einmal kWh und wird täglich um 00:00 Uhr auf '0' gesetzt)
                  // ====== Konfiguration START ======
                  
                  // ID des Datenpunkts, der den aktuellen Hausverbrauch in Watt (W) liefert.
                  // Diesen Wert MUSST du an deine ioBroker-Installation anpassen!
                  // Beispiel: 'shelly.0.shellypower.power' oder 'modbus.0.holdingRegisters.power_total'
                  const currentHouseConsumptionPowerId = "senec.0.ENERGY.GUI_HOUSE_POW";
                  
                  // ID des Datenpunkts für den täglichen Hausverbrauch in Wh (wird erstellt, falls nicht vorhanden)
                  const dailyHouseConsumptionWhId = "0_userdata.0.Energie.Senec.Tages_Hausverbrauch_Wh";
                  // ID des Datenpunkts für den täglichen Hausverbrauch in kWh (wird erstellt, falls nicht vorhanden)
                  const dailyHouseConsumptionKWhId = "0_userdata.0.Energie.Senec.Tages_Hausverbrauch_kWh";
                  
                  // ====== Konfiguration ENDE ======
                  
                  
                  // Globale Variablen für die Berechnung
                  let lastPowerValue = 0; // Letzter bekannter Leistungswert
                  let lastUpdateTime = new Date().getTime(); // Zeitpunkt der letzten Aktualisierung in Millisekunden
                  
                  // --- Hilfsfunktionen ---
                  
                  // Funktion zum Erstellen der notwendigen Datenpunkte (States)
                  function createMyStates() {
                      createState(dailyHouseConsumptionWhId, 0, {
                          name: 'Täglicher Hausverbrauch (Wh)',
                          type: 'number',
                          read: true,
                          write: false,
                          role: 'value.power.consumption',
                          unit: 'Wh',
                          desc: 'Summierter Hausverbrauch für den aktuellen Tag in Wattstunden'
                      });
                      createState(dailyHouseConsumptionKWhId, 0, {
                          name: 'Täglicher Hausverbrauch (kWh)',
                          type: 'number',
                          read: true,
                          write: false,
                          role: 'value.power.consumption',
                          unit: 'kWh',
                          desc: 'Summierter Hausverbrauch für den aktuellen Tag in Kilowattstunden'
                      });
                      log("Datenpunkte für den Hausverbrauch überprüft/erstellt.");
                  }
                  
                  // Funktion, um den initialen Wert aus dem Datenpunkt zu lesen und zu loggen
                  async function initializeConsumptionValues() {
                      const state = await getStateAsync(dailyHouseConsumptionWhId);
                      if (state && state.val !== null) {
                          log(`Initialer Wert für täglichen Hausverbrauch Wh: ${state.val} Wh`);
                      } else {
                          setState(dailyHouseConsumptionWhId, 0, true);
                          setState(dailyHouseConsumptionKWhId, 0, true);
                          log(`Datenpunkte ${dailyHouseConsumptionWhId} und ${dailyHouseConsumptionKWhId} auf 0 gesetzt.`);
                      }
                  }
                  
                  // --- Hauptlogik ---
                  
                  // 1. Beim Start des Skripts: Datenpunkte erstellen und initialisieren
                  createMyStates();
                  initializeConsumptionValues();
                  
                  // 2. Trigger bei Änderung des Hausverbrauchs-Datenpunkts
                  on({ id: currentHouseConsumptionPowerId, change: 'ne' }, async function (obj) {
                      const currentPower = parseFloat(obj.state.val); // Aktueller Leistungswert in Watt
                  
                      // Prüfen, ob der Wert gültig ist
                      if (isNaN(currentPower)) {
                          log(`Ungültiger Leistungswert erhalten: ${obj.state.val}. Berechnung übersprungen.`, 'warn');
                          return;
                      }
                  
                      const currentTime = new Date().getTime(); // Aktueller Zeitstempel in Millisekunden
                  
                      // Initialisierung von lastPowerValue und lastUpdateTime beim ersten Trigger
                      if (lastPowerValue === 0 && lastUpdateTime === new Date().getTime()) {
                          const powerState = getState(currentHouseConsumptionPowerId);
                          if (powerState && powerState.val !== null) {
                              lastPowerValue = parseFloat(powerState.val);
                          } else {
                              lastPowerValue = 0; // Fallback
                          }
                          lastUpdateTime = currentTime;
                          log("Initialisierung der Leistungswerte beim ersten Trigger.");
                          return;
                      }
                  
                      const timeDiffSeconds = (currentTime - lastUpdateTime) / 1000; // Zeitdifferenz in Sekunden
                  
                      // Falls keine Zeit vergangen ist (z.B. zu schnelle Updates oder gleicher Zeitstempel)
                      if (timeDiffSeconds <= 0) {
                          // log("Zeitdifferenz ist 0 oder negativ, Überspringe Berechnung.", 'debug'); // Kann viele Logs verursachen
                          return;
                      }
                  
                      // Berechnung der Energie: Leistung (W) * Zeit (s) = Wattsekunden (Ws)
                      const energyWs = currentPower * timeDiffSeconds;
                      // Umrechnung von Wattsekunden in Wattstunden (Ws / 3600 = Wh)
                      const energyWh = energyWs / 3600;
                  
                      log(`Aktuelle Leistung: ${currentPower.toFixed(2)} W, Zeitdiff: ${timeDiffSeconds.toFixed(2)} s, Berechnete Energie: ${energyWh.toFixed(2)} Wh`);
                  
                      // Aktuellen summierten Verbrauch von ioBroker lesen und sicherstellen, dass es eine Zahl ist
                      let currentDailyConsumptionWh = parseFloat((await getStateAsync(dailyHouseConsumptionWhId)).val) || 0;
                  
                      // Energie zum Tagesverbrauch addieren
                      currentDailyConsumptionWh += energyWh;
                  
                      // Werte in die Datenpunkte schreiben
                      setState(dailyHouseConsumptionWhId, currentDailyConsumptionWh.toFixed(2), true); // Wh auf 2 Nachkommastellen
                      setState(dailyHouseConsumptionKWhId, (currentDailyConsumptionWh / 1000).toFixed(3), true); // kWh auf 3 Nachkommastellen
                  
                      log(`Hausverbrauch addiert. Neue Summe: ${currentDailyConsumptionWh.toFixed(2)} Wh (${(currentDailyConsumptionWh / 1000).toFixed(3)} kWh)`);
                  
                      // Werte für die nächste Iteration speichern
                      lastPowerValue = currentPower;
                      lastUpdateTime = currentTime;
                  });
                  
                  // 3. Reset der Tagessummen um Mitternacht
                  schedule('0 0 * * *', async function () {
                      log("Mitternacht erreicht, setze täglichen Hausverbrauch zurück.");
                      setState(dailyHouseConsumptionWhId, 0, true);
                      setState(dailyHouseConsumptionKWhId, 0, true);
                  
                      // Wichtig: lastUpdateTime muss auch zurückgesetzt werden für korrekte delta-t Berechnung am neuen Tag
                      // und lastPowerValue für den ersten Wert des neuen Tages
                      lastUpdateTime = new Date().getTime();
                      lastPowerValue = parseFloat((await getStateAsync(currentHouseConsumptionPowerId)).val) || 0; // Aktuellen Power-Wert erneut holen
                  
                      log("Täglicher Hausverbrauch wurde zurückgesetzt.");
                  });
                  
                  // Optional: Info-Log beim Start des Skripts
                  log("Skript zum Überwachen des täglichen Hausverbrauchs gestartet.");
                  
                  1. Akku Be-und Entladung (schreibt die Werte (batIn und batOut) in DP's , einmal Wh und einmal kWh und wird täglich um 00:00 Uhr auf '0' gesetzt)
                  // ====== Konfiguration START ======
                  // Datenpunkt-ID, die die aktuelle Leistung in Watt liefert.
                  // Negativ für BatOut, Positiv für BatIn.
                  // Diesen Wert musst du an deine ioBroker-Installation anpassen!
                  const powerStateId = "senec.0.ENERGY.GUI_BAT_DATA_POWER"; // Beispiel: smartmeter.0.0_1_123_456_789.power_total_current
                  
                  // Datenpunkt-ID für die tägliche BatOut in Wh (wird erstellt, falls nicht vorhanden)
                  const dailyBatOutWhStateId = "0_userdata.0.Energie.Senec.Bat_Out_Wh";
                  // Datenpunkt-ID für die tägliche BatOut in kWh
                  const dailyBatOutKWhStateId = "0_userdata.0.Energie.Senec.Bat_Out_kWh";
                  
                  // Datenpunkt-ID für den täglichen BatIn in Wh (wird erstellt, falls nicht vorhanden)
                  const dailyBatInWhStateId = "0_userdata.0.Energie.Senec.Bat_In_Wh";
                  // Datenpunkt-ID für den täglichen BatIn in kWh
                  const dailyBatInKWhStateId = "0_userdata.0.Energie.Senec.Bat_In_kWh";
                  
                  // ====== Konfiguration ENDE ======
                  
                  
                  // Globale Variablen für die Berechnung der Tagessummen
                  let lastPowerValue = 0; // Letzter bekannter Leistungswert
                  let lastUpdateTime = new Date().getTime(); // Zeitpunkt der letzten Aktualisierung in Millisekunden
                  
                  // Funktion zum Initialisieren der Datenpunkte (falls nicht vorhanden)
                  function createStates() {
                      createState(dailyBatOutWhStateId, 0, {
                          name: 'Daily BatOut (Wh)',
                          type: 'number',
                          read: true,
                          write: false,
                          role: 'value.power.consumption',
                          unit: 'Wh'
                      });
                      createState(dailyBatOutKWhStateId, 0, {
                          name: 'Daily BatOut (kWh)',
                          type: 'number',
                          read: true,
                          write: false,
                          role: 'value.power.consumption',
                          unit: 'kWh'
                      });
                      createState(dailyBatInWhStateId, 0, {
                          name: 'Daily BatIn (Wh)',
                          type: 'number',
                          read: true,
                          write: false,
                          role: 'value.power.consumption',
                          unit: 'Wh'
                      });
                      createState(dailyBatInKWhStateId, 0, {
                          name: 'Daily BatIn (kWh)',
                          type: 'number',
                          read: true,
                          write: false,
                          role: 'value.power.consumption',
                          unit: 'kWh'
                      });
                  }
                  
                  // Beim Start des Skripts Datenpunkte erstellen und initialisieren
                  createStates();
                  
                  // Werte aus den Datenpunkten beim Skriptstart lesen, falls schon vorhanden
                  // Prüfen, ob die Datenpunkte bereits einen Wert haben, ansonsten auf 0 setzen
                  let initialBatOutState = getState(dailyBatOutWhStateId);
                  if (initialBatOutState && initialBatOutState.val !== null) {
                      log(`Initialer Wert für BatOut Wh: ${initialBatOutState.val}`);
                  } else {
                      setState(dailyBatOutWhStateId, 0);
                      log(`Datenpunkt ${dailyBatOutWhStateId} auf 0 gesetzt.`);
                  }
                  
                  let initialBatInState = getState(dailyBatInWhStateId);
                  if (initialBatInState && initialBatInState.val !== null) {
                      log(`Initialer Wert für BatIn Wh: ${initialBatInState.val}`);
                  } else {
                      setState(dailyBatInWhStateId, 0);
                      log(`Datenpunkt ${dailyBatInWhStateId} auf 0 gesetzt.`);
                  }
                  
                  // Trigger bei Änderung des Leistungsdatenpunkts
                  on({ id: powerStateId, change: 'ne' }, async function (obj) {
                      const currentPower = obj.state.val; // Aktueller Leistungswert in Watt
                      const currentTime = new Date().getTime(); // Aktueller Zeitstempel in Millisekunden
                  
                      // Wenn der Wert zum ersten Mal kommt oder Zeitunterschied zu gering ist
                      if (lastPowerValue === 0 && lastUpdateTime === new Date().getTime()) { // Initialisierung
                          lastPowerValue = currentPower;
                          lastUpdateTime = currentTime;
                          log("Initialisierung der Leistungswerte.");
                          return;
                      }
                  
                      const timeDiffSeconds = (currentTime - lastUpdateTime) / 1000; // Zeitdifferenz in Sekunden
                  
                      if (timeDiffSeconds <= 0) { // Falls keine Zeit vergangen ist (z.B. zu schnelle Updates)
                          log("Zeitdifferenz ist 0 oder negativ, Überspringe Berechnung.");
                          return;
                      }
                  
                      // Leistung * Zeit = Energie (Wattsekunden)
                      const energyWs = currentPower * timeDiffSeconds;
                      const energyWh = energyWs / 3600; // Umrechnung von Wattsekunden in Wattstunden
                  
                      log(`Aktuelle Leistung: ${currentPower} W, Zeitdiff: ${timeDiffSeconds.toFixed(2)} s, Berechnete Energie: ${energyWh.toFixed(2)} Wh`);
                  
                      // Sicherstellen, dass die gelesenen Werte Zahlen sind (durch parseFloat oder den Unary-Plus-Operator)
                      let currentBatInWh = parseFloat((await getStateAsync(dailyBatInWhStateId)).val) || 0;
                      let currentBatOutWh = parseFloat((await getStateAsync(dailyBatOutWhStateId)).val) || 0;
                  
                      if (currentPower < 0) { // BatOut
                          currentBatOutWh += Math.abs(energyWh); // Absolutwert, damit die Summe positiv ist
                          setState(dailyBatOutWhStateId, currentBatOutWh.toFixed(2), true);
                          setState(dailyBatOutKWhStateId, (currentBatOutWh / 1000).toFixed(3), true);
                          log(`BatOut addiert. Neue Summe: ${currentBatOutWh.toFixed(2)} Wh`);
                      } else { // BatIn
                          currentBatInWh += energyWh;
                          setState(dailyBatInWhStateId, currentBatInWh.toFixed(2), true);
                          setState(dailyBatInKWhStateId, (currentBatInWh / 1000).toFixed(3), true);
                          log(`BatIn addiert. Neue Summe: ${currentBatInWh.toFixed(2)} Wh`);
                      }
                  
                      // Werte für die nächste Iteration speichern
                      lastPowerValue = currentPower;
                      lastUpdateTime = currentTime;
                  });
                  
                  
                  // Reset der Tagessummen um Mitternacht
                  schedule('0 0 * * *', async function () {
                      log("Mitternacht erreicht, setze Tagessummen zurück.");
                      setState(dailyBatOutWhStateId, 0, true);
                      setState(dailyBatOutKWhStateId, 0, true);
                      setState(dailyBatInWhStateId, 0, true);
                      setState(dailyBatInKWhStateId, 0, true);
                      // lastUpdateTime muss auch zurückgesetzt werden, um korrekte delta-t Berechnung am neuen Tag zu gewährleisten
                      lastUpdateTime = new Date().getTime();
                      lastPowerValue = (await getStateAsync(powerStateId)).val || 0; // Aktuellen Power-Wert erneut holen
                  
                      log("Tagessummen wurden zurückgesetzt.");
                  });
                  
                  // Optional: Für Debugging, wenn das Skript startet
                  log("Skript zum Überwachen von BatOut und BatIn gestartet.");
                  
                  1. Grid Power (schreibt die Werte in DP's (Einspeisung und Netzbezug), einmal Wh und einmal kWh und wird täglich um 00:00 Uhr auf '0' gesetzt)
                  // ====== Konfiguration START ======
                  // Datenpunkt-ID, die die aktuelle Leistung in Watt liefert.
                  // Negativ für Einspeisung, Positiv für Netzbezug.
                  // Diesen Wert musst du an deine ioBroker-Installation anpassen!
                  const powerStateId = "senec.0.ENERGY.GUI_GRID_POW"; // Beispiel: smartmeter.0.0_1_123_456_789.power_total_current
                  
                  // Datenpunkt-ID für die tägliche Einspeisung in Wh (wird erstellt, falls nicht vorhanden)
                  const dailyFeedInWhStateId = "0_userdata.0.Energie.Senec.Tages_Einspeisung_Wh";
                  // Datenpunkt-ID für die tägliche Einspeisung in kWh
                  const dailyFeedInKWhStateId = "0_userdata.0.Energie.Senec.Tages_Einspeisung_kWh";
                  
                  // Datenpunkt-ID für den täglichen Netzbezug in Wh (wird erstellt, falls nicht vorhanden)
                  const dailyGridPurchaseWhStateId = "0_userdata.0.Energie.Senec.Tages_Netzbezug_Wh";
                  // Datenpunkt-ID für den täglichen Netzbezug in kWh
                  const dailyGridPurchaseKWhStateId = "0_userdata.0.Energie.Senec.Tages_Netzbezug_kWh";
                  
                  // ====== Konfiguration ENDE ======
                  
                  
                  // Globale Variablen für die Berechnung der Tagessummen
                  let lastPowerValue = 0; // Letzter bekannter Leistungswert
                  let lastUpdateTime = new Date().getTime(); // Zeitpunkt der letzten Aktualisierung in Millisekunden
                  
                  // Funktion zum Initialisieren der Datenpunkte (falls nicht vorhanden)
                  function createStates() {
                      createState(dailyFeedInWhStateId, 0, {
                          name: 'Tägliche Einspeisung (Wh)',
                          type: 'number',
                          read: true,
                          write: false,
                          role: 'value.power.consumption',
                          unit: 'Wh'
                      });
                      createState(dailyFeedInKWhStateId, 0, {
                          name: 'Tägliche Einspeisung (kWh)',
                          type: 'number',
                          read: true,
                          write: false,
                          role: 'value.power.consumption',
                          unit: 'kWh'
                      });
                      createState(dailyGridPurchaseWhStateId, 0, {
                          name: 'Täglicher Netzbezug (Wh)',
                          type: 'number',
                          read: true,
                          write: false,
                          role: 'value.power.consumption',
                          unit: 'Wh'
                      });
                      createState(dailyGridPurchaseKWhStateId, 0, {
                          name: 'Täglicher Netzbezug (kWh)',
                          type: 'number',
                          read: true,
                          write: false,
                          role: 'value.power.consumption',
                          unit: 'kWh'
                      });
                  }
                  
                  // Beim Start des Skripts Datenpunkte erstellen und initialisieren
                  createStates();
                  
                  // Werte aus den Datenpunkten beim Skriptstart lesen, falls schon vorhanden
                  // Prüfen, ob die Datenpunkte bereits einen Wert haben, ansonsten auf 0 setzen
                  let initialFeedInState = getState(dailyFeedInWhStateId);
                  if (initialFeedInState && initialFeedInState.val !== null) {
                      log(`Initialer Wert für Einspeisung Wh: ${initialFeedInState.val}`);
                  } else {
                      setState(dailyFeedInWhStateId, 0);
                      log(`Datenpunkt ${dailyFeedInWhStateId} auf 0 gesetzt.`);
                  }
                  
                  let initialGridPurchaseState = getState(dailyGridPurchaseWhStateId);
                  if (initialGridPurchaseState && initialGridPurchaseState.val !== null) {
                      log(`Initialer Wert für Netzbezug Wh: ${initialGridPurchaseState.val}`);
                  } else {
                      setState(dailyGridPurchaseWhStateId, 0);
                      log(`Datenpunkt ${dailyGridPurchaseWhStateId} auf 0 gesetzt.`);
                  }
                  
                  // Trigger bei Änderung des Leistungsdatenpunkts
                  on({ id: powerStateId, change: 'ne' }, async function (obj) {
                      const currentPower = obj.state.val; // Aktueller Leistungswert in Watt
                      const currentTime = new Date().getTime(); // Aktueller Zeitstempel in Millisekunden
                  
                      // Wenn der Wert zum ersten Mal kommt oder Zeitunterschied zu gering ist
                      // Hier ist es wichtig, dass lastPowerValue und lastUpdateTime initialisiert werden
                      if (lastPowerValue === 0 && lastUpdateTime === new Date().getTime()) { // Initialisierung
                          const powerState = getState(powerStateId);
                          if (powerState && powerState.val !== null) {
                              lastPowerValue = powerState.val;
                          } else {
                              lastPowerValue = 0; // Fallback, falls kein Wert verfügbar
                          }
                          lastUpdateTime = currentTime;
                          log("Initialisierung der Leistungswerte beim ersten Trigger.");
                          return;
                      }
                  
                  
                      const timeDiffSeconds = (currentTime - lastUpdateTime) / 1000; // Zeitdifferenz in Sekunden
                  
                      if (timeDiffSeconds <= 0) { // Falls keine Zeit vergangen ist (z.B. zu schnelle Updates)
                          log("Zeitdifferenz ist 0 oder negativ, Überspringe Berechnung.");
                          return;
                      }
                  
                      // Leistung * Zeit = Energie (Wattsekunden)
                      const energyWs = currentPower * timeDiffSeconds;
                      const energyWh = energyWs / 3600; // Umrechnung von Wattsekunden in Wattstunden
                  
                      log(`Aktuelle Leistung: ${currentPower} W, Zeitdiff: ${timeDiffSeconds.toFixed(2)} s, Berechnete Energie: ${energyWh.toFixed(2)} Wh`);
                  
                      // **KORRIGIERTER BEREICH START**
                      // Sicherstellen, dass die gelesenen Werte Zahlen sind (durch parseFloat oder den Unary-Plus-Operator)
                      let currentFeedInWh = parseFloat((await getStateAsync(dailyFeedInWhStateId)).val) || 0;
                      let currentGridPurchaseWh = parseFloat((await getStateAsync(dailyGridPurchaseWhStateId)).val) || 0;
                      // **KORRIGIERTER BEREICH ENDE**
                  
                      if (currentPower < 0) { // Einspeisung
                          currentFeedInWh += Math.abs(energyWh); // Absolutwert, damit die Summe positiv ist
                          setState(dailyFeedInWhStateId, currentFeedInWh.toFixed(2), true);
                          setState(dailyFeedInKWhStateId, (currentFeedInWh / 1000).toFixed(3), true);
                          log(`Einspeisung addiert. Neue Summe: ${currentFeedInWh.toFixed(2)} Wh`);
                      } else { // Netzbezug
                          currentGridPurchaseWh += energyWh;
                          setState(dailyGridPurchaseWhStateId, currentGridPurchaseWh.toFixed(2), true);
                          setState(dailyGridPurchaseKWhStateId, (currentGridPurchaseWh / 1000).toFixed(3), true);
                          log(`Netzbezug addiert. Neue Summe: ${currentGridPurchaseWh.toFixed(2)} Wh`);
                      }
                  
                      // Werte für die nächste Iteration speichern
                      lastPowerValue = currentPower;
                      lastUpdateTime = currentTime;
                  });
                  
                  
                  // Reset der Tagessummen um Mitternacht
                  schedule('0 0 * * *', async function () {
                      log("Mitternacht erreicht, setze Tagessummen zurück.");
                      setState(dailyFeedInWhStateId, 0, true);
                      setState(dailyFeedInKWhStateId, 0, true);
                      setState(dailyGridPurchaseWhStateId, 0, true);
                      setState(dailyGridPurchaseKWhStateId, 0, true);
                      // lastUpdateTime muss auch zurückgesetzt werden, um korrekte delta-t Berechnung am neuen Tag zu gewährleisten
                      lastUpdateTime = new Date().getTime();
                      lastPowerValue = (await getStateAsync(powerStateId)).val || 0; // Aktuellen Power-Wert erneut holen
                  
                      log("Tagessummen wurden zurückgesetzt.");
                  });
                  
                  // Optional: Für Debugging, wenn das Skript startet
                  log("Skript zum Überwachen von Einspeisung und Netzbezug gestartet.");
                  

                  wer Lust hat kann ja mit testen ob das so passt.

                  M R 3 Antworten Letzte Antwort
                  2
                  • S Offline
                    S Offline
                    Semmy
                    schrieb am zuletzt editiert von
                    #367

                    Hallo
                    Sieht gut aus bis jetzt. Ist es möglich, für diese Datenpunkte jährliche Datenpunkte zu integrieren?

                    Viele Grüße
                    Semmy

                    1 Antwort Letzte Antwort
                    0
                    • icebearI icebear

                      @dispo112 said in [Neuer Adapter] Senec Home Adapter:

                      So, bitte schön. Die Ordnerpfade sind alle standard. Theoretisch könnt ihr das Skript importieren und starten, fertig. Alle neuen Datenpunkte werden im Userdata erzeugt und können dann via Lovelace / VIS abgegriffen werden.

                      Nochmal vielen Dank für deine Arbeit. Läuft bei mir seit gestern und die Werte sind soweit völlig O.K.

                      Ich hab mich jetzt auch entschieden, nicht mehr darauf zu Warten ob irgendeiner etwas bereitstellt das die API oder die Werte über mein-senec abgegriffen werden. Die Klimzüge über HA sind mir zu aufwendig und keiner weiß wie lange das dann funktioniert bevor Senec da wieder den Riegel vorschiebt.
                      Solange wie der Adapter mir die Live-Daten zur Verfügung stellt reicht mir das.

                      Ich hab deshalb zusätzlich zu dem Script von @dispo112 noch drei weitere Scripte bei mir implementiert, die laufen seit gestern und liefern meines Erachtens ausreichend genaue Werte, so das sich eine gewisse Statistik aufrechterhalten lässt.

                      Hier die drei Scripte die ich zusätzlich noch implementiert hab:

                      1. Hausverbrauch (schreibt die Werte in zwei DP's , einmal Wh und einmal kWh und wird täglich um 00:00 Uhr auf '0' gesetzt)
                      // ====== Konfiguration START ======
                      
                      // ID des Datenpunkts, der den aktuellen Hausverbrauch in Watt (W) liefert.
                      // Diesen Wert MUSST du an deine ioBroker-Installation anpassen!
                      // Beispiel: 'shelly.0.shellypower.power' oder 'modbus.0.holdingRegisters.power_total'
                      const currentHouseConsumptionPowerId = "senec.0.ENERGY.GUI_HOUSE_POW";
                      
                      // ID des Datenpunkts für den täglichen Hausverbrauch in Wh (wird erstellt, falls nicht vorhanden)
                      const dailyHouseConsumptionWhId = "0_userdata.0.Energie.Senec.Tages_Hausverbrauch_Wh";
                      // ID des Datenpunkts für den täglichen Hausverbrauch in kWh (wird erstellt, falls nicht vorhanden)
                      const dailyHouseConsumptionKWhId = "0_userdata.0.Energie.Senec.Tages_Hausverbrauch_kWh";
                      
                      // ====== Konfiguration ENDE ======
                      
                      
                      // Globale Variablen für die Berechnung
                      let lastPowerValue = 0; // Letzter bekannter Leistungswert
                      let lastUpdateTime = new Date().getTime(); // Zeitpunkt der letzten Aktualisierung in Millisekunden
                      
                      // --- Hilfsfunktionen ---
                      
                      // Funktion zum Erstellen der notwendigen Datenpunkte (States)
                      function createMyStates() {
                          createState(dailyHouseConsumptionWhId, 0, {
                              name: 'Täglicher Hausverbrauch (Wh)',
                              type: 'number',
                              read: true,
                              write: false,
                              role: 'value.power.consumption',
                              unit: 'Wh',
                              desc: 'Summierter Hausverbrauch für den aktuellen Tag in Wattstunden'
                          });
                          createState(dailyHouseConsumptionKWhId, 0, {
                              name: 'Täglicher Hausverbrauch (kWh)',
                              type: 'number',
                              read: true,
                              write: false,
                              role: 'value.power.consumption',
                              unit: 'kWh',
                              desc: 'Summierter Hausverbrauch für den aktuellen Tag in Kilowattstunden'
                          });
                          log("Datenpunkte für den Hausverbrauch überprüft/erstellt.");
                      }
                      
                      // Funktion, um den initialen Wert aus dem Datenpunkt zu lesen und zu loggen
                      async function initializeConsumptionValues() {
                          const state = await getStateAsync(dailyHouseConsumptionWhId);
                          if (state && state.val !== null) {
                              log(`Initialer Wert für täglichen Hausverbrauch Wh: ${state.val} Wh`);
                          } else {
                              setState(dailyHouseConsumptionWhId, 0, true);
                              setState(dailyHouseConsumptionKWhId, 0, true);
                              log(`Datenpunkte ${dailyHouseConsumptionWhId} und ${dailyHouseConsumptionKWhId} auf 0 gesetzt.`);
                          }
                      }
                      
                      // --- Hauptlogik ---
                      
                      // 1. Beim Start des Skripts: Datenpunkte erstellen und initialisieren
                      createMyStates();
                      initializeConsumptionValues();
                      
                      // 2. Trigger bei Änderung des Hausverbrauchs-Datenpunkts
                      on({ id: currentHouseConsumptionPowerId, change: 'ne' }, async function (obj) {
                          const currentPower = parseFloat(obj.state.val); // Aktueller Leistungswert in Watt
                      
                          // Prüfen, ob der Wert gültig ist
                          if (isNaN(currentPower)) {
                              log(`Ungültiger Leistungswert erhalten: ${obj.state.val}. Berechnung übersprungen.`, 'warn');
                              return;
                          }
                      
                          const currentTime = new Date().getTime(); // Aktueller Zeitstempel in Millisekunden
                      
                          // Initialisierung von lastPowerValue und lastUpdateTime beim ersten Trigger
                          if (lastPowerValue === 0 && lastUpdateTime === new Date().getTime()) {
                              const powerState = getState(currentHouseConsumptionPowerId);
                              if (powerState && powerState.val !== null) {
                                  lastPowerValue = parseFloat(powerState.val);
                              } else {
                                  lastPowerValue = 0; // Fallback
                              }
                              lastUpdateTime = currentTime;
                              log("Initialisierung der Leistungswerte beim ersten Trigger.");
                              return;
                          }
                      
                          const timeDiffSeconds = (currentTime - lastUpdateTime) / 1000; // Zeitdifferenz in Sekunden
                      
                          // Falls keine Zeit vergangen ist (z.B. zu schnelle Updates oder gleicher Zeitstempel)
                          if (timeDiffSeconds <= 0) {
                              // log("Zeitdifferenz ist 0 oder negativ, Überspringe Berechnung.", 'debug'); // Kann viele Logs verursachen
                              return;
                          }
                      
                          // Berechnung der Energie: Leistung (W) * Zeit (s) = Wattsekunden (Ws)
                          const energyWs = currentPower * timeDiffSeconds;
                          // Umrechnung von Wattsekunden in Wattstunden (Ws / 3600 = Wh)
                          const energyWh = energyWs / 3600;
                      
                          log(`Aktuelle Leistung: ${currentPower.toFixed(2)} W, Zeitdiff: ${timeDiffSeconds.toFixed(2)} s, Berechnete Energie: ${energyWh.toFixed(2)} Wh`);
                      
                          // Aktuellen summierten Verbrauch von ioBroker lesen und sicherstellen, dass es eine Zahl ist
                          let currentDailyConsumptionWh = parseFloat((await getStateAsync(dailyHouseConsumptionWhId)).val) || 0;
                      
                          // Energie zum Tagesverbrauch addieren
                          currentDailyConsumptionWh += energyWh;
                      
                          // Werte in die Datenpunkte schreiben
                          setState(dailyHouseConsumptionWhId, currentDailyConsumptionWh.toFixed(2), true); // Wh auf 2 Nachkommastellen
                          setState(dailyHouseConsumptionKWhId, (currentDailyConsumptionWh / 1000).toFixed(3), true); // kWh auf 3 Nachkommastellen
                      
                          log(`Hausverbrauch addiert. Neue Summe: ${currentDailyConsumptionWh.toFixed(2)} Wh (${(currentDailyConsumptionWh / 1000).toFixed(3)} kWh)`);
                      
                          // Werte für die nächste Iteration speichern
                          lastPowerValue = currentPower;
                          lastUpdateTime = currentTime;
                      });
                      
                      // 3. Reset der Tagessummen um Mitternacht
                      schedule('0 0 * * *', async function () {
                          log("Mitternacht erreicht, setze täglichen Hausverbrauch zurück.");
                          setState(dailyHouseConsumptionWhId, 0, true);
                          setState(dailyHouseConsumptionKWhId, 0, true);
                      
                          // Wichtig: lastUpdateTime muss auch zurückgesetzt werden für korrekte delta-t Berechnung am neuen Tag
                          // und lastPowerValue für den ersten Wert des neuen Tages
                          lastUpdateTime = new Date().getTime();
                          lastPowerValue = parseFloat((await getStateAsync(currentHouseConsumptionPowerId)).val) || 0; // Aktuellen Power-Wert erneut holen
                      
                          log("Täglicher Hausverbrauch wurde zurückgesetzt.");
                      });
                      
                      // Optional: Info-Log beim Start des Skripts
                      log("Skript zum Überwachen des täglichen Hausverbrauchs gestartet.");
                      
                      1. Akku Be-und Entladung (schreibt die Werte (batIn und batOut) in DP's , einmal Wh und einmal kWh und wird täglich um 00:00 Uhr auf '0' gesetzt)
                      // ====== Konfiguration START ======
                      // Datenpunkt-ID, die die aktuelle Leistung in Watt liefert.
                      // Negativ für BatOut, Positiv für BatIn.
                      // Diesen Wert musst du an deine ioBroker-Installation anpassen!
                      const powerStateId = "senec.0.ENERGY.GUI_BAT_DATA_POWER"; // Beispiel: smartmeter.0.0_1_123_456_789.power_total_current
                      
                      // Datenpunkt-ID für die tägliche BatOut in Wh (wird erstellt, falls nicht vorhanden)
                      const dailyBatOutWhStateId = "0_userdata.0.Energie.Senec.Bat_Out_Wh";
                      // Datenpunkt-ID für die tägliche BatOut in kWh
                      const dailyBatOutKWhStateId = "0_userdata.0.Energie.Senec.Bat_Out_kWh";
                      
                      // Datenpunkt-ID für den täglichen BatIn in Wh (wird erstellt, falls nicht vorhanden)
                      const dailyBatInWhStateId = "0_userdata.0.Energie.Senec.Bat_In_Wh";
                      // Datenpunkt-ID für den täglichen BatIn in kWh
                      const dailyBatInKWhStateId = "0_userdata.0.Energie.Senec.Bat_In_kWh";
                      
                      // ====== Konfiguration ENDE ======
                      
                      
                      // Globale Variablen für die Berechnung der Tagessummen
                      let lastPowerValue = 0; // Letzter bekannter Leistungswert
                      let lastUpdateTime = new Date().getTime(); // Zeitpunkt der letzten Aktualisierung in Millisekunden
                      
                      // Funktion zum Initialisieren der Datenpunkte (falls nicht vorhanden)
                      function createStates() {
                          createState(dailyBatOutWhStateId, 0, {
                              name: 'Daily BatOut (Wh)',
                              type: 'number',
                              read: true,
                              write: false,
                              role: 'value.power.consumption',
                              unit: 'Wh'
                          });
                          createState(dailyBatOutKWhStateId, 0, {
                              name: 'Daily BatOut (kWh)',
                              type: 'number',
                              read: true,
                              write: false,
                              role: 'value.power.consumption',
                              unit: 'kWh'
                          });
                          createState(dailyBatInWhStateId, 0, {
                              name: 'Daily BatIn (Wh)',
                              type: 'number',
                              read: true,
                              write: false,
                              role: 'value.power.consumption',
                              unit: 'Wh'
                          });
                          createState(dailyBatInKWhStateId, 0, {
                              name: 'Daily BatIn (kWh)',
                              type: 'number',
                              read: true,
                              write: false,
                              role: 'value.power.consumption',
                              unit: 'kWh'
                          });
                      }
                      
                      // Beim Start des Skripts Datenpunkte erstellen und initialisieren
                      createStates();
                      
                      // Werte aus den Datenpunkten beim Skriptstart lesen, falls schon vorhanden
                      // Prüfen, ob die Datenpunkte bereits einen Wert haben, ansonsten auf 0 setzen
                      let initialBatOutState = getState(dailyBatOutWhStateId);
                      if (initialBatOutState && initialBatOutState.val !== null) {
                          log(`Initialer Wert für BatOut Wh: ${initialBatOutState.val}`);
                      } else {
                          setState(dailyBatOutWhStateId, 0);
                          log(`Datenpunkt ${dailyBatOutWhStateId} auf 0 gesetzt.`);
                      }
                      
                      let initialBatInState = getState(dailyBatInWhStateId);
                      if (initialBatInState && initialBatInState.val !== null) {
                          log(`Initialer Wert für BatIn Wh: ${initialBatInState.val}`);
                      } else {
                          setState(dailyBatInWhStateId, 0);
                          log(`Datenpunkt ${dailyBatInWhStateId} auf 0 gesetzt.`);
                      }
                      
                      // Trigger bei Änderung des Leistungsdatenpunkts
                      on({ id: powerStateId, change: 'ne' }, async function (obj) {
                          const currentPower = obj.state.val; // Aktueller Leistungswert in Watt
                          const currentTime = new Date().getTime(); // Aktueller Zeitstempel in Millisekunden
                      
                          // Wenn der Wert zum ersten Mal kommt oder Zeitunterschied zu gering ist
                          if (lastPowerValue === 0 && lastUpdateTime === new Date().getTime()) { // Initialisierung
                              lastPowerValue = currentPower;
                              lastUpdateTime = currentTime;
                              log("Initialisierung der Leistungswerte.");
                              return;
                          }
                      
                          const timeDiffSeconds = (currentTime - lastUpdateTime) / 1000; // Zeitdifferenz in Sekunden
                      
                          if (timeDiffSeconds <= 0) { // Falls keine Zeit vergangen ist (z.B. zu schnelle Updates)
                              log("Zeitdifferenz ist 0 oder negativ, Überspringe Berechnung.");
                              return;
                          }
                      
                          // Leistung * Zeit = Energie (Wattsekunden)
                          const energyWs = currentPower * timeDiffSeconds;
                          const energyWh = energyWs / 3600; // Umrechnung von Wattsekunden in Wattstunden
                      
                          log(`Aktuelle Leistung: ${currentPower} W, Zeitdiff: ${timeDiffSeconds.toFixed(2)} s, Berechnete Energie: ${energyWh.toFixed(2)} Wh`);
                      
                          // Sicherstellen, dass die gelesenen Werte Zahlen sind (durch parseFloat oder den Unary-Plus-Operator)
                          let currentBatInWh = parseFloat((await getStateAsync(dailyBatInWhStateId)).val) || 0;
                          let currentBatOutWh = parseFloat((await getStateAsync(dailyBatOutWhStateId)).val) || 0;
                      
                          if (currentPower < 0) { // BatOut
                              currentBatOutWh += Math.abs(energyWh); // Absolutwert, damit die Summe positiv ist
                              setState(dailyBatOutWhStateId, currentBatOutWh.toFixed(2), true);
                              setState(dailyBatOutKWhStateId, (currentBatOutWh / 1000).toFixed(3), true);
                              log(`BatOut addiert. Neue Summe: ${currentBatOutWh.toFixed(2)} Wh`);
                          } else { // BatIn
                              currentBatInWh += energyWh;
                              setState(dailyBatInWhStateId, currentBatInWh.toFixed(2), true);
                              setState(dailyBatInKWhStateId, (currentBatInWh / 1000).toFixed(3), true);
                              log(`BatIn addiert. Neue Summe: ${currentBatInWh.toFixed(2)} Wh`);
                          }
                      
                          // Werte für die nächste Iteration speichern
                          lastPowerValue = currentPower;
                          lastUpdateTime = currentTime;
                      });
                      
                      
                      // Reset der Tagessummen um Mitternacht
                      schedule('0 0 * * *', async function () {
                          log("Mitternacht erreicht, setze Tagessummen zurück.");
                          setState(dailyBatOutWhStateId, 0, true);
                          setState(dailyBatOutKWhStateId, 0, true);
                          setState(dailyBatInWhStateId, 0, true);
                          setState(dailyBatInKWhStateId, 0, true);
                          // lastUpdateTime muss auch zurückgesetzt werden, um korrekte delta-t Berechnung am neuen Tag zu gewährleisten
                          lastUpdateTime = new Date().getTime();
                          lastPowerValue = (await getStateAsync(powerStateId)).val || 0; // Aktuellen Power-Wert erneut holen
                      
                          log("Tagessummen wurden zurückgesetzt.");
                      });
                      
                      // Optional: Für Debugging, wenn das Skript startet
                      log("Skript zum Überwachen von BatOut und BatIn gestartet.");
                      
                      1. Grid Power (schreibt die Werte in DP's (Einspeisung und Netzbezug), einmal Wh und einmal kWh und wird täglich um 00:00 Uhr auf '0' gesetzt)
                      // ====== Konfiguration START ======
                      // Datenpunkt-ID, die die aktuelle Leistung in Watt liefert.
                      // Negativ für Einspeisung, Positiv für Netzbezug.
                      // Diesen Wert musst du an deine ioBroker-Installation anpassen!
                      const powerStateId = "senec.0.ENERGY.GUI_GRID_POW"; // Beispiel: smartmeter.0.0_1_123_456_789.power_total_current
                      
                      // Datenpunkt-ID für die tägliche Einspeisung in Wh (wird erstellt, falls nicht vorhanden)
                      const dailyFeedInWhStateId = "0_userdata.0.Energie.Senec.Tages_Einspeisung_Wh";
                      // Datenpunkt-ID für die tägliche Einspeisung in kWh
                      const dailyFeedInKWhStateId = "0_userdata.0.Energie.Senec.Tages_Einspeisung_kWh";
                      
                      // Datenpunkt-ID für den täglichen Netzbezug in Wh (wird erstellt, falls nicht vorhanden)
                      const dailyGridPurchaseWhStateId = "0_userdata.0.Energie.Senec.Tages_Netzbezug_Wh";
                      // Datenpunkt-ID für den täglichen Netzbezug in kWh
                      const dailyGridPurchaseKWhStateId = "0_userdata.0.Energie.Senec.Tages_Netzbezug_kWh";
                      
                      // ====== Konfiguration ENDE ======
                      
                      
                      // Globale Variablen für die Berechnung der Tagessummen
                      let lastPowerValue = 0; // Letzter bekannter Leistungswert
                      let lastUpdateTime = new Date().getTime(); // Zeitpunkt der letzten Aktualisierung in Millisekunden
                      
                      // Funktion zum Initialisieren der Datenpunkte (falls nicht vorhanden)
                      function createStates() {
                          createState(dailyFeedInWhStateId, 0, {
                              name: 'Tägliche Einspeisung (Wh)',
                              type: 'number',
                              read: true,
                              write: false,
                              role: 'value.power.consumption',
                              unit: 'Wh'
                          });
                          createState(dailyFeedInKWhStateId, 0, {
                              name: 'Tägliche Einspeisung (kWh)',
                              type: 'number',
                              read: true,
                              write: false,
                              role: 'value.power.consumption',
                              unit: 'kWh'
                          });
                          createState(dailyGridPurchaseWhStateId, 0, {
                              name: 'Täglicher Netzbezug (Wh)',
                              type: 'number',
                              read: true,
                              write: false,
                              role: 'value.power.consumption',
                              unit: 'Wh'
                          });
                          createState(dailyGridPurchaseKWhStateId, 0, {
                              name: 'Täglicher Netzbezug (kWh)',
                              type: 'number',
                              read: true,
                              write: false,
                              role: 'value.power.consumption',
                              unit: 'kWh'
                          });
                      }
                      
                      // Beim Start des Skripts Datenpunkte erstellen und initialisieren
                      createStates();
                      
                      // Werte aus den Datenpunkten beim Skriptstart lesen, falls schon vorhanden
                      // Prüfen, ob die Datenpunkte bereits einen Wert haben, ansonsten auf 0 setzen
                      let initialFeedInState = getState(dailyFeedInWhStateId);
                      if (initialFeedInState && initialFeedInState.val !== null) {
                          log(`Initialer Wert für Einspeisung Wh: ${initialFeedInState.val}`);
                      } else {
                          setState(dailyFeedInWhStateId, 0);
                          log(`Datenpunkt ${dailyFeedInWhStateId} auf 0 gesetzt.`);
                      }
                      
                      let initialGridPurchaseState = getState(dailyGridPurchaseWhStateId);
                      if (initialGridPurchaseState && initialGridPurchaseState.val !== null) {
                          log(`Initialer Wert für Netzbezug Wh: ${initialGridPurchaseState.val}`);
                      } else {
                          setState(dailyGridPurchaseWhStateId, 0);
                          log(`Datenpunkt ${dailyGridPurchaseWhStateId} auf 0 gesetzt.`);
                      }
                      
                      // Trigger bei Änderung des Leistungsdatenpunkts
                      on({ id: powerStateId, change: 'ne' }, async function (obj) {
                          const currentPower = obj.state.val; // Aktueller Leistungswert in Watt
                          const currentTime = new Date().getTime(); // Aktueller Zeitstempel in Millisekunden
                      
                          // Wenn der Wert zum ersten Mal kommt oder Zeitunterschied zu gering ist
                          // Hier ist es wichtig, dass lastPowerValue und lastUpdateTime initialisiert werden
                          if (lastPowerValue === 0 && lastUpdateTime === new Date().getTime()) { // Initialisierung
                              const powerState = getState(powerStateId);
                              if (powerState && powerState.val !== null) {
                                  lastPowerValue = powerState.val;
                              } else {
                                  lastPowerValue = 0; // Fallback, falls kein Wert verfügbar
                              }
                              lastUpdateTime = currentTime;
                              log("Initialisierung der Leistungswerte beim ersten Trigger.");
                              return;
                          }
                      
                      
                          const timeDiffSeconds = (currentTime - lastUpdateTime) / 1000; // Zeitdifferenz in Sekunden
                      
                          if (timeDiffSeconds <= 0) { // Falls keine Zeit vergangen ist (z.B. zu schnelle Updates)
                              log("Zeitdifferenz ist 0 oder negativ, Überspringe Berechnung.");
                              return;
                          }
                      
                          // Leistung * Zeit = Energie (Wattsekunden)
                          const energyWs = currentPower * timeDiffSeconds;
                          const energyWh = energyWs / 3600; // Umrechnung von Wattsekunden in Wattstunden
                      
                          log(`Aktuelle Leistung: ${currentPower} W, Zeitdiff: ${timeDiffSeconds.toFixed(2)} s, Berechnete Energie: ${energyWh.toFixed(2)} Wh`);
                      
                          // **KORRIGIERTER BEREICH START**
                          // Sicherstellen, dass die gelesenen Werte Zahlen sind (durch parseFloat oder den Unary-Plus-Operator)
                          let currentFeedInWh = parseFloat((await getStateAsync(dailyFeedInWhStateId)).val) || 0;
                          let currentGridPurchaseWh = parseFloat((await getStateAsync(dailyGridPurchaseWhStateId)).val) || 0;
                          // **KORRIGIERTER BEREICH ENDE**
                      
                          if (currentPower < 0) { // Einspeisung
                              currentFeedInWh += Math.abs(energyWh); // Absolutwert, damit die Summe positiv ist
                              setState(dailyFeedInWhStateId, currentFeedInWh.toFixed(2), true);
                              setState(dailyFeedInKWhStateId, (currentFeedInWh / 1000).toFixed(3), true);
                              log(`Einspeisung addiert. Neue Summe: ${currentFeedInWh.toFixed(2)} Wh`);
                          } else { // Netzbezug
                              currentGridPurchaseWh += energyWh;
                              setState(dailyGridPurchaseWhStateId, currentGridPurchaseWh.toFixed(2), true);
                              setState(dailyGridPurchaseKWhStateId, (currentGridPurchaseWh / 1000).toFixed(3), true);
                              log(`Netzbezug addiert. Neue Summe: ${currentGridPurchaseWh.toFixed(2)} Wh`);
                          }
                      
                          // Werte für die nächste Iteration speichern
                          lastPowerValue = currentPower;
                          lastUpdateTime = currentTime;
                      });
                      
                      
                      // Reset der Tagessummen um Mitternacht
                      schedule('0 0 * * *', async function () {
                          log("Mitternacht erreicht, setze Tagessummen zurück.");
                          setState(dailyFeedInWhStateId, 0, true);
                          setState(dailyFeedInKWhStateId, 0, true);
                          setState(dailyGridPurchaseWhStateId, 0, true);
                          setState(dailyGridPurchaseKWhStateId, 0, true);
                          // lastUpdateTime muss auch zurückgesetzt werden, um korrekte delta-t Berechnung am neuen Tag zu gewährleisten
                          lastUpdateTime = new Date().getTime();
                          lastPowerValue = (await getStateAsync(powerStateId)).val || 0; // Aktuellen Power-Wert erneut holen
                      
                          log("Tagessummen wurden zurückgesetzt.");
                      });
                      
                      // Optional: Für Debugging, wenn das Skript startet
                      log("Skript zum Überwachen von Einspeisung und Netzbezug gestartet.");
                      

                      wer Lust hat kann ja mit testen ob das so passt.

                      M Offline
                      M Offline
                      musicnrw
                      schrieb am zuletzt editiert von
                      #368

                      @icebear, ich bin was iobroker und Scripte angeht absoluter Anfänger. Kannst Du mir bitte möglichst detailiert beschreiben, was ich an welcher Stelle tun muss? Also, wie und wo richte ich Deine Scripte in meiner Konfiguration ein, damit ich die Werte aus der SENEC-Anlage in meine InfluxDB bekomme. Vielen Dank im Voraus!

                      1 Antwort Letzte Antwort
                      0
                      • icebearI Offline
                        icebearI Offline
                        icebear
                        schrieb am zuletzt editiert von
                        #369

                        @musicnrw said in [Neuer Adapter] Senec Home Adapter:

                        Also, wie und wo richte ich Deine Scripte in meiner Konfiguration ein,

                        Scripte von oben kopieren und dann auf 'Skripte'

                        Senec_1.png

                        Dann legst 1. Einen neuen Ordner (im Root-Verzeichnis an), dann 2. den Ordner anklicken (das er 'blau' markiert ist) und dann oben auf 3. das '+' für neues Script.

                        Senec_2.png

                        Dann JS auswählen

                        Senec_3.png

                        Dann einen Namen vergeben und das kopierte Script einfügen.

                        Senec_4.png

                        Auf den 'roten Pfeil' Script starten.

                        Unter > 0_userdata.0.Energie.Senec sollten dann die DP erstellt und mit den Werten befüllt werden.

                        M 1 Antwort Letzte Antwort
                        2
                        • icebearI icebear

                          @dispo112 said in [Neuer Adapter] Senec Home Adapter:

                          So, bitte schön. Die Ordnerpfade sind alle standard. Theoretisch könnt ihr das Skript importieren und starten, fertig. Alle neuen Datenpunkte werden im Userdata erzeugt und können dann via Lovelace / VIS abgegriffen werden.

                          Nochmal vielen Dank für deine Arbeit. Läuft bei mir seit gestern und die Werte sind soweit völlig O.K.

                          Ich hab mich jetzt auch entschieden, nicht mehr darauf zu Warten ob irgendeiner etwas bereitstellt das die API oder die Werte über mein-senec abgegriffen werden. Die Klimzüge über HA sind mir zu aufwendig und keiner weiß wie lange das dann funktioniert bevor Senec da wieder den Riegel vorschiebt.
                          Solange wie der Adapter mir die Live-Daten zur Verfügung stellt reicht mir das.

                          Ich hab deshalb zusätzlich zu dem Script von @dispo112 noch drei weitere Scripte bei mir implementiert, die laufen seit gestern und liefern meines Erachtens ausreichend genaue Werte, so das sich eine gewisse Statistik aufrechterhalten lässt.

                          Hier die drei Scripte die ich zusätzlich noch implementiert hab:

                          1. Hausverbrauch (schreibt die Werte in zwei DP's , einmal Wh und einmal kWh und wird täglich um 00:00 Uhr auf '0' gesetzt)
                          // ====== Konfiguration START ======
                          
                          // ID des Datenpunkts, der den aktuellen Hausverbrauch in Watt (W) liefert.
                          // Diesen Wert MUSST du an deine ioBroker-Installation anpassen!
                          // Beispiel: 'shelly.0.shellypower.power' oder 'modbus.0.holdingRegisters.power_total'
                          const currentHouseConsumptionPowerId = "senec.0.ENERGY.GUI_HOUSE_POW";
                          
                          // ID des Datenpunkts für den täglichen Hausverbrauch in Wh (wird erstellt, falls nicht vorhanden)
                          const dailyHouseConsumptionWhId = "0_userdata.0.Energie.Senec.Tages_Hausverbrauch_Wh";
                          // ID des Datenpunkts für den täglichen Hausverbrauch in kWh (wird erstellt, falls nicht vorhanden)
                          const dailyHouseConsumptionKWhId = "0_userdata.0.Energie.Senec.Tages_Hausverbrauch_kWh";
                          
                          // ====== Konfiguration ENDE ======
                          
                          
                          // Globale Variablen für die Berechnung
                          let lastPowerValue = 0; // Letzter bekannter Leistungswert
                          let lastUpdateTime = new Date().getTime(); // Zeitpunkt der letzten Aktualisierung in Millisekunden
                          
                          // --- Hilfsfunktionen ---
                          
                          // Funktion zum Erstellen der notwendigen Datenpunkte (States)
                          function createMyStates() {
                              createState(dailyHouseConsumptionWhId, 0, {
                                  name: 'Täglicher Hausverbrauch (Wh)',
                                  type: 'number',
                                  read: true,
                                  write: false,
                                  role: 'value.power.consumption',
                                  unit: 'Wh',
                                  desc: 'Summierter Hausverbrauch für den aktuellen Tag in Wattstunden'
                              });
                              createState(dailyHouseConsumptionKWhId, 0, {
                                  name: 'Täglicher Hausverbrauch (kWh)',
                                  type: 'number',
                                  read: true,
                                  write: false,
                                  role: 'value.power.consumption',
                                  unit: 'kWh',
                                  desc: 'Summierter Hausverbrauch für den aktuellen Tag in Kilowattstunden'
                              });
                              log("Datenpunkte für den Hausverbrauch überprüft/erstellt.");
                          }
                          
                          // Funktion, um den initialen Wert aus dem Datenpunkt zu lesen und zu loggen
                          async function initializeConsumptionValues() {
                              const state = await getStateAsync(dailyHouseConsumptionWhId);
                              if (state && state.val !== null) {
                                  log(`Initialer Wert für täglichen Hausverbrauch Wh: ${state.val} Wh`);
                              } else {
                                  setState(dailyHouseConsumptionWhId, 0, true);
                                  setState(dailyHouseConsumptionKWhId, 0, true);
                                  log(`Datenpunkte ${dailyHouseConsumptionWhId} und ${dailyHouseConsumptionKWhId} auf 0 gesetzt.`);
                              }
                          }
                          
                          // --- Hauptlogik ---
                          
                          // 1. Beim Start des Skripts: Datenpunkte erstellen und initialisieren
                          createMyStates();
                          initializeConsumptionValues();
                          
                          // 2. Trigger bei Änderung des Hausverbrauchs-Datenpunkts
                          on({ id: currentHouseConsumptionPowerId, change: 'ne' }, async function (obj) {
                              const currentPower = parseFloat(obj.state.val); // Aktueller Leistungswert in Watt
                          
                              // Prüfen, ob der Wert gültig ist
                              if (isNaN(currentPower)) {
                                  log(`Ungültiger Leistungswert erhalten: ${obj.state.val}. Berechnung übersprungen.`, 'warn');
                                  return;
                              }
                          
                              const currentTime = new Date().getTime(); // Aktueller Zeitstempel in Millisekunden
                          
                              // Initialisierung von lastPowerValue und lastUpdateTime beim ersten Trigger
                              if (lastPowerValue === 0 && lastUpdateTime === new Date().getTime()) {
                                  const powerState = getState(currentHouseConsumptionPowerId);
                                  if (powerState && powerState.val !== null) {
                                      lastPowerValue = parseFloat(powerState.val);
                                  } else {
                                      lastPowerValue = 0; // Fallback
                                  }
                                  lastUpdateTime = currentTime;
                                  log("Initialisierung der Leistungswerte beim ersten Trigger.");
                                  return;
                              }
                          
                              const timeDiffSeconds = (currentTime - lastUpdateTime) / 1000; // Zeitdifferenz in Sekunden
                          
                              // Falls keine Zeit vergangen ist (z.B. zu schnelle Updates oder gleicher Zeitstempel)
                              if (timeDiffSeconds <= 0) {
                                  // log("Zeitdifferenz ist 0 oder negativ, Überspringe Berechnung.", 'debug'); // Kann viele Logs verursachen
                                  return;
                              }
                          
                              // Berechnung der Energie: Leistung (W) * Zeit (s) = Wattsekunden (Ws)
                              const energyWs = currentPower * timeDiffSeconds;
                              // Umrechnung von Wattsekunden in Wattstunden (Ws / 3600 = Wh)
                              const energyWh = energyWs / 3600;
                          
                              log(`Aktuelle Leistung: ${currentPower.toFixed(2)} W, Zeitdiff: ${timeDiffSeconds.toFixed(2)} s, Berechnete Energie: ${energyWh.toFixed(2)} Wh`);
                          
                              // Aktuellen summierten Verbrauch von ioBroker lesen und sicherstellen, dass es eine Zahl ist
                              let currentDailyConsumptionWh = parseFloat((await getStateAsync(dailyHouseConsumptionWhId)).val) || 0;
                          
                              // Energie zum Tagesverbrauch addieren
                              currentDailyConsumptionWh += energyWh;
                          
                              // Werte in die Datenpunkte schreiben
                              setState(dailyHouseConsumptionWhId, currentDailyConsumptionWh.toFixed(2), true); // Wh auf 2 Nachkommastellen
                              setState(dailyHouseConsumptionKWhId, (currentDailyConsumptionWh / 1000).toFixed(3), true); // kWh auf 3 Nachkommastellen
                          
                              log(`Hausverbrauch addiert. Neue Summe: ${currentDailyConsumptionWh.toFixed(2)} Wh (${(currentDailyConsumptionWh / 1000).toFixed(3)} kWh)`);
                          
                              // Werte für die nächste Iteration speichern
                              lastPowerValue = currentPower;
                              lastUpdateTime = currentTime;
                          });
                          
                          // 3. Reset der Tagessummen um Mitternacht
                          schedule('0 0 * * *', async function () {
                              log("Mitternacht erreicht, setze täglichen Hausverbrauch zurück.");
                              setState(dailyHouseConsumptionWhId, 0, true);
                              setState(dailyHouseConsumptionKWhId, 0, true);
                          
                              // Wichtig: lastUpdateTime muss auch zurückgesetzt werden für korrekte delta-t Berechnung am neuen Tag
                              // und lastPowerValue für den ersten Wert des neuen Tages
                              lastUpdateTime = new Date().getTime();
                              lastPowerValue = parseFloat((await getStateAsync(currentHouseConsumptionPowerId)).val) || 0; // Aktuellen Power-Wert erneut holen
                          
                              log("Täglicher Hausverbrauch wurde zurückgesetzt.");
                          });
                          
                          // Optional: Info-Log beim Start des Skripts
                          log("Skript zum Überwachen des täglichen Hausverbrauchs gestartet.");
                          
                          1. Akku Be-und Entladung (schreibt die Werte (batIn und batOut) in DP's , einmal Wh und einmal kWh und wird täglich um 00:00 Uhr auf '0' gesetzt)
                          // ====== Konfiguration START ======
                          // Datenpunkt-ID, die die aktuelle Leistung in Watt liefert.
                          // Negativ für BatOut, Positiv für BatIn.
                          // Diesen Wert musst du an deine ioBroker-Installation anpassen!
                          const powerStateId = "senec.0.ENERGY.GUI_BAT_DATA_POWER"; // Beispiel: smartmeter.0.0_1_123_456_789.power_total_current
                          
                          // Datenpunkt-ID für die tägliche BatOut in Wh (wird erstellt, falls nicht vorhanden)
                          const dailyBatOutWhStateId = "0_userdata.0.Energie.Senec.Bat_Out_Wh";
                          // Datenpunkt-ID für die tägliche BatOut in kWh
                          const dailyBatOutKWhStateId = "0_userdata.0.Energie.Senec.Bat_Out_kWh";
                          
                          // Datenpunkt-ID für den täglichen BatIn in Wh (wird erstellt, falls nicht vorhanden)
                          const dailyBatInWhStateId = "0_userdata.0.Energie.Senec.Bat_In_Wh";
                          // Datenpunkt-ID für den täglichen BatIn in kWh
                          const dailyBatInKWhStateId = "0_userdata.0.Energie.Senec.Bat_In_kWh";
                          
                          // ====== Konfiguration ENDE ======
                          
                          
                          // Globale Variablen für die Berechnung der Tagessummen
                          let lastPowerValue = 0; // Letzter bekannter Leistungswert
                          let lastUpdateTime = new Date().getTime(); // Zeitpunkt der letzten Aktualisierung in Millisekunden
                          
                          // Funktion zum Initialisieren der Datenpunkte (falls nicht vorhanden)
                          function createStates() {
                              createState(dailyBatOutWhStateId, 0, {
                                  name: 'Daily BatOut (Wh)',
                                  type: 'number',
                                  read: true,
                                  write: false,
                                  role: 'value.power.consumption',
                                  unit: 'Wh'
                              });
                              createState(dailyBatOutKWhStateId, 0, {
                                  name: 'Daily BatOut (kWh)',
                                  type: 'number',
                                  read: true,
                                  write: false,
                                  role: 'value.power.consumption',
                                  unit: 'kWh'
                              });
                              createState(dailyBatInWhStateId, 0, {
                                  name: 'Daily BatIn (Wh)',
                                  type: 'number',
                                  read: true,
                                  write: false,
                                  role: 'value.power.consumption',
                                  unit: 'Wh'
                              });
                              createState(dailyBatInKWhStateId, 0, {
                                  name: 'Daily BatIn (kWh)',
                                  type: 'number',
                                  read: true,
                                  write: false,
                                  role: 'value.power.consumption',
                                  unit: 'kWh'
                              });
                          }
                          
                          // Beim Start des Skripts Datenpunkte erstellen und initialisieren
                          createStates();
                          
                          // Werte aus den Datenpunkten beim Skriptstart lesen, falls schon vorhanden
                          // Prüfen, ob die Datenpunkte bereits einen Wert haben, ansonsten auf 0 setzen
                          let initialBatOutState = getState(dailyBatOutWhStateId);
                          if (initialBatOutState && initialBatOutState.val !== null) {
                              log(`Initialer Wert für BatOut Wh: ${initialBatOutState.val}`);
                          } else {
                              setState(dailyBatOutWhStateId, 0);
                              log(`Datenpunkt ${dailyBatOutWhStateId} auf 0 gesetzt.`);
                          }
                          
                          let initialBatInState = getState(dailyBatInWhStateId);
                          if (initialBatInState && initialBatInState.val !== null) {
                              log(`Initialer Wert für BatIn Wh: ${initialBatInState.val}`);
                          } else {
                              setState(dailyBatInWhStateId, 0);
                              log(`Datenpunkt ${dailyBatInWhStateId} auf 0 gesetzt.`);
                          }
                          
                          // Trigger bei Änderung des Leistungsdatenpunkts
                          on({ id: powerStateId, change: 'ne' }, async function (obj) {
                              const currentPower = obj.state.val; // Aktueller Leistungswert in Watt
                              const currentTime = new Date().getTime(); // Aktueller Zeitstempel in Millisekunden
                          
                              // Wenn der Wert zum ersten Mal kommt oder Zeitunterschied zu gering ist
                              if (lastPowerValue === 0 && lastUpdateTime === new Date().getTime()) { // Initialisierung
                                  lastPowerValue = currentPower;
                                  lastUpdateTime = currentTime;
                                  log("Initialisierung der Leistungswerte.");
                                  return;
                              }
                          
                              const timeDiffSeconds = (currentTime - lastUpdateTime) / 1000; // Zeitdifferenz in Sekunden
                          
                              if (timeDiffSeconds <= 0) { // Falls keine Zeit vergangen ist (z.B. zu schnelle Updates)
                                  log("Zeitdifferenz ist 0 oder negativ, Überspringe Berechnung.");
                                  return;
                              }
                          
                              // Leistung * Zeit = Energie (Wattsekunden)
                              const energyWs = currentPower * timeDiffSeconds;
                              const energyWh = energyWs / 3600; // Umrechnung von Wattsekunden in Wattstunden
                          
                              log(`Aktuelle Leistung: ${currentPower} W, Zeitdiff: ${timeDiffSeconds.toFixed(2)} s, Berechnete Energie: ${energyWh.toFixed(2)} Wh`);
                          
                              // Sicherstellen, dass die gelesenen Werte Zahlen sind (durch parseFloat oder den Unary-Plus-Operator)
                              let currentBatInWh = parseFloat((await getStateAsync(dailyBatInWhStateId)).val) || 0;
                              let currentBatOutWh = parseFloat((await getStateAsync(dailyBatOutWhStateId)).val) || 0;
                          
                              if (currentPower < 0) { // BatOut
                                  currentBatOutWh += Math.abs(energyWh); // Absolutwert, damit die Summe positiv ist
                                  setState(dailyBatOutWhStateId, currentBatOutWh.toFixed(2), true);
                                  setState(dailyBatOutKWhStateId, (currentBatOutWh / 1000).toFixed(3), true);
                                  log(`BatOut addiert. Neue Summe: ${currentBatOutWh.toFixed(2)} Wh`);
                              } else { // BatIn
                                  currentBatInWh += energyWh;
                                  setState(dailyBatInWhStateId, currentBatInWh.toFixed(2), true);
                                  setState(dailyBatInKWhStateId, (currentBatInWh / 1000).toFixed(3), true);
                                  log(`BatIn addiert. Neue Summe: ${currentBatInWh.toFixed(2)} Wh`);
                              }
                          
                              // Werte für die nächste Iteration speichern
                              lastPowerValue = currentPower;
                              lastUpdateTime = currentTime;
                          });
                          
                          
                          // Reset der Tagessummen um Mitternacht
                          schedule('0 0 * * *', async function () {
                              log("Mitternacht erreicht, setze Tagessummen zurück.");
                              setState(dailyBatOutWhStateId, 0, true);
                              setState(dailyBatOutKWhStateId, 0, true);
                              setState(dailyBatInWhStateId, 0, true);
                              setState(dailyBatInKWhStateId, 0, true);
                              // lastUpdateTime muss auch zurückgesetzt werden, um korrekte delta-t Berechnung am neuen Tag zu gewährleisten
                              lastUpdateTime = new Date().getTime();
                              lastPowerValue = (await getStateAsync(powerStateId)).val || 0; // Aktuellen Power-Wert erneut holen
                          
                              log("Tagessummen wurden zurückgesetzt.");
                          });
                          
                          // Optional: Für Debugging, wenn das Skript startet
                          log("Skript zum Überwachen von BatOut und BatIn gestartet.");
                          
                          1. Grid Power (schreibt die Werte in DP's (Einspeisung und Netzbezug), einmal Wh und einmal kWh und wird täglich um 00:00 Uhr auf '0' gesetzt)
                          // ====== Konfiguration START ======
                          // Datenpunkt-ID, die die aktuelle Leistung in Watt liefert.
                          // Negativ für Einspeisung, Positiv für Netzbezug.
                          // Diesen Wert musst du an deine ioBroker-Installation anpassen!
                          const powerStateId = "senec.0.ENERGY.GUI_GRID_POW"; // Beispiel: smartmeter.0.0_1_123_456_789.power_total_current
                          
                          // Datenpunkt-ID für die tägliche Einspeisung in Wh (wird erstellt, falls nicht vorhanden)
                          const dailyFeedInWhStateId = "0_userdata.0.Energie.Senec.Tages_Einspeisung_Wh";
                          // Datenpunkt-ID für die tägliche Einspeisung in kWh
                          const dailyFeedInKWhStateId = "0_userdata.0.Energie.Senec.Tages_Einspeisung_kWh";
                          
                          // Datenpunkt-ID für den täglichen Netzbezug in Wh (wird erstellt, falls nicht vorhanden)
                          const dailyGridPurchaseWhStateId = "0_userdata.0.Energie.Senec.Tages_Netzbezug_Wh";
                          // Datenpunkt-ID für den täglichen Netzbezug in kWh
                          const dailyGridPurchaseKWhStateId = "0_userdata.0.Energie.Senec.Tages_Netzbezug_kWh";
                          
                          // ====== Konfiguration ENDE ======
                          
                          
                          // Globale Variablen für die Berechnung der Tagessummen
                          let lastPowerValue = 0; // Letzter bekannter Leistungswert
                          let lastUpdateTime = new Date().getTime(); // Zeitpunkt der letzten Aktualisierung in Millisekunden
                          
                          // Funktion zum Initialisieren der Datenpunkte (falls nicht vorhanden)
                          function createStates() {
                              createState(dailyFeedInWhStateId, 0, {
                                  name: 'Tägliche Einspeisung (Wh)',
                                  type: 'number',
                                  read: true,
                                  write: false,
                                  role: 'value.power.consumption',
                                  unit: 'Wh'
                              });
                              createState(dailyFeedInKWhStateId, 0, {
                                  name: 'Tägliche Einspeisung (kWh)',
                                  type: 'number',
                                  read: true,
                                  write: false,
                                  role: 'value.power.consumption',
                                  unit: 'kWh'
                              });
                              createState(dailyGridPurchaseWhStateId, 0, {
                                  name: 'Täglicher Netzbezug (Wh)',
                                  type: 'number',
                                  read: true,
                                  write: false,
                                  role: 'value.power.consumption',
                                  unit: 'Wh'
                              });
                              createState(dailyGridPurchaseKWhStateId, 0, {
                                  name: 'Täglicher Netzbezug (kWh)',
                                  type: 'number',
                                  read: true,
                                  write: false,
                                  role: 'value.power.consumption',
                                  unit: 'kWh'
                              });
                          }
                          
                          // Beim Start des Skripts Datenpunkte erstellen und initialisieren
                          createStates();
                          
                          // Werte aus den Datenpunkten beim Skriptstart lesen, falls schon vorhanden
                          // Prüfen, ob die Datenpunkte bereits einen Wert haben, ansonsten auf 0 setzen
                          let initialFeedInState = getState(dailyFeedInWhStateId);
                          if (initialFeedInState && initialFeedInState.val !== null) {
                              log(`Initialer Wert für Einspeisung Wh: ${initialFeedInState.val}`);
                          } else {
                              setState(dailyFeedInWhStateId, 0);
                              log(`Datenpunkt ${dailyFeedInWhStateId} auf 0 gesetzt.`);
                          }
                          
                          let initialGridPurchaseState = getState(dailyGridPurchaseWhStateId);
                          if (initialGridPurchaseState && initialGridPurchaseState.val !== null) {
                              log(`Initialer Wert für Netzbezug Wh: ${initialGridPurchaseState.val}`);
                          } else {
                              setState(dailyGridPurchaseWhStateId, 0);
                              log(`Datenpunkt ${dailyGridPurchaseWhStateId} auf 0 gesetzt.`);
                          }
                          
                          // Trigger bei Änderung des Leistungsdatenpunkts
                          on({ id: powerStateId, change: 'ne' }, async function (obj) {
                              const currentPower = obj.state.val; // Aktueller Leistungswert in Watt
                              const currentTime = new Date().getTime(); // Aktueller Zeitstempel in Millisekunden
                          
                              // Wenn der Wert zum ersten Mal kommt oder Zeitunterschied zu gering ist
                              // Hier ist es wichtig, dass lastPowerValue und lastUpdateTime initialisiert werden
                              if (lastPowerValue === 0 && lastUpdateTime === new Date().getTime()) { // Initialisierung
                                  const powerState = getState(powerStateId);
                                  if (powerState && powerState.val !== null) {
                                      lastPowerValue = powerState.val;
                                  } else {
                                      lastPowerValue = 0; // Fallback, falls kein Wert verfügbar
                                  }
                                  lastUpdateTime = currentTime;
                                  log("Initialisierung der Leistungswerte beim ersten Trigger.");
                                  return;
                              }
                          
                          
                              const timeDiffSeconds = (currentTime - lastUpdateTime) / 1000; // Zeitdifferenz in Sekunden
                          
                              if (timeDiffSeconds <= 0) { // Falls keine Zeit vergangen ist (z.B. zu schnelle Updates)
                                  log("Zeitdifferenz ist 0 oder negativ, Überspringe Berechnung.");
                                  return;
                              }
                          
                              // Leistung * Zeit = Energie (Wattsekunden)
                              const energyWs = currentPower * timeDiffSeconds;
                              const energyWh = energyWs / 3600; // Umrechnung von Wattsekunden in Wattstunden
                          
                              log(`Aktuelle Leistung: ${currentPower} W, Zeitdiff: ${timeDiffSeconds.toFixed(2)} s, Berechnete Energie: ${energyWh.toFixed(2)} Wh`);
                          
                              // **KORRIGIERTER BEREICH START**
                              // Sicherstellen, dass die gelesenen Werte Zahlen sind (durch parseFloat oder den Unary-Plus-Operator)
                              let currentFeedInWh = parseFloat((await getStateAsync(dailyFeedInWhStateId)).val) || 0;
                              let currentGridPurchaseWh = parseFloat((await getStateAsync(dailyGridPurchaseWhStateId)).val) || 0;
                              // **KORRIGIERTER BEREICH ENDE**
                          
                              if (currentPower < 0) { // Einspeisung
                                  currentFeedInWh += Math.abs(energyWh); // Absolutwert, damit die Summe positiv ist
                                  setState(dailyFeedInWhStateId, currentFeedInWh.toFixed(2), true);
                                  setState(dailyFeedInKWhStateId, (currentFeedInWh / 1000).toFixed(3), true);
                                  log(`Einspeisung addiert. Neue Summe: ${currentFeedInWh.toFixed(2)} Wh`);
                              } else { // Netzbezug
                                  currentGridPurchaseWh += energyWh;
                                  setState(dailyGridPurchaseWhStateId, currentGridPurchaseWh.toFixed(2), true);
                                  setState(dailyGridPurchaseKWhStateId, (currentGridPurchaseWh / 1000).toFixed(3), true);
                                  log(`Netzbezug addiert. Neue Summe: ${currentGridPurchaseWh.toFixed(2)} Wh`);
                              }
                          
                              // Werte für die nächste Iteration speichern
                              lastPowerValue = currentPower;
                              lastUpdateTime = currentTime;
                          });
                          
                          
                          // Reset der Tagessummen um Mitternacht
                          schedule('0 0 * * *', async function () {
                              log("Mitternacht erreicht, setze Tagessummen zurück.");
                              setState(dailyFeedInWhStateId, 0, true);
                              setState(dailyFeedInKWhStateId, 0, true);
                              setState(dailyGridPurchaseWhStateId, 0, true);
                              setState(dailyGridPurchaseKWhStateId, 0, true);
                              // lastUpdateTime muss auch zurückgesetzt werden, um korrekte delta-t Berechnung am neuen Tag zu gewährleisten
                              lastUpdateTime = new Date().getTime();
                              lastPowerValue = (await getStateAsync(powerStateId)).val || 0; // Aktuellen Power-Wert erneut holen
                          
                              log("Tagessummen wurden zurückgesetzt.");
                          });
                          
                          // Optional: Für Debugging, wenn das Skript startet
                          log("Skript zum Überwachen von Einspeisung und Netzbezug gestartet.");
                          

                          wer Lust hat kann ja mit testen ob das so passt.

                          R Offline
                          R Offline
                          RicoStriese
                          schrieb am zuletzt editiert von
                          #370

                          @icebear Danke für die Arbeit, habe alles übernommen. Es funktioniert super. Nochmals besten Danke für die Mühe.:clap: :clap:

                          1 Antwort Letzte Antwort
                          0
                          • icebearI icebear

                            @dispo112 said in [Neuer Adapter] Senec Home Adapter:

                            So, bitte schön. Die Ordnerpfade sind alle standard. Theoretisch könnt ihr das Skript importieren und starten, fertig. Alle neuen Datenpunkte werden im Userdata erzeugt und können dann via Lovelace / VIS abgegriffen werden.

                            Nochmal vielen Dank für deine Arbeit. Läuft bei mir seit gestern und die Werte sind soweit völlig O.K.

                            Ich hab mich jetzt auch entschieden, nicht mehr darauf zu Warten ob irgendeiner etwas bereitstellt das die API oder die Werte über mein-senec abgegriffen werden. Die Klimzüge über HA sind mir zu aufwendig und keiner weiß wie lange das dann funktioniert bevor Senec da wieder den Riegel vorschiebt.
                            Solange wie der Adapter mir die Live-Daten zur Verfügung stellt reicht mir das.

                            Ich hab deshalb zusätzlich zu dem Script von @dispo112 noch drei weitere Scripte bei mir implementiert, die laufen seit gestern und liefern meines Erachtens ausreichend genaue Werte, so das sich eine gewisse Statistik aufrechterhalten lässt.

                            Hier die drei Scripte die ich zusätzlich noch implementiert hab:

                            1. Hausverbrauch (schreibt die Werte in zwei DP's , einmal Wh und einmal kWh und wird täglich um 00:00 Uhr auf '0' gesetzt)
                            // ====== Konfiguration START ======
                            
                            // ID des Datenpunkts, der den aktuellen Hausverbrauch in Watt (W) liefert.
                            // Diesen Wert MUSST du an deine ioBroker-Installation anpassen!
                            // Beispiel: 'shelly.0.shellypower.power' oder 'modbus.0.holdingRegisters.power_total'
                            const currentHouseConsumptionPowerId = "senec.0.ENERGY.GUI_HOUSE_POW";
                            
                            // ID des Datenpunkts für den täglichen Hausverbrauch in Wh (wird erstellt, falls nicht vorhanden)
                            const dailyHouseConsumptionWhId = "0_userdata.0.Energie.Senec.Tages_Hausverbrauch_Wh";
                            // ID des Datenpunkts für den täglichen Hausverbrauch in kWh (wird erstellt, falls nicht vorhanden)
                            const dailyHouseConsumptionKWhId = "0_userdata.0.Energie.Senec.Tages_Hausverbrauch_kWh";
                            
                            // ====== Konfiguration ENDE ======
                            
                            
                            // Globale Variablen für die Berechnung
                            let lastPowerValue = 0; // Letzter bekannter Leistungswert
                            let lastUpdateTime = new Date().getTime(); // Zeitpunkt der letzten Aktualisierung in Millisekunden
                            
                            // --- Hilfsfunktionen ---
                            
                            // Funktion zum Erstellen der notwendigen Datenpunkte (States)
                            function createMyStates() {
                                createState(dailyHouseConsumptionWhId, 0, {
                                    name: 'Täglicher Hausverbrauch (Wh)',
                                    type: 'number',
                                    read: true,
                                    write: false,
                                    role: 'value.power.consumption',
                                    unit: 'Wh',
                                    desc: 'Summierter Hausverbrauch für den aktuellen Tag in Wattstunden'
                                });
                                createState(dailyHouseConsumptionKWhId, 0, {
                                    name: 'Täglicher Hausverbrauch (kWh)',
                                    type: 'number',
                                    read: true,
                                    write: false,
                                    role: 'value.power.consumption',
                                    unit: 'kWh',
                                    desc: 'Summierter Hausverbrauch für den aktuellen Tag in Kilowattstunden'
                                });
                                log("Datenpunkte für den Hausverbrauch überprüft/erstellt.");
                            }
                            
                            // Funktion, um den initialen Wert aus dem Datenpunkt zu lesen und zu loggen
                            async function initializeConsumptionValues() {
                                const state = await getStateAsync(dailyHouseConsumptionWhId);
                                if (state && state.val !== null) {
                                    log(`Initialer Wert für täglichen Hausverbrauch Wh: ${state.val} Wh`);
                                } else {
                                    setState(dailyHouseConsumptionWhId, 0, true);
                                    setState(dailyHouseConsumptionKWhId, 0, true);
                                    log(`Datenpunkte ${dailyHouseConsumptionWhId} und ${dailyHouseConsumptionKWhId} auf 0 gesetzt.`);
                                }
                            }
                            
                            // --- Hauptlogik ---
                            
                            // 1. Beim Start des Skripts: Datenpunkte erstellen und initialisieren
                            createMyStates();
                            initializeConsumptionValues();
                            
                            // 2. Trigger bei Änderung des Hausverbrauchs-Datenpunkts
                            on({ id: currentHouseConsumptionPowerId, change: 'ne' }, async function (obj) {
                                const currentPower = parseFloat(obj.state.val); // Aktueller Leistungswert in Watt
                            
                                // Prüfen, ob der Wert gültig ist
                                if (isNaN(currentPower)) {
                                    log(`Ungültiger Leistungswert erhalten: ${obj.state.val}. Berechnung übersprungen.`, 'warn');
                                    return;
                                }
                            
                                const currentTime = new Date().getTime(); // Aktueller Zeitstempel in Millisekunden
                            
                                // Initialisierung von lastPowerValue und lastUpdateTime beim ersten Trigger
                                if (lastPowerValue === 0 && lastUpdateTime === new Date().getTime()) {
                                    const powerState = getState(currentHouseConsumptionPowerId);
                                    if (powerState && powerState.val !== null) {
                                        lastPowerValue = parseFloat(powerState.val);
                                    } else {
                                        lastPowerValue = 0; // Fallback
                                    }
                                    lastUpdateTime = currentTime;
                                    log("Initialisierung der Leistungswerte beim ersten Trigger.");
                                    return;
                                }
                            
                                const timeDiffSeconds = (currentTime - lastUpdateTime) / 1000; // Zeitdifferenz in Sekunden
                            
                                // Falls keine Zeit vergangen ist (z.B. zu schnelle Updates oder gleicher Zeitstempel)
                                if (timeDiffSeconds <= 0) {
                                    // log("Zeitdifferenz ist 0 oder negativ, Überspringe Berechnung.", 'debug'); // Kann viele Logs verursachen
                                    return;
                                }
                            
                                // Berechnung der Energie: Leistung (W) * Zeit (s) = Wattsekunden (Ws)
                                const energyWs = currentPower * timeDiffSeconds;
                                // Umrechnung von Wattsekunden in Wattstunden (Ws / 3600 = Wh)
                                const energyWh = energyWs / 3600;
                            
                                log(`Aktuelle Leistung: ${currentPower.toFixed(2)} W, Zeitdiff: ${timeDiffSeconds.toFixed(2)} s, Berechnete Energie: ${energyWh.toFixed(2)} Wh`);
                            
                                // Aktuellen summierten Verbrauch von ioBroker lesen und sicherstellen, dass es eine Zahl ist
                                let currentDailyConsumptionWh = parseFloat((await getStateAsync(dailyHouseConsumptionWhId)).val) || 0;
                            
                                // Energie zum Tagesverbrauch addieren
                                currentDailyConsumptionWh += energyWh;
                            
                                // Werte in die Datenpunkte schreiben
                                setState(dailyHouseConsumptionWhId, currentDailyConsumptionWh.toFixed(2), true); // Wh auf 2 Nachkommastellen
                                setState(dailyHouseConsumptionKWhId, (currentDailyConsumptionWh / 1000).toFixed(3), true); // kWh auf 3 Nachkommastellen
                            
                                log(`Hausverbrauch addiert. Neue Summe: ${currentDailyConsumptionWh.toFixed(2)} Wh (${(currentDailyConsumptionWh / 1000).toFixed(3)} kWh)`);
                            
                                // Werte für die nächste Iteration speichern
                                lastPowerValue = currentPower;
                                lastUpdateTime = currentTime;
                            });
                            
                            // 3. Reset der Tagessummen um Mitternacht
                            schedule('0 0 * * *', async function () {
                                log("Mitternacht erreicht, setze täglichen Hausverbrauch zurück.");
                                setState(dailyHouseConsumptionWhId, 0, true);
                                setState(dailyHouseConsumptionKWhId, 0, true);
                            
                                // Wichtig: lastUpdateTime muss auch zurückgesetzt werden für korrekte delta-t Berechnung am neuen Tag
                                // und lastPowerValue für den ersten Wert des neuen Tages
                                lastUpdateTime = new Date().getTime();
                                lastPowerValue = parseFloat((await getStateAsync(currentHouseConsumptionPowerId)).val) || 0; // Aktuellen Power-Wert erneut holen
                            
                                log("Täglicher Hausverbrauch wurde zurückgesetzt.");
                            });
                            
                            // Optional: Info-Log beim Start des Skripts
                            log("Skript zum Überwachen des täglichen Hausverbrauchs gestartet.");
                            
                            1. Akku Be-und Entladung (schreibt die Werte (batIn und batOut) in DP's , einmal Wh und einmal kWh und wird täglich um 00:00 Uhr auf '0' gesetzt)
                            // ====== Konfiguration START ======
                            // Datenpunkt-ID, die die aktuelle Leistung in Watt liefert.
                            // Negativ für BatOut, Positiv für BatIn.
                            // Diesen Wert musst du an deine ioBroker-Installation anpassen!
                            const powerStateId = "senec.0.ENERGY.GUI_BAT_DATA_POWER"; // Beispiel: smartmeter.0.0_1_123_456_789.power_total_current
                            
                            // Datenpunkt-ID für die tägliche BatOut in Wh (wird erstellt, falls nicht vorhanden)
                            const dailyBatOutWhStateId = "0_userdata.0.Energie.Senec.Bat_Out_Wh";
                            // Datenpunkt-ID für die tägliche BatOut in kWh
                            const dailyBatOutKWhStateId = "0_userdata.0.Energie.Senec.Bat_Out_kWh";
                            
                            // Datenpunkt-ID für den täglichen BatIn in Wh (wird erstellt, falls nicht vorhanden)
                            const dailyBatInWhStateId = "0_userdata.0.Energie.Senec.Bat_In_Wh";
                            // Datenpunkt-ID für den täglichen BatIn in kWh
                            const dailyBatInKWhStateId = "0_userdata.0.Energie.Senec.Bat_In_kWh";
                            
                            // ====== Konfiguration ENDE ======
                            
                            
                            // Globale Variablen für die Berechnung der Tagessummen
                            let lastPowerValue = 0; // Letzter bekannter Leistungswert
                            let lastUpdateTime = new Date().getTime(); // Zeitpunkt der letzten Aktualisierung in Millisekunden
                            
                            // Funktion zum Initialisieren der Datenpunkte (falls nicht vorhanden)
                            function createStates() {
                                createState(dailyBatOutWhStateId, 0, {
                                    name: 'Daily BatOut (Wh)',
                                    type: 'number',
                                    read: true,
                                    write: false,
                                    role: 'value.power.consumption',
                                    unit: 'Wh'
                                });
                                createState(dailyBatOutKWhStateId, 0, {
                                    name: 'Daily BatOut (kWh)',
                                    type: 'number',
                                    read: true,
                                    write: false,
                                    role: 'value.power.consumption',
                                    unit: 'kWh'
                                });
                                createState(dailyBatInWhStateId, 0, {
                                    name: 'Daily BatIn (Wh)',
                                    type: 'number',
                                    read: true,
                                    write: false,
                                    role: 'value.power.consumption',
                                    unit: 'Wh'
                                });
                                createState(dailyBatInKWhStateId, 0, {
                                    name: 'Daily BatIn (kWh)',
                                    type: 'number',
                                    read: true,
                                    write: false,
                                    role: 'value.power.consumption',
                                    unit: 'kWh'
                                });
                            }
                            
                            // Beim Start des Skripts Datenpunkte erstellen und initialisieren
                            createStates();
                            
                            // Werte aus den Datenpunkten beim Skriptstart lesen, falls schon vorhanden
                            // Prüfen, ob die Datenpunkte bereits einen Wert haben, ansonsten auf 0 setzen
                            let initialBatOutState = getState(dailyBatOutWhStateId);
                            if (initialBatOutState && initialBatOutState.val !== null) {
                                log(`Initialer Wert für BatOut Wh: ${initialBatOutState.val}`);
                            } else {
                                setState(dailyBatOutWhStateId, 0);
                                log(`Datenpunkt ${dailyBatOutWhStateId} auf 0 gesetzt.`);
                            }
                            
                            let initialBatInState = getState(dailyBatInWhStateId);
                            if (initialBatInState && initialBatInState.val !== null) {
                                log(`Initialer Wert für BatIn Wh: ${initialBatInState.val}`);
                            } else {
                                setState(dailyBatInWhStateId, 0);
                                log(`Datenpunkt ${dailyBatInWhStateId} auf 0 gesetzt.`);
                            }
                            
                            // Trigger bei Änderung des Leistungsdatenpunkts
                            on({ id: powerStateId, change: 'ne' }, async function (obj) {
                                const currentPower = obj.state.val; // Aktueller Leistungswert in Watt
                                const currentTime = new Date().getTime(); // Aktueller Zeitstempel in Millisekunden
                            
                                // Wenn der Wert zum ersten Mal kommt oder Zeitunterschied zu gering ist
                                if (lastPowerValue === 0 && lastUpdateTime === new Date().getTime()) { // Initialisierung
                                    lastPowerValue = currentPower;
                                    lastUpdateTime = currentTime;
                                    log("Initialisierung der Leistungswerte.");
                                    return;
                                }
                            
                                const timeDiffSeconds = (currentTime - lastUpdateTime) / 1000; // Zeitdifferenz in Sekunden
                            
                                if (timeDiffSeconds <= 0) { // Falls keine Zeit vergangen ist (z.B. zu schnelle Updates)
                                    log("Zeitdifferenz ist 0 oder negativ, Überspringe Berechnung.");
                                    return;
                                }
                            
                                // Leistung * Zeit = Energie (Wattsekunden)
                                const energyWs = currentPower * timeDiffSeconds;
                                const energyWh = energyWs / 3600; // Umrechnung von Wattsekunden in Wattstunden
                            
                                log(`Aktuelle Leistung: ${currentPower} W, Zeitdiff: ${timeDiffSeconds.toFixed(2)} s, Berechnete Energie: ${energyWh.toFixed(2)} Wh`);
                            
                                // Sicherstellen, dass die gelesenen Werte Zahlen sind (durch parseFloat oder den Unary-Plus-Operator)
                                let currentBatInWh = parseFloat((await getStateAsync(dailyBatInWhStateId)).val) || 0;
                                let currentBatOutWh = parseFloat((await getStateAsync(dailyBatOutWhStateId)).val) || 0;
                            
                                if (currentPower < 0) { // BatOut
                                    currentBatOutWh += Math.abs(energyWh); // Absolutwert, damit die Summe positiv ist
                                    setState(dailyBatOutWhStateId, currentBatOutWh.toFixed(2), true);
                                    setState(dailyBatOutKWhStateId, (currentBatOutWh / 1000).toFixed(3), true);
                                    log(`BatOut addiert. Neue Summe: ${currentBatOutWh.toFixed(2)} Wh`);
                                } else { // BatIn
                                    currentBatInWh += energyWh;
                                    setState(dailyBatInWhStateId, currentBatInWh.toFixed(2), true);
                                    setState(dailyBatInKWhStateId, (currentBatInWh / 1000).toFixed(3), true);
                                    log(`BatIn addiert. Neue Summe: ${currentBatInWh.toFixed(2)} Wh`);
                                }
                            
                                // Werte für die nächste Iteration speichern
                                lastPowerValue = currentPower;
                                lastUpdateTime = currentTime;
                            });
                            
                            
                            // Reset der Tagessummen um Mitternacht
                            schedule('0 0 * * *', async function () {
                                log("Mitternacht erreicht, setze Tagessummen zurück.");
                                setState(dailyBatOutWhStateId, 0, true);
                                setState(dailyBatOutKWhStateId, 0, true);
                                setState(dailyBatInWhStateId, 0, true);
                                setState(dailyBatInKWhStateId, 0, true);
                                // lastUpdateTime muss auch zurückgesetzt werden, um korrekte delta-t Berechnung am neuen Tag zu gewährleisten
                                lastUpdateTime = new Date().getTime();
                                lastPowerValue = (await getStateAsync(powerStateId)).val || 0; // Aktuellen Power-Wert erneut holen
                            
                                log("Tagessummen wurden zurückgesetzt.");
                            });
                            
                            // Optional: Für Debugging, wenn das Skript startet
                            log("Skript zum Überwachen von BatOut und BatIn gestartet.");
                            
                            1. Grid Power (schreibt die Werte in DP's (Einspeisung und Netzbezug), einmal Wh und einmal kWh und wird täglich um 00:00 Uhr auf '0' gesetzt)
                            // ====== Konfiguration START ======
                            // Datenpunkt-ID, die die aktuelle Leistung in Watt liefert.
                            // Negativ für Einspeisung, Positiv für Netzbezug.
                            // Diesen Wert musst du an deine ioBroker-Installation anpassen!
                            const powerStateId = "senec.0.ENERGY.GUI_GRID_POW"; // Beispiel: smartmeter.0.0_1_123_456_789.power_total_current
                            
                            // Datenpunkt-ID für die tägliche Einspeisung in Wh (wird erstellt, falls nicht vorhanden)
                            const dailyFeedInWhStateId = "0_userdata.0.Energie.Senec.Tages_Einspeisung_Wh";
                            // Datenpunkt-ID für die tägliche Einspeisung in kWh
                            const dailyFeedInKWhStateId = "0_userdata.0.Energie.Senec.Tages_Einspeisung_kWh";
                            
                            // Datenpunkt-ID für den täglichen Netzbezug in Wh (wird erstellt, falls nicht vorhanden)
                            const dailyGridPurchaseWhStateId = "0_userdata.0.Energie.Senec.Tages_Netzbezug_Wh";
                            // Datenpunkt-ID für den täglichen Netzbezug in kWh
                            const dailyGridPurchaseKWhStateId = "0_userdata.0.Energie.Senec.Tages_Netzbezug_kWh";
                            
                            // ====== Konfiguration ENDE ======
                            
                            
                            // Globale Variablen für die Berechnung der Tagessummen
                            let lastPowerValue = 0; // Letzter bekannter Leistungswert
                            let lastUpdateTime = new Date().getTime(); // Zeitpunkt der letzten Aktualisierung in Millisekunden
                            
                            // Funktion zum Initialisieren der Datenpunkte (falls nicht vorhanden)
                            function createStates() {
                                createState(dailyFeedInWhStateId, 0, {
                                    name: 'Tägliche Einspeisung (Wh)',
                                    type: 'number',
                                    read: true,
                                    write: false,
                                    role: 'value.power.consumption',
                                    unit: 'Wh'
                                });
                                createState(dailyFeedInKWhStateId, 0, {
                                    name: 'Tägliche Einspeisung (kWh)',
                                    type: 'number',
                                    read: true,
                                    write: false,
                                    role: 'value.power.consumption',
                                    unit: 'kWh'
                                });
                                createState(dailyGridPurchaseWhStateId, 0, {
                                    name: 'Täglicher Netzbezug (Wh)',
                                    type: 'number',
                                    read: true,
                                    write: false,
                                    role: 'value.power.consumption',
                                    unit: 'Wh'
                                });
                                createState(dailyGridPurchaseKWhStateId, 0, {
                                    name: 'Täglicher Netzbezug (kWh)',
                                    type: 'number',
                                    read: true,
                                    write: false,
                                    role: 'value.power.consumption',
                                    unit: 'kWh'
                                });
                            }
                            
                            // Beim Start des Skripts Datenpunkte erstellen und initialisieren
                            createStates();
                            
                            // Werte aus den Datenpunkten beim Skriptstart lesen, falls schon vorhanden
                            // Prüfen, ob die Datenpunkte bereits einen Wert haben, ansonsten auf 0 setzen
                            let initialFeedInState = getState(dailyFeedInWhStateId);
                            if (initialFeedInState && initialFeedInState.val !== null) {
                                log(`Initialer Wert für Einspeisung Wh: ${initialFeedInState.val}`);
                            } else {
                                setState(dailyFeedInWhStateId, 0);
                                log(`Datenpunkt ${dailyFeedInWhStateId} auf 0 gesetzt.`);
                            }
                            
                            let initialGridPurchaseState = getState(dailyGridPurchaseWhStateId);
                            if (initialGridPurchaseState && initialGridPurchaseState.val !== null) {
                                log(`Initialer Wert für Netzbezug Wh: ${initialGridPurchaseState.val}`);
                            } else {
                                setState(dailyGridPurchaseWhStateId, 0);
                                log(`Datenpunkt ${dailyGridPurchaseWhStateId} auf 0 gesetzt.`);
                            }
                            
                            // Trigger bei Änderung des Leistungsdatenpunkts
                            on({ id: powerStateId, change: 'ne' }, async function (obj) {
                                const currentPower = obj.state.val; // Aktueller Leistungswert in Watt
                                const currentTime = new Date().getTime(); // Aktueller Zeitstempel in Millisekunden
                            
                                // Wenn der Wert zum ersten Mal kommt oder Zeitunterschied zu gering ist
                                // Hier ist es wichtig, dass lastPowerValue und lastUpdateTime initialisiert werden
                                if (lastPowerValue === 0 && lastUpdateTime === new Date().getTime()) { // Initialisierung
                                    const powerState = getState(powerStateId);
                                    if (powerState && powerState.val !== null) {
                                        lastPowerValue = powerState.val;
                                    } else {
                                        lastPowerValue = 0; // Fallback, falls kein Wert verfügbar
                                    }
                                    lastUpdateTime = currentTime;
                                    log("Initialisierung der Leistungswerte beim ersten Trigger.");
                                    return;
                                }
                            
                            
                                const timeDiffSeconds = (currentTime - lastUpdateTime) / 1000; // Zeitdifferenz in Sekunden
                            
                                if (timeDiffSeconds <= 0) { // Falls keine Zeit vergangen ist (z.B. zu schnelle Updates)
                                    log("Zeitdifferenz ist 0 oder negativ, Überspringe Berechnung.");
                                    return;
                                }
                            
                                // Leistung * Zeit = Energie (Wattsekunden)
                                const energyWs = currentPower * timeDiffSeconds;
                                const energyWh = energyWs / 3600; // Umrechnung von Wattsekunden in Wattstunden
                            
                                log(`Aktuelle Leistung: ${currentPower} W, Zeitdiff: ${timeDiffSeconds.toFixed(2)} s, Berechnete Energie: ${energyWh.toFixed(2)} Wh`);
                            
                                // **KORRIGIERTER BEREICH START**
                                // Sicherstellen, dass die gelesenen Werte Zahlen sind (durch parseFloat oder den Unary-Plus-Operator)
                                let currentFeedInWh = parseFloat((await getStateAsync(dailyFeedInWhStateId)).val) || 0;
                                let currentGridPurchaseWh = parseFloat((await getStateAsync(dailyGridPurchaseWhStateId)).val) || 0;
                                // **KORRIGIERTER BEREICH ENDE**
                            
                                if (currentPower < 0) { // Einspeisung
                                    currentFeedInWh += Math.abs(energyWh); // Absolutwert, damit die Summe positiv ist
                                    setState(dailyFeedInWhStateId, currentFeedInWh.toFixed(2), true);
                                    setState(dailyFeedInKWhStateId, (currentFeedInWh / 1000).toFixed(3), true);
                                    log(`Einspeisung addiert. Neue Summe: ${currentFeedInWh.toFixed(2)} Wh`);
                                } else { // Netzbezug
                                    currentGridPurchaseWh += energyWh;
                                    setState(dailyGridPurchaseWhStateId, currentGridPurchaseWh.toFixed(2), true);
                                    setState(dailyGridPurchaseKWhStateId, (currentGridPurchaseWh / 1000).toFixed(3), true);
                                    log(`Netzbezug addiert. Neue Summe: ${currentGridPurchaseWh.toFixed(2)} Wh`);
                                }
                            
                                // Werte für die nächste Iteration speichern
                                lastPowerValue = currentPower;
                                lastUpdateTime = currentTime;
                            });
                            
                            
                            // Reset der Tagessummen um Mitternacht
                            schedule('0 0 * * *', async function () {
                                log("Mitternacht erreicht, setze Tagessummen zurück.");
                                setState(dailyFeedInWhStateId, 0, true);
                                setState(dailyFeedInKWhStateId, 0, true);
                                setState(dailyGridPurchaseWhStateId, 0, true);
                                setState(dailyGridPurchaseKWhStateId, 0, true);
                                // lastUpdateTime muss auch zurückgesetzt werden, um korrekte delta-t Berechnung am neuen Tag zu gewährleisten
                                lastUpdateTime = new Date().getTime();
                                lastPowerValue = (await getStateAsync(powerStateId)).val || 0; // Aktuellen Power-Wert erneut holen
                            
                                log("Tagessummen wurden zurückgesetzt.");
                            });
                            
                            // Optional: Für Debugging, wenn das Skript startet
                            log("Skript zum Überwachen von Einspeisung und Netzbezug gestartet.");
                            

                            wer Lust hat kann ja mit testen ob das so passt.

                            R Offline
                            R Offline
                            RicoStriese
                            schrieb am zuletzt editiert von
                            #371

                            @icebear Danke für die Arbeit, habe alles übernommen. Es funktioniert super. Nochmals besten Danke für die Mühe.:clap: :clap:

                            1 Antwort Letzte Antwort
                            0
                            • icebearI icebear

                              @musicnrw said in [Neuer Adapter] Senec Home Adapter:

                              Also, wie und wo richte ich Deine Scripte in meiner Konfiguration ein,

                              Scripte von oben kopieren und dann auf 'Skripte'

                              Senec_1.png

                              Dann legst 1. Einen neuen Ordner (im Root-Verzeichnis an), dann 2. den Ordner anklicken (das er 'blau' markiert ist) und dann oben auf 3. das '+' für neues Script.

                              Senec_2.png

                              Dann JS auswählen

                              Senec_3.png

                              Dann einen Namen vergeben und das kopierte Script einfügen.

                              Senec_4.png

                              Auf den 'roten Pfeil' Script starten.

                              Unter > 0_userdata.0.Energie.Senec sollten dann die DP erstellt und mit den Werten befüllt werden.

                              M Offline
                              M Offline
                              musicnrw
                              schrieb am zuletzt editiert von
                              #372

                              @icebear, super. Vielen Dank für Deine Arbeit. Ich werde es am Wochenende umsetzen.

                              1 Antwort Letzte Antwort
                              0
                              • D Offline
                                D Offline
                                DiMe
                                schrieb am zuletzt editiert von
                                #373

                                Hi Zusammen,
                                habe heute Zeit gehabt und habe mich dem Thema angenommen. War schneller fertig als ich dachte. Es klappt alles wunderbar. Vielen Dank für die sehr wertvollen Beiträge!

                                1 Antwort Letzte Antwort
                                0
                                • H Offline
                                  H Offline
                                  HansJochen
                                  schrieb am zuletzt editiert von
                                  #374

                                  Guten Morgen,

                                  ich bin gerade auf diesen Thread gestoßen und habe das für mich sehr ähnlich gelöst wie Icebear mit dem hier geteilten Script. Ich möchte hier eine Idee teilen, die aber anders als dieses Script nicht einfach für jeden Senec Besitzer möglich ist und dann auch für jeden etwas anders. Vielleicht mag das aber der eine oder andere für sich auch umsetzen.

                                  Das Summieren der Speicher Werte funktioniert natürlich nur, solange ioBroker läuft. Das wird meistens der Fall sein. Ich ermittle seit Jahren die summierten Verbrauchswerte meiner Wärmepumpe auf die gleiche Art mit gutem Ergebnis. Durch Updates oder Wartung verlorene Verbrauchswerte spielen dort in meiner Statistik eigentlich keine große Rolle. Allerdings: Wenn der Speicher gerade mal nicht kommunizieren mag (NPU Fehler oder sonstwas), gehen ja auch Werte verloren.

                                  Für die Einspeisung und den Netzbezug habe ich Zähler, die ich über einen Tibber Pulse auslese. Die haben geringere Auflösung (die Nachkommastelle wird nicht übermittelt), sind aber sonst natürlich sehr genau und ausfallsicher. Deswegen verwende ich für diese Werte die Zählerwerte und berechne nur Hausverbrauch und Produktion so, wie im in Icebears Skript.

                                  Die Möglichkeiten sind hier vielfältig, je nach Installation und Alter der PV Anlage messen die Zähler etwas anderes. Der Weg ist folgender:

                                  • Ich habe einen Cronjob, der mir jede Stunde, jeden Tag, jeden Monat und jedes Jahr den Zählerstand in einen Datenpunkt kopiert. Bei Skript Neustart prüfe ich den Zeitstempel dieser Zählerwerte und aktualisiere sie, falls sie älter als erwartet sind (dann natürlich zu spät, aber das ist besser, als einen ganzen Jahreswechsel zu verpassen).
                                  • Ein Trigger auf jeden Zähler berechnet die Differenz aus aktuellem Zählerstand und Zählerstand zu Beginn der aktuellen Stunde, Monats, ... und speichert das als Verbrauchswert in diesem Zeitraum.

                                  Die beste Lösung wäre vermutlich eine Mischung der beiden Vorgehensweisen: Die dynamische Berechnung wie in Icebears Script (wegen der höheren Auflösung) mit Korrektur auf Basis der Zählerstände, soweit erforderlich.

                                  1 Antwort Letzte Antwort
                                  1
                                  • T Offline
                                    T Offline
                                    ToniTL
                                    schrieb am zuletzt editiert von
                                    #375

                                    Hallo,
                                    ich habe mal eine Frage bezüglich des Projekts an sich. Läuft das noch oder wurde das jetzt auf Eis gelegt?

                                    Leider hört es sich teils so an, das SENEC vielleicht den API-Zugang sperren könnte. Für mich zumindest kein gutes Zeichen, wenn dieser Zugang beim V4 gänzlich weggelassen wurde.
                                    Ich habe ebenso jetzt eine manuelle Zählung eingerichtet, welche aber auf die Zuverlässigkeit und Beständigkeit von SENEC aufbaut.

                                    Hat sich jemand schon einmal darüber Gedanken gemacht, den Enfluri direkt anzuzapfen? Das heißt als read only (sniffer)? Welche Daten werden darüber genau geliefert?

                                    Mit diesem Gedanken spiele ich schon länger und es würde unabhängiger von SENECs Laune laufen. Ich verstehe den Sicherheitsgedanken seitens SENEC und den damit verbundenen Onlinezwang. Aber bei jedem Update kann Schluss mit der API sein.
                                    Ich mag die Unabhängigkeit und mein persönliches Hausdashboard. Ebenso läuft meine PV-Überschussbeladung meiner Wallbox mit Daten von SENEC. Ich habe es zwar auf das Nötigste reduziert (Einspeisung und Bezug über Wattwächter). Aber Hausverbrauch an sich wäre noch nett.

                                    O 1 Antwort Letzte Antwort
                                    1
                                    • T ToniTL

                                      Hallo,
                                      ich habe mal eine Frage bezüglich des Projekts an sich. Läuft das noch oder wurde das jetzt auf Eis gelegt?

                                      Leider hört es sich teils so an, das SENEC vielleicht den API-Zugang sperren könnte. Für mich zumindest kein gutes Zeichen, wenn dieser Zugang beim V4 gänzlich weggelassen wurde.
                                      Ich habe ebenso jetzt eine manuelle Zählung eingerichtet, welche aber auf die Zuverlässigkeit und Beständigkeit von SENEC aufbaut.

                                      Hat sich jemand schon einmal darüber Gedanken gemacht, den Enfluri direkt anzuzapfen? Das heißt als read only (sniffer)? Welche Daten werden darüber genau geliefert?

                                      Mit diesem Gedanken spiele ich schon länger und es würde unabhängiger von SENECs Laune laufen. Ich verstehe den Sicherheitsgedanken seitens SENEC und den damit verbundenen Onlinezwang. Aber bei jedem Update kann Schluss mit der API sein.
                                      Ich mag die Unabhängigkeit und mein persönliches Hausdashboard. Ebenso läuft meine PV-Überschussbeladung meiner Wallbox mit Daten von SENEC. Ich habe es zwar auf das Nötigste reduziert (Einspeisung und Bezug über Wattwächter). Aber Hausverbrauch an sich wäre noch nett.

                                      O Offline
                                      O Offline
                                      oxident
                                      schrieb am zuletzt editiert von
                                      #376

                                      @tonitl Das wäre schon recht hilfreich und wichtig. Auch für die, die mit den NPU-Abstürzen zu kämpfen haben.

                                      Ich glaube, der Bus wird sogar am Senec selber durchgeschliffen, oder?

                                      B 1 Antwort Letzte Antwort
                                      1
                                      • O oxident

                                        @tonitl Das wäre schon recht hilfreich und wichtig. Auch für die, die mit den NPU-Abstürzen zu kämpfen haben.

                                        Ich glaube, der Bus wird sogar am Senec selber durchgeschliffen, oder?

                                        B Offline
                                        B Offline
                                        Blockmove
                                        schrieb am zuletzt editiert von
                                        #377

                                        @oxident said in [Neuer Adapter] Senec Home Adapter:

                                        @tonitl Das wäre schon recht hilfreich und wichtig. Auch für die, die mit den NPU-Abstürzen zu kämpfen haben.

                                        Ich glaube, der Bus wird sogar am Senec selber durchgeschliffen, oder?

                                        Mit sowas sollte es funktionieren:
                                        RS485-Sniffer

                                        Seit dem ich mich vom Senec-Adapter verabschiedet hab und die Abfrage nur noch über curl mache, hab ich keinerlei NPU-Abstürze mehr gehabt.
                                        Die Kommunikationsfehler sind auch sehr viel weniger geworden. Ich hol mir halt nur noch die Daten, die ich wirklich brauche.

                                        The difference beetween Man and Boys:
                                        The price of their toys 😀

                                        T 1 Antwort Letzte Antwort
                                        0
                                        • B Blockmove

                                          @oxident said in [Neuer Adapter] Senec Home Adapter:

                                          @tonitl Das wäre schon recht hilfreich und wichtig. Auch für die, die mit den NPU-Abstürzen zu kämpfen haben.

                                          Ich glaube, der Bus wird sogar am Senec selber durchgeschliffen, oder?

                                          Mit sowas sollte es funktionieren:
                                          RS485-Sniffer

                                          Seit dem ich mich vom Senec-Adapter verabschiedet hab und die Abfrage nur noch über curl mache, hab ich keinerlei NPU-Abstürze mehr gehabt.
                                          Die Kommunikationsfehler sind auch sehr viel weniger geworden. Ich hol mir halt nur noch die Daten, die ich wirklich brauche.

                                          T Offline
                                          T Offline
                                          ToniTL
                                          schrieb am zuletzt editiert von
                                          #378

                                          @blockmove läuft bei dir das Setup schon über den enfluri oder rufst du die Daten über curl vom senec selbst ab?

                                          Solltest du es schon über den enfluri betreiben, könntest du mitteilen wie du es angestellt hast? Schritt für Schritt Anleitung?

                                          B 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

                                          724

                                          Online

                                          32.4k

                                          Benutzer

                                          81.5k

                                          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