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. ioBroker Allgemein
  4. PV Überwachung hoymiles

NEWS

  • Weihnachtsangebot 2025! 🎄
    BluefoxB
    Bluefox
    23
    1
    1.3k

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

  • Monatsrückblick – September 2025
    BluefoxB
    Bluefox
    14
    1
    2.5k

PV Überwachung hoymiles

Geplant Angeheftet Gesperrt Verschoben ioBroker Allgemein
13 Beiträge 3 Kommentatoren 1.1k Aufrufe 4 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.
  • M martinschm

    Hi,

    Ich habe Ende letzten Jahres eine Zaun PV mit 26 Modulen und 5 hoymiles Wechselrichtern selber gebaut.

    Über eine openDTU ist die Anlage in iobroker eingebunden.

    Jetzt ist mir letztens eher zufällig aufgefallen, das ein PV Modul keine Leistung bringt. Der Gesamtbetrag war knapp ein Drittel niedriger als der der benachbarten Module. Schien also schon eine Weile ein Problem vorzuliegen.

    Heute ist mir dann aufgefallen das ein WR hing und der Ertrag fast null war.

    Ich würde das ganze gerne automatisch überwachen. Da der Ertrag stark vom Wetter abhängig ist machen dynamische Grenzwerte wahrscheinlich am meisten Sinn.

    Wie würdet ihr das überwachen?
    Hab überlegt den Durchschnitt über die anderen Module am gleichen WR zu bilden und dann ein Alarm wenn der Wert mehr als 10% oder so drunter liegt.

    Und auf Ebene der WRs schauen ob einer mehr als 10% hinter den anderen herhinkt.

    Gibt es andere Ideen?

    R Offline
    R Offline
    Ralf 2
    schrieb am zuletzt editiert von
    #2

    @martinschm sagte in PV Überwachung hoymiles:

    Über eine openDTU ist die Anlage in iobroker eingebunden.

    Ich weiß nicht, was OpenDPU an weiteren Datenpunkten liefert, ggf. kann man hier auch noch irgendwelche Fehlerstatus auslesen und mit berücksichtigen. Aber dein Ansatz ist erst einmal gut und wohl richtig.

    Gruß Ralf

    M 1 Antwort Letzte Antwort
    1
    • R Ralf 2

      @martinschm sagte in PV Überwachung hoymiles:

      Über eine openDTU ist die Anlage in iobroker eingebunden.

      Ich weiß nicht, was OpenDPU an weiteren Datenpunkten liefert, ggf. kann man hier auch noch irgendwelche Fehlerstatus auslesen und mit berücksichtigen. Aber dein Ansatz ist erst einmal gut und wohl richtig.

      M Offline
      M Offline
      martinschm
      schrieb am zuletzt editiert von
      #3

      @ralf-2 said in PV Überwachung hoymiles:

      @martinschm sagte in PV Überwachung hoymiles:

      Über eine openDTU ist die Anlage in iobroker eingebunden.

      Ich weiß nicht, was OpenDPU an weiteren Datenpunkten liefert, ggf. kann man hier auch noch irgendwelche Fehlerstatus auslesen und mit berücksichtigen. Aber dein Ansatz ist erst einmal gut und wohl richtig.

      Fehlerstatus wird aktuell leider nicht mitgeliefert. Hab ich schon ein Feature requests zu aufgemacht.

      R 1 Antwort Letzte Antwort
      0
      • M martinschm

        @ralf-2 said in PV Überwachung hoymiles:

        @martinschm sagte in PV Überwachung hoymiles:

        Über eine openDTU ist die Anlage in iobroker eingebunden.

        Ich weiß nicht, was OpenDPU an weiteren Datenpunkten liefert, ggf. kann man hier auch noch irgendwelche Fehlerstatus auslesen und mit berücksichtigen. Aber dein Ansatz ist erst einmal gut und wohl richtig.

        Fehlerstatus wird aktuell leider nicht mitgeliefert. Hab ich schon ein Feature requests zu aufgemacht.

        R Offline
        R Offline
        Ralf 2
        schrieb am zuletzt editiert von
        #4

        @martinschm
        Wäre zwar schön aber bestimmt nicht zwingend nötig.
        Ich würde einfach die Erträge der einzelnen Module Module für einen Tag aufsummieren und dann bei Abweichung von x Prozent eine Meldung geben.
        Bedenke dabei, das vielleicht auch etwas ein Modul mal verschatten kann (Handwerkeraute, oder so etwas). Ich würde das einfach mal eine Woche ohne Alarm laufen lassen und dann den Grenzwert in Prozent daraus ableiten.
        Das bekommen wir schon als Teamarbeit hier im Forum hin. Daten solltest du mal im Vorfeld sammeln.

        Gruß Ralf

        M 1 Antwort Letzte Antwort
        0
        • B Offline
          B Offline
          Beowolf
          schrieb am zuletzt editiert von
          #5

          Der Opendtu Adapter zeigt doch bei jedem WR die Datenpunkte "producing" und "last_update" aus. Den Datenpunkt "available" gibt es auch noch.

          Da ist doch alles vorhanden was man braucht.

          Die Natur braucht nicht unseren Schutz, sie braucht unsere Abwesenheit.

          M 1 Antwort Letzte Antwort
          0
          • B Beowolf

            Der Opendtu Adapter zeigt doch bei jedem WR die Datenpunkte "producing" und "last_update" aus. Den Datenpunkt "available" gibt es auch noch.

            Da ist doch alles vorhanden was man braucht.

            M Offline
            M Offline
            martinschm
            schrieb am zuletzt editiert von
            #6

            @beowolf said in PV Überwachung hoymiles:

            Der Opendtu Adapter zeigt doch bei jedem WR die Datenpunkte "producing" und "last_update" aus. Den Datenpunkt "available" gibt es auch noch.

            Da ist doch alles vorhanden was man braucht.

            Leider nicht ganz. producing bezieht sich halt nur auf einen WR, aber wenn mal ein Modul ausfällt bekommst du es so nicht mit.

            B 1 Antwort Letzte Antwort
            0
            • R Ralf 2

              @martinschm
              Wäre zwar schön aber bestimmt nicht zwingend nötig.
              Ich würde einfach die Erträge der einzelnen Module Module für einen Tag aufsummieren und dann bei Abweichung von x Prozent eine Meldung geben.
              Bedenke dabei, das vielleicht auch etwas ein Modul mal verschatten kann (Handwerkeraute, oder so etwas). Ich würde das einfach mal eine Woche ohne Alarm laufen lassen und dann den Grenzwert in Prozent daraus ableiten.
              Das bekommen wir schon als Teamarbeit hier im Forum hin. Daten solltest du mal im Vorfeld sammeln.

              M Offline
              M Offline
              martinschm
              schrieb am zuletzt editiert von martinschm
              #7

              @ralf-2 said in PV Überwachung hoymiles:

              @martinschm
              Wäre zwar schön aber bestimmt nicht zwingend nötig.
              Ich würde einfach die Erträge der einzelnen Module Module für einen Tag aufsummieren und dann bei Abweichung von x Prozent eine Meldung geben.
              Bedenke dabei, das vielleicht auch etwas ein Modul mal verschatten kann (Handwerkeraute, oder so etwas). Ich würde das einfach mal eine Woche ohne Alarm laufen lassen und dann den Grenzwert in Prozent daraus ableiten.
              Das bekommen wir schon als Teamarbeit hier im Forum hin. Daten solltest du mal im Vorfeld sammeln.

              Ich hab mal mit perplexity.ai ein paar Runden gedreht und nutze aktuell dieses Skript

              const wrThreshold = 0.7;
              const moduleThreshold = 0.7;
              const minProduction = 5;
              const telegramInstance = 'telegram.0';
              const warnDelay = 15 * 60 * 1000; // 15 Minuten in ms
              
              // Gruppen-Konfiguration wie gehabt
              const groups = [
                {
                  name: "Zaun",
                  wrs: [
                    { id: "xx", name: "WR1", moduleCount: 6 },
                    { id: "xx", name: "WR2", moduleCount: 6 },
                    { id: "xx", name: "WR3", moduleCount: 6 }
                  ]
                },
                {
                  name: "Gartenhütte",
                  wrs: [
                    { id: "xx", name: "WR4", moduleCount: 4 },
                    { id: "xx", name: "WR5", moduleCount: 4 }
                  ]
                }
              ];
              
              // Statusspeicher
              if (!globalThis.wrStatus) globalThis.wrStatus = {};
              
              function checkWRs() {
                  let now = Date.now();
              
                  groups.forEach(group => {
                      let wrPowers = [];
                      let activeWRs = [];
              
                      // 1. Prüfe, welche WR produzieren
                      group.wrs.forEach((wr, i) => {
                          const producingState = getState(`opendtu.0.${wr.id}.producing`).val;
                          const isProducing = producingState === true || producingState === 'true';
                          if (isProducing) {
                              let wrPower = getState(`opendtu.0.${wr.id}.power_dc`).val;
                              wrPowers[i] = wrPower;
                              activeWRs.push({ index: i, ...wr, wrPower });
                          } else {
                              wrPowers[i] = 0;
                          }
                      });
              
                      // 2. WR-Vergleich (nur aktive WRs und erst nach 15 Minuten)
                      if (activeWRs.length > 1) {
                          let avgWR = activeWRs.reduce((sum, wr) => sum + wr.wrPower, 0) / activeWRs.length;
                          activeWRs.forEach(wr => {
                              let status = globalThis.wrStatus[wr.name] || { warnSince: null, warned: false };
                              if (wr.wrPower < avgWR * wrThreshold) {
                                  if (!status.warnSince) status.warnSince = now;
                                  if (!status.warned && (now - status.warnSince) >= warnDelay) {
                                      sendTo(telegramInstance, 'send', {
                                          text: `⚠️ *WR-Warnung (${group.name})*: ${wr.name} liefert seit 15 Minuten nur ${wr.wrPower} W (Durchschnitt: ${avgWR.toFixed(1)} W)`
                                      });
                                      status.warned = true;
                                  }
                              } else {
                                  if (status.warned) {
                                      sendTo(telegramInstance, 'send', {
                                          text: `✅ *Entwarnung (${group.name})*: ${wr.name} liefert wieder ausreichend Leistung.`
                                      });
                                  }
                                  status.warnSince = null;
                                  status.warned = false;
                              }
                              globalThis.wrStatus[wr.name] = status;
                          });
                      }
              
                      // 3. Modulvergleich je WR (nur bei aktiven WRs, erst nach 15 Minuten)
                      activeWRs.forEach(wr => {
                          let modulePowers = [];
                          for (let m = 1; m <= wr.moduleCount; m++) {
                              let modPower = getState(`opendtu.0.${wr.id}.dc.input_${m}.power`).val;
                              modulePowers[m - 1] = modPower;
                          }
                          let avgModule = modulePowers.reduce((a, b) => a + b, 0) / wr.moduleCount;
                          modulePowers.forEach((mp, idx) => {
                              let key = `${wr.name}_modul${idx+1}`;
                              let status = globalThis.wrStatus[key] || { warnSince: null, warned: false };
                              if (mp < avgModule * moduleThreshold) {
                                  if (!status.warnSince) status.warnSince = now;
                                  if (!status.warned && (now - status.warnSince) >= warnDelay) {
                                      sendTo(telegramInstance, 'send', {
                                          text: `⚠️ *Modul-Warnung (${wr.name})*: Modul ${idx + 1} liefert seit 15 Minuten nur ${mp} W (Durchschnitt: ${avgModule.toFixed(1)} W)`
                                      });
                                      status.warned = true;
                                  }
                              } else {
                                  if (status.warned) {
                                      sendTo(telegramInstance, 'send', {
                                          text: `✅ *Entwarnung (${wr.name})*: Modul ${idx + 1} liefert wieder ausreichend Leistung.`
                                      });
                                  }
                                  status.warnSince = null;
                                  status.warned = false;
                              }
                              globalThis.wrStatus[key] = status;
                          });
                      });
              
                      // 4. Überwachung nicht-produzierender WRs (wie gehabt, ggf. auch mit 15min-Verzögerung anpassen)
                      group.wrs.forEach((wr, i) => {
                          const producingState = getState(`opendtu.0.${wr.id}.producing`).val;
                          const isProducing = producingState === true || producingState === 'true';
                          let status = globalThis.wrStatus[wr.name + "_prod"] || { warnSince: null, warned: false };
                          if (!isProducing) {
                              let anyOtherProducing = group.wrs.some((otherWr, otherIdx) => {
                                  if (otherIdx !== i) {
                                      const otherProducingState = getState(`opendtu.0.${otherWr.id}.producing`).val;
                                      return otherProducingState === true || otherProducingState === 'true';
                                  }
                                  return false;
                              });
                              if (anyOtherProducing) {
                                  if (!status.warnSince) status.warnSince = now;
                                  if (!status.warned && (now - status.warnSince) >= warnDelay) {
                                      sendTo(telegramInstance, 'send', {
                                          text: `🔴 *Ausfall (${group.name})*: ${wr.name} produziert seit 15 Minuten nichts, obwohl andere laufen!`
                                      });
                                      status.warned = true;
                                  }
                              } else {
                                  status.warnSince = null;
                                  status.warned = false;
                              }
                          } else {
                              if (status.warned) {
                                  sendTo(telegramInstance, 'send', {
                                      text: `✅ *Entwarnung (${group.name})*: ${wr.name} produziert wieder!`
                                  });
                              }
                              status.warnSince = null;
                              status.warned = false;
                          }
                          globalThis.wrStatus[wr.name + "_prod"] = status;
                      });
                  });
              }
              
              schedule('*/2 * * * *', checkWRs);
              
              

              Das ist die zweite Version, die erste hat zu viele Meldungen in den Morgen- und Abendstunden gebracht wenn einzelne Module kurz verschattet sind.

              Das Skript vergleicht die Module eines WRs miteinander und warnt wenn ein Module nach 15 min immer noch hinter den anderen herhinkt. Außerdem vergleicht es die WRs innerhalb von zwei Gruppen (wo die Module jeweils gleich ausgerichtet sind) miteinander.

              B 2 Antworten Letzte Antwort
              0
              • M martinschm

                @beowolf said in PV Überwachung hoymiles:

                Der Opendtu Adapter zeigt doch bei jedem WR die Datenpunkte "producing" und "last_update" aus. Den Datenpunkt "available" gibt es auch noch.

                Da ist doch alles vorhanden was man braucht.

                Leider nicht ganz. producing bezieht sich halt nur auf einen WR, aber wenn mal ein Modul ausfällt bekommst du es so nicht mit.

                B Offline
                B Offline
                Beowolf
                schrieb am zuletzt editiert von Beowolf
                #8

                @martinschm

                Na ja, es sind ja auch die Werte von Spannung, Strom und Leistung pro Eingang da. Dann auch noch die Einstrahlung in %.

                Das sind doch genug Werte um daraus etwas zu machen.

                Ich werde dein Skript mal testen. Ist bestimmt interessant.

                Etwas mehr Beschreibung, was wo bei den Einstellung eingegeben werden muß ist bestimmt nicht schlecht.

                Die Natur braucht nicht unseren Schutz, sie braucht unsere Abwesenheit.

                1 Antwort Letzte Antwort
                0
                • M martinschm

                  @ralf-2 said in PV Überwachung hoymiles:

                  @martinschm
                  Wäre zwar schön aber bestimmt nicht zwingend nötig.
                  Ich würde einfach die Erträge der einzelnen Module Module für einen Tag aufsummieren und dann bei Abweichung von x Prozent eine Meldung geben.
                  Bedenke dabei, das vielleicht auch etwas ein Modul mal verschatten kann (Handwerkeraute, oder so etwas). Ich würde das einfach mal eine Woche ohne Alarm laufen lassen und dann den Grenzwert in Prozent daraus ableiten.
                  Das bekommen wir schon als Teamarbeit hier im Forum hin. Daten solltest du mal im Vorfeld sammeln.

                  Ich hab mal mit perplexity.ai ein paar Runden gedreht und nutze aktuell dieses Skript

                  const wrThreshold = 0.7;
                  const moduleThreshold = 0.7;
                  const minProduction = 5;
                  const telegramInstance = 'telegram.0';
                  const warnDelay = 15 * 60 * 1000; // 15 Minuten in ms
                  
                  // Gruppen-Konfiguration wie gehabt
                  const groups = [
                    {
                      name: "Zaun",
                      wrs: [
                        { id: "xx", name: "WR1", moduleCount: 6 },
                        { id: "xx", name: "WR2", moduleCount: 6 },
                        { id: "xx", name: "WR3", moduleCount: 6 }
                      ]
                    },
                    {
                      name: "Gartenhütte",
                      wrs: [
                        { id: "xx", name: "WR4", moduleCount: 4 },
                        { id: "xx", name: "WR5", moduleCount: 4 }
                      ]
                    }
                  ];
                  
                  // Statusspeicher
                  if (!globalThis.wrStatus) globalThis.wrStatus = {};
                  
                  function checkWRs() {
                      let now = Date.now();
                  
                      groups.forEach(group => {
                          let wrPowers = [];
                          let activeWRs = [];
                  
                          // 1. Prüfe, welche WR produzieren
                          group.wrs.forEach((wr, i) => {
                              const producingState = getState(`opendtu.0.${wr.id}.producing`).val;
                              const isProducing = producingState === true || producingState === 'true';
                              if (isProducing) {
                                  let wrPower = getState(`opendtu.0.${wr.id}.power_dc`).val;
                                  wrPowers[i] = wrPower;
                                  activeWRs.push({ index: i, ...wr, wrPower });
                              } else {
                                  wrPowers[i] = 0;
                              }
                          });
                  
                          // 2. WR-Vergleich (nur aktive WRs und erst nach 15 Minuten)
                          if (activeWRs.length > 1) {
                              let avgWR = activeWRs.reduce((sum, wr) => sum + wr.wrPower, 0) / activeWRs.length;
                              activeWRs.forEach(wr => {
                                  let status = globalThis.wrStatus[wr.name] || { warnSince: null, warned: false };
                                  if (wr.wrPower < avgWR * wrThreshold) {
                                      if (!status.warnSince) status.warnSince = now;
                                      if (!status.warned && (now - status.warnSince) >= warnDelay) {
                                          sendTo(telegramInstance, 'send', {
                                              text: `⚠️ *WR-Warnung (${group.name})*: ${wr.name} liefert seit 15 Minuten nur ${wr.wrPower} W (Durchschnitt: ${avgWR.toFixed(1)} W)`
                                          });
                                          status.warned = true;
                                      }
                                  } else {
                                      if (status.warned) {
                                          sendTo(telegramInstance, 'send', {
                                              text: `✅ *Entwarnung (${group.name})*: ${wr.name} liefert wieder ausreichend Leistung.`
                                          });
                                      }
                                      status.warnSince = null;
                                      status.warned = false;
                                  }
                                  globalThis.wrStatus[wr.name] = status;
                              });
                          }
                  
                          // 3. Modulvergleich je WR (nur bei aktiven WRs, erst nach 15 Minuten)
                          activeWRs.forEach(wr => {
                              let modulePowers = [];
                              for (let m = 1; m <= wr.moduleCount; m++) {
                                  let modPower = getState(`opendtu.0.${wr.id}.dc.input_${m}.power`).val;
                                  modulePowers[m - 1] = modPower;
                              }
                              let avgModule = modulePowers.reduce((a, b) => a + b, 0) / wr.moduleCount;
                              modulePowers.forEach((mp, idx) => {
                                  let key = `${wr.name}_modul${idx+1}`;
                                  let status = globalThis.wrStatus[key] || { warnSince: null, warned: false };
                                  if (mp < avgModule * moduleThreshold) {
                                      if (!status.warnSince) status.warnSince = now;
                                      if (!status.warned && (now - status.warnSince) >= warnDelay) {
                                          sendTo(telegramInstance, 'send', {
                                              text: `⚠️ *Modul-Warnung (${wr.name})*: Modul ${idx + 1} liefert seit 15 Minuten nur ${mp} W (Durchschnitt: ${avgModule.toFixed(1)} W)`
                                          });
                                          status.warned = true;
                                      }
                                  } else {
                                      if (status.warned) {
                                          sendTo(telegramInstance, 'send', {
                                              text: `✅ *Entwarnung (${wr.name})*: Modul ${idx + 1} liefert wieder ausreichend Leistung.`
                                          });
                                      }
                                      status.warnSince = null;
                                      status.warned = false;
                                  }
                                  globalThis.wrStatus[key] = status;
                              });
                          });
                  
                          // 4. Überwachung nicht-produzierender WRs (wie gehabt, ggf. auch mit 15min-Verzögerung anpassen)
                          group.wrs.forEach((wr, i) => {
                              const producingState = getState(`opendtu.0.${wr.id}.producing`).val;
                              const isProducing = producingState === true || producingState === 'true';
                              let status = globalThis.wrStatus[wr.name + "_prod"] || { warnSince: null, warned: false };
                              if (!isProducing) {
                                  let anyOtherProducing = group.wrs.some((otherWr, otherIdx) => {
                                      if (otherIdx !== i) {
                                          const otherProducingState = getState(`opendtu.0.${otherWr.id}.producing`).val;
                                          return otherProducingState === true || otherProducingState === 'true';
                                      }
                                      return false;
                                  });
                                  if (anyOtherProducing) {
                                      if (!status.warnSince) status.warnSince = now;
                                      if (!status.warned && (now - status.warnSince) >= warnDelay) {
                                          sendTo(telegramInstance, 'send', {
                                              text: `🔴 *Ausfall (${group.name})*: ${wr.name} produziert seit 15 Minuten nichts, obwohl andere laufen!`
                                          });
                                          status.warned = true;
                                      }
                                  } else {
                                      status.warnSince = null;
                                      status.warned = false;
                                  }
                              } else {
                                  if (status.warned) {
                                      sendTo(telegramInstance, 'send', {
                                          text: `✅ *Entwarnung (${group.name})*: ${wr.name} produziert wieder!`
                                      });
                                  }
                                  status.warnSince = null;
                                  status.warned = false;
                              }
                              globalThis.wrStatus[wr.name + "_prod"] = status;
                          });
                      });
                  }
                  
                  schedule('*/2 * * * *', checkWRs);
                  
                  

                  Das ist die zweite Version, die erste hat zu viele Meldungen in den Morgen- und Abendstunden gebracht wenn einzelne Module kurz verschattet sind.

                  Das Skript vergleicht die Module eines WRs miteinander und warnt wenn ein Module nach 15 min immer noch hinter den anderen herhinkt. Außerdem vergleicht es die WRs innerhalb von zwei Gruppen (wo die Module jeweils gleich ausgerichtet sind) miteinander.

                  B Offline
                  B Offline
                  Beowolf
                  schrieb am zuletzt editiert von
                  #9

                  @martinschm sagte in PV Überwachung hoymiles:

                  nutze aktuell dieses Skript

                  wr.jpg

                  Wo kommen diese 78,2 W her? Wo wird das berechnet?

                  Die Natur braucht nicht unseren Schutz, sie braucht unsere Abwesenheit.

                  M 1 Antwort Letzte Antwort
                  0
                  • M martinschm

                    @ralf-2 said in PV Überwachung hoymiles:

                    @martinschm
                    Wäre zwar schön aber bestimmt nicht zwingend nötig.
                    Ich würde einfach die Erträge der einzelnen Module Module für einen Tag aufsummieren und dann bei Abweichung von x Prozent eine Meldung geben.
                    Bedenke dabei, das vielleicht auch etwas ein Modul mal verschatten kann (Handwerkeraute, oder so etwas). Ich würde das einfach mal eine Woche ohne Alarm laufen lassen und dann den Grenzwert in Prozent daraus ableiten.
                    Das bekommen wir schon als Teamarbeit hier im Forum hin. Daten solltest du mal im Vorfeld sammeln.

                    Ich hab mal mit perplexity.ai ein paar Runden gedreht und nutze aktuell dieses Skript

                    const wrThreshold = 0.7;
                    const moduleThreshold = 0.7;
                    const minProduction = 5;
                    const telegramInstance = 'telegram.0';
                    const warnDelay = 15 * 60 * 1000; // 15 Minuten in ms
                    
                    // Gruppen-Konfiguration wie gehabt
                    const groups = [
                      {
                        name: "Zaun",
                        wrs: [
                          { id: "xx", name: "WR1", moduleCount: 6 },
                          { id: "xx", name: "WR2", moduleCount: 6 },
                          { id: "xx", name: "WR3", moduleCount: 6 }
                        ]
                      },
                      {
                        name: "Gartenhütte",
                        wrs: [
                          { id: "xx", name: "WR4", moduleCount: 4 },
                          { id: "xx", name: "WR5", moduleCount: 4 }
                        ]
                      }
                    ];
                    
                    // Statusspeicher
                    if (!globalThis.wrStatus) globalThis.wrStatus = {};
                    
                    function checkWRs() {
                        let now = Date.now();
                    
                        groups.forEach(group => {
                            let wrPowers = [];
                            let activeWRs = [];
                    
                            // 1. Prüfe, welche WR produzieren
                            group.wrs.forEach((wr, i) => {
                                const producingState = getState(`opendtu.0.${wr.id}.producing`).val;
                                const isProducing = producingState === true || producingState === 'true';
                                if (isProducing) {
                                    let wrPower = getState(`opendtu.0.${wr.id}.power_dc`).val;
                                    wrPowers[i] = wrPower;
                                    activeWRs.push({ index: i, ...wr, wrPower });
                                } else {
                                    wrPowers[i] = 0;
                                }
                            });
                    
                            // 2. WR-Vergleich (nur aktive WRs und erst nach 15 Minuten)
                            if (activeWRs.length > 1) {
                                let avgWR = activeWRs.reduce((sum, wr) => sum + wr.wrPower, 0) / activeWRs.length;
                                activeWRs.forEach(wr => {
                                    let status = globalThis.wrStatus[wr.name] || { warnSince: null, warned: false };
                                    if (wr.wrPower < avgWR * wrThreshold) {
                                        if (!status.warnSince) status.warnSince = now;
                                        if (!status.warned && (now - status.warnSince) >= warnDelay) {
                                            sendTo(telegramInstance, 'send', {
                                                text: `⚠️ *WR-Warnung (${group.name})*: ${wr.name} liefert seit 15 Minuten nur ${wr.wrPower} W (Durchschnitt: ${avgWR.toFixed(1)} W)`
                                            });
                                            status.warned = true;
                                        }
                                    } else {
                                        if (status.warned) {
                                            sendTo(telegramInstance, 'send', {
                                                text: `✅ *Entwarnung (${group.name})*: ${wr.name} liefert wieder ausreichend Leistung.`
                                            });
                                        }
                                        status.warnSince = null;
                                        status.warned = false;
                                    }
                                    globalThis.wrStatus[wr.name] = status;
                                });
                            }
                    
                            // 3. Modulvergleich je WR (nur bei aktiven WRs, erst nach 15 Minuten)
                            activeWRs.forEach(wr => {
                                let modulePowers = [];
                                for (let m = 1; m <= wr.moduleCount; m++) {
                                    let modPower = getState(`opendtu.0.${wr.id}.dc.input_${m}.power`).val;
                                    modulePowers[m - 1] = modPower;
                                }
                                let avgModule = modulePowers.reduce((a, b) => a + b, 0) / wr.moduleCount;
                                modulePowers.forEach((mp, idx) => {
                                    let key = `${wr.name}_modul${idx+1}`;
                                    let status = globalThis.wrStatus[key] || { warnSince: null, warned: false };
                                    if (mp < avgModule * moduleThreshold) {
                                        if (!status.warnSince) status.warnSince = now;
                                        if (!status.warned && (now - status.warnSince) >= warnDelay) {
                                            sendTo(telegramInstance, 'send', {
                                                text: `⚠️ *Modul-Warnung (${wr.name})*: Modul ${idx + 1} liefert seit 15 Minuten nur ${mp} W (Durchschnitt: ${avgModule.toFixed(1)} W)`
                                            });
                                            status.warned = true;
                                        }
                                    } else {
                                        if (status.warned) {
                                            sendTo(telegramInstance, 'send', {
                                                text: `✅ *Entwarnung (${wr.name})*: Modul ${idx + 1} liefert wieder ausreichend Leistung.`
                                            });
                                        }
                                        status.warnSince = null;
                                        status.warned = false;
                                    }
                                    globalThis.wrStatus[key] = status;
                                });
                            });
                    
                            // 4. Überwachung nicht-produzierender WRs (wie gehabt, ggf. auch mit 15min-Verzögerung anpassen)
                            group.wrs.forEach((wr, i) => {
                                const producingState = getState(`opendtu.0.${wr.id}.producing`).val;
                                const isProducing = producingState === true || producingState === 'true';
                                let status = globalThis.wrStatus[wr.name + "_prod"] || { warnSince: null, warned: false };
                                if (!isProducing) {
                                    let anyOtherProducing = group.wrs.some((otherWr, otherIdx) => {
                                        if (otherIdx !== i) {
                                            const otherProducingState = getState(`opendtu.0.${otherWr.id}.producing`).val;
                                            return otherProducingState === true || otherProducingState === 'true';
                                        }
                                        return false;
                                    });
                                    if (anyOtherProducing) {
                                        if (!status.warnSince) status.warnSince = now;
                                        if (!status.warned && (now - status.warnSince) >= warnDelay) {
                                            sendTo(telegramInstance, 'send', {
                                                text: `🔴 *Ausfall (${group.name})*: ${wr.name} produziert seit 15 Minuten nichts, obwohl andere laufen!`
                                            });
                                            status.warned = true;
                                        }
                                    } else {
                                        status.warnSince = null;
                                        status.warned = false;
                                    }
                                } else {
                                    if (status.warned) {
                                        sendTo(telegramInstance, 'send', {
                                            text: `✅ *Entwarnung (${group.name})*: ${wr.name} produziert wieder!`
                                        });
                                    }
                                    status.warnSince = null;
                                    status.warned = false;
                                }
                                globalThis.wrStatus[wr.name + "_prod"] = status;
                            });
                        });
                    }
                    
                    schedule('*/2 * * * *', checkWRs);
                    
                    

                    Das ist die zweite Version, die erste hat zu viele Meldungen in den Morgen- und Abendstunden gebracht wenn einzelne Module kurz verschattet sind.

                    Das Skript vergleicht die Module eines WRs miteinander und warnt wenn ein Module nach 15 min immer noch hinter den anderen herhinkt. Außerdem vergleicht es die WRs innerhalb von zwei Gruppen (wo die Module jeweils gleich ausgerichtet sind) miteinander.

                    B Offline
                    B Offline
                    Beowolf
                    schrieb am zuletzt editiert von
                    #10

                    @martinschm
                    Noch eine Frage.

                    Warum baust du die Konstante "minProduction = 5" ein, die dann später nicht verwendet wird?

                    Ist da noch etwas geplant?

                    Die Natur braucht nicht unseren Schutz, sie braucht unsere Abwesenheit.

                    M 1 Antwort Letzte Antwort
                    0
                    • B Beowolf

                      @martinschm
                      Noch eine Frage.

                      Warum baust du die Konstante "minProduction = 5" ein, die dann später nicht verwendet wird?

                      Ist da noch etwas geplant?

                      M Offline
                      M Offline
                      martinschm
                      schrieb am zuletzt editiert von
                      #11

                      @beowolf said in PV Überwachung hoymiles:

                      @martinschm
                      Noch eine Frage.

                      Warum baust du die Konstante "minProduction = 5" ein, die dann später nicht verwendet wird?

                      Ist da noch etwas geplant?

                      Hi, nein das ist ein Überbleibsel aus der ersten Version.

                      1 Antwort Letzte Antwort
                      0
                      • B Beowolf

                        @martinschm sagte in PV Überwachung hoymiles:

                        nutze aktuell dieses Skript

                        wr.jpg

                        Wo kommen diese 78,2 W her? Wo wird das berechnet?

                        M Offline
                        M Offline
                        martinschm
                        schrieb am zuletzt editiert von
                        #12

                        @beowolf said in PV Überwachung hoymiles:

                        @martinschm sagte in PV Überwachung hoymiles:

                        nutze aktuell dieses Skript

                        wr.jpg

                        Wo kommen diese 78,2 W her? Wo wird das berechnet?

                        Hi, ja wird berechnet aus den Werten der anderen Module.

                        1 Antwort Letzte Antwort
                        0
                        • B Offline
                          B Offline
                          Beowolf
                          schrieb am zuletzt editiert von Beowolf
                          #13

                          Ich habedas Skript mal etwas "erweitert".

                          Das legt jetzt Datenpunkte unter "userdata" an. Die Daten können dann weiter in einer VIS verwendet werden.

                          const wrThreshold = 0.7;
                          const moduleThreshold = 0.7;
                          const minProduction = 5;
                          const pushoverInstance = 'pushover.0';
                          const warnDelay = 15 * 60 * 1000;
                          
                          const groups = [
                            {
                              name: "Solaranlage",
                              wrs: [
                                { id: "114***********", name: "WR1_HM-1000", moduleCount: 2 },
                                { id: "114***********", name: "WR2_HM-1000", moduleCount: 2 },
                                { id: "114***********", name: "WR3_HM-1000", moduleCount: 2 }
                              ]
                            }
                          ];
                          
                          if (!globalThis.wrStatus) globalThis.wrStatus = {};
                          
                          function sendPushoverMessage(message) {
                            sendTo(pushoverInstance, 'send', {
                              message,
                              title: 'Wechselrichter-Überwachung',
                              priority: 0
                            });
                          }
                          
                          function checkWRs() {
                            let now = Date.now();
                          
                            groups.forEach(group => {
                              let wrPowers = [];
                              let activeWRs = [];
                          
                              group.wrs.forEach((wr, i) => {
                                const producingState = getState(`opendtu.0.${wr.id}.producing`).val;
                                const isProducing = producingState === true || producingState === 'true';
                                const wrPower = isProducing ? getState(`opendtu.0.${wr.id}.power_dc`).val : 0;
                                wrPowers[i] = wrPower;
                          
                                if (isProducing) {
                                  activeWRs.push({ index: i, ...wr, wrPower });
                                }
                          
                                // Schreibe Status in 0_userdata
                                const statusText = isProducing
                                  ? (wrPower >= minProduction ? "✅ OK" : "⚠️ Schwache Produktion")
                                  : "❌ Keine Produktion";
                                setState(`0_userdata.0.WR_Status.${wr.name}.Status`, { val: statusText, ack: true });
                              });
                          
                              if (activeWRs.length > 1) {
                                let avgWR = activeWRs.reduce((sum, wr) => sum + wr.wrPower, 0) / activeWRs.length;
                          
                                activeWRs.forEach(wr => {
                                  let status = globalThis.wrStatus[wr.name] || { warnSince: null, warned: false };
                          
                                  if (wr.wrPower < avgWR * wrThreshold) {
                                    if (!status.warnSince) status.warnSince = now;
                                    if (!status.warned && (now - status.warnSince) >= warnDelay) {
                                      sendPushoverMessage(`⚠️ WR-Warnung (${group.name}): ${wr.name} liefert seit 15 Minuten nur ${wr.wrPower} W (Durchschnitt: ${avgWR.toFixed(1)} W)`);
                                      status.warned = true;
                                    }
                                  } else {
                                    if (status.warned) {
                                      sendPushoverMessage(`✅ Entwarnung (${group.name}): ${wr.name} liefert wieder ausreichend Leistung.`);
                                    }
                                    status.warnSince = null;
                                    status.warned = false;
                                  }
                          
                                  globalThis.wrStatus[wr.name] = status;
                                });
                              }
                          
                              activeWRs.forEach(wr => {
                                let modulePowers = [];
                                for (let m = 1; m <= wr.moduleCount; m++) {
                                  let modPower = getState(`opendtu.0.${wr.id}.dc.input_${m}.power`).val;
                                  modulePowers[m - 1] = modPower;
                                }
                          
                                let avgModule = modulePowers.reduce((a, b) => a + b, 0) / wr.moduleCount;
                          
                                modulePowers.forEach((mp, idx) => {
                                  const modKey = `${wr.name}_modul${idx + 1}`;
                                  let status = globalThis.wrStatus[modKey] || { warnSince: null, warned: false };
                          
                                  // Modulstatus schreiben
                                  const modStatus = mp > 0 ? "✅ OK" : "❌ Kein Ertrag";
                                  setState(`0_userdata.0.WR_Status.${wr.name}.Modul${idx + 1}`, { val: modStatus, ack: true });
                          
                                  if (mp < avgModule * moduleThreshold) {
                                    if (!status.warnSince) status.warnSince = now;
                                    if (!status.warned && (now - status.warnSince) >= warnDelay) {
                                      sendPushoverMessage(`⚠️ Modul-Warnung (${wr.name}): Modul ${idx + 1} liefert seit 15 Minuten nur ${mp} W (Durchschnitt: ${avgModule.toFixed(1)} W)`);
                                      status.warned = true;
                                    }
                                  } else {
                                    if (status.warned) {
                                      sendPushoverMessage(`✅ Entwarnung (${wr.name}): Modul ${idx + 1} liefert wieder ausreichend Leistung.`);
                                    }
                                    status.warnSince = null;
                                    status.warned = false;
                                  }
                          
                                  globalThis.wrStatus[modKey] = status;
                                });
                              });
                          
                              group.wrs.forEach((wr, i) => {
                                const producingState = getState(`opendtu.0.${wr.id}.producing`).val;
                                const isProducing = producingState === true || producingState === 'true';
                          
                                let status = globalThis.wrStatus[wr.name + "_prod"] || { warnSince: null, warned: false };
                          
                                if (!isProducing) {
                                  let anyOtherProducing = group.wrs.some((otherWr, idx) => {
                                    if (idx !== i) {
                                      const otherState = getState(`opendtu.0.${otherWr.id}.producing`).val;
                                      return otherState === true || otherState === 'true';
                                    }
                                    return false;
                                  });
                          
                                  if (anyOtherProducing) {
                                    if (!status.warnSince) status.warnSince = now;
                                    if (!status.warned && (now - status.warnSince) >= warnDelay) {
                                      sendPushoverMessage(`🔴 Ausfall (${group.name}): ${wr.name} produziert seit 15 Minuten nichts, obwohl andere laufen!`);
                                      status.warned = true;
                                    }
                                  } else {
                                    status.warnSince = null;
                                    status.warned = false;
                                  }
                                } else {
                                  if (status.warned) {
                                    sendPushoverMessage(`✅ Entwarnung (${group.name}): ${wr.name} produziert wieder!`);
                                  }
                                  status.warnSince = null;
                                  status.warned = false;
                                }
                          
                                globalThis.wrStatus[wr.name + "_prod"] = status;
                              });
                            });
                          }
                          
                          schedule('*/2 * * * *', checkWRs);
                          

                          Die Natur braucht nicht unseren Schutz, sie braucht unsere Abwesenheit.

                          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
                          FAQ Cloud / IOT
                          HowTo: Node.js-Update
                          HowTo: Backup/Restore
                          Downloads
                          BLOG

                          347

                          Online

                          32.5k

                          Benutzer

                          81.7k

                          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