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

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

Community Forum

donate donate
  1. ioBroker Community Home
  2. Deutsch
  3. Skripten / Logik
  4. JavaScript
  5. Hoymiles WR mit 1600W regeln

NEWS

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

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

  • Weihnachtsangebot 2025! 🎄
    BluefoxB
    Bluefox
    25
    1
    2.1k

Hoymiles WR mit 1600W regeln

Geplant Angeheftet Gesperrt Verschoben JavaScript
3 Beiträge 3 Kommentatoren 274 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.
  • N Offline
    N Offline
    NobbyNobs
    schrieb am zuletzt editiert von
    #1

    Guten Abend miteinander,

    ich habe folgendes Setup:

    mME --> Einspeisung WR auf L1 --> ShellyEM 3 --> Verbraucher

    Dieser Aufbau ist den Gegebenheiten geschuldet.

    Ich schreibe meine Daten mittels des Shelly-Adapter in iobroker und mqtt mit. Die Daten des WR liefert mir eine OpenDTU - diese soll auch die neue Leistungsgrenze schreiben.

    Ich habe folgenden JavaScript-Code erarbeitet:

    // Datenpunkte
    const wrPowerDP = 'opendtu.0.1164a00f8949.ac.phase_1.power';  // Wechselrichter-Leistung
    const housePowerDP = 'shelly.0.SHEM-3#485519C98888#1.Total.InstantPower';  // Hausverbrauch
    const mqttLimitDP = 'opendtu.0.1164a00f8949.power_control.limit_nonpersistent_absolute';  // MQTT Limit-Datenpunkt
    const producingDP = 'opendtu.0.1164a00f8949.producing';  // Producing Status
    
    // Konfiguration
    const thresholdWR = 800; // Mindestleistung des Wechselrichters in Watt
    const thresholdDifferenceMin = 400; // Mindestdifferenz für das Setzen eines Limits
    const thresholdDifferenceMax = 50;  // Maximale Differenz, um das Limit zu erhöhen
    const maxWRPower = 1600; // Maximale zulässige Leistung des WR
    const changeThreshold = 10; // Schwellenwert für signifikante Limitänderung (in Watt)
    
    // Initialisiere Zähler-Datenpunkte für Prüfungen und Limitänderungen
    if (!existsState('0_userdata.0.solar.check_counter')) {
        createState('0_userdata.0.solar.check_counter', 0, {
            name: 'Anzahl der Prüfungen',
            type: 'number',
            unit: 'Prüfungen',
            read: true,
            write: true
        });
    }
    
    if (!existsState('0_userdata.0.solar.change_counter')) {
        createState('0_userdata.0.solar.change_counter', 0, {
            name: 'Anzahl der Prüfungen mit Limitänderung',
            type: 'number',
            unit: 'Prüfungen',
            read: true,
            write: true
        });
    }
    
    if (!existsState('0_userdata.0.solar.no_change_counter')) {
        createState('0_userdata.0.solar.no_change_counter', 0, {
            name: 'Anzahl der Prüfungen ohne Limitänderung',
            type: 'number',
            unit: 'Prüfungen',
            read: true,
            write: true
        });
    }
    
    // Differenz-Datenpunkt für Grafana
    if (!existsState('0_userdata.0.solar.wr_haus_difference')) {
        createState('0_userdata.0.solar.wr_haus_difference', 0, {
            name: 'WR - Haus Leistung Differenz',
            type: 'number',
            unit: 'Watt',
            read: true,
            write: true
        });
    }
    
    // Zustand für Low Power Mode
    if (!existsState('0_userdata.0.solar.low_power_mode')) {
        createState('0_userdata.0.solar.low_power_mode', false, {
            name: 'Low Power Mode aktiv',
            type: 'boolean',
            read: true,
            write: true
        });
    }
    
    // Funktion zur Berechnung des Limits
    function calculateLimit(wrPower, housePower) {
        let limit = wrPower - thresholdDifferenceMin;
    
        if (wrPower - housePower < thresholdDifferenceMax || wrPower - housePower > thresholdDifferenceMin) {
            limit = housePower + thresholdDifferenceMin;
        }
    
        if (limit < 0) {
            limit = 0;
        } else if (limit > maxWRPower) {
            limit = maxWRPower;
        }
    
        return limit;
    }
    
    // Hauptfunktion zur Leistungsprüfung und Limitsteuerung
    function checkPower() {
        const wrPower = getState(wrPowerDP).val;
        const housePower = getState(housePowerDP).val;
        const powerDifference = parseFloat((wrPower - housePower).toFixed(2));
        const isLowPower = getState('0_userdata.0.solar.low_power_mode').val;
        const currentLimit = getState(mqttLimitDP).val;
    
        // Prüfungszähler erhöhen
        let checkCount = getState('0_userdata.0.solar.check_counter').val + 1;
        setState('0_userdata.0.solar.check_counter', checkCount);
    
        // WR-Leistung unter Schwellwert → Low Power Mode
        if (wrPower < thresholdWR) {
            if (!isLowPower) {
                console.log('WR-Leistung unter ' + thresholdWR + ' W – Low Power Mode aktiviert');
                console.log('Limit wird geändert von ' + currentLimit + ' W auf ' + maxWRPower + ' W');
                setState(mqttLimitDP, maxWRPower);
                setState('0_userdata.0.solar.low_power_mode', true);
    
                let changeCount = getState('0_userdata.0.solar.change_counter').val + 1;
                setState('0_userdata.0.solar.change_counter', changeCount);
            } else {
                console.log('Low Power Mode aktiv – WR-Leistung weiter unter ' + thresholdWR + ' W');
                console.log('Limit bleibt unverändert bei ' + currentLimit + ' W');
                let noChangeCount = getState('0_userdata.0.solar.no_change_counter').val + 1;
                setState('0_userdata.0.solar.no_change_counter', noChangeCount);
            }
        } else {
            if (isLowPower) {
                console.log('WR-Leistung über ' + thresholdWR + ' W – Low Power Mode deaktiviert');
                setState('0_userdata.0.solar.low_power_mode', false);
            }
    
            if (powerDifference >= 0) {
                const newLimit = calculateLimit(wrPower, housePower);
    
                if (Math.abs(currentLimit - newLimit) >= changeThreshold) {
                    console.log('Limit wird geändert von ' + currentLimit + ' W auf ' + newLimit + ' W');
                    setState(mqttLimitDP, newLimit);
    
                    let changeCount = getState('0_userdata.0.solar.change_counter').val + 1;
                    setState('0_userdata.0.solar.change_counter', changeCount);
                } else {
                    console.log('Limit bleibt unverändert bei ' + currentLimit + ' W – Änderung (' + Math.abs(currentLimit - newLimit) + ' W) unterhalb Schwelle (' + changeThreshold + ' W)');
                    let noChangeCount = getState('0_userdata.0.solar.no_change_counter').val + 1;
                    setState('0_userdata.0.solar.no_change_counter', noChangeCount);
                }
            } else {
                console.log('Keine Regelung – WR-Haus Differenz negativ (' + powerDifference + ' W)');
            }
        }
    
        setState('0_userdata.0.solar.wr_haus_difference', powerDifference);
    }
    
    // Sofort prüfen bei Produktionsstart
    on({ id: producingDP, val: true }, function () {
        console.log('Produktion gestartet – Starte erste Prüfung der Leistung');
        checkPower();
    });
    
    // Zyklische Prüfung alle 15 Sekunden bei aktiver Produktion
    setInterval(function () {
        if (getState(producingDP).val === true) {
            checkPower();
        }
    }, 60000);
    
    

    Ich möchte die Anzahl der Schreibvorgänge auf den WR so gering wie möglich halten, daher die eingebauten Einschränkungen.

    Allerdings klappt das schreiben des neuen Limit auf den WR nicht - habe ich irgendwo einen Denkfehler?

    Gruß, NobbyNobs

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

      Die Logik in "calculateLimit()" ist für mich unklar.

      if (wrPower - housePower < thresholdDifferenceMax || wrPower - housePower > thresholdDifferenceMin)
      

      Diese Bedingung ist irgendwie logisch nicht richtig, glaube ich. Sie trifft immer zu, wenn powerDifference außerhalb des Bereichs thresholdDifferenceMax bis thresholdDifferenceMin liegt.

      Versuche das mal.

      // ===========================
      // Konfiguration
      // ===========================
      const wrPowerDP = 'opendtu.0.1164a00f8949.ac.phase_1.power';
      const housePowerDP = 'shelly.0.SHEM-3#485519C98888#1.Total.InstantPower';
      const mqttLimitDP = 'opendtu.0.1164a00f8949.power_control.limit_nonpersistent_absolute';
      const producingDP = 'opendtu.0.1164a00f8949.producing';
      
      const thresholdWR = 800;
      const thresholdDifferenceMin = 400;
      const thresholdDifferenceMax = 50;
      const maxWRPower = 1600;
      const changeThreshold = 10;
      
      const debug = true; // Setze auf false, um Logs zu deaktivieren
      
      // ===========================
      // Datenpunkt-Initialisierung
      // ===========================
      const statesToInit = [
          { id: '0_userdata.0.solar.check_counter', default: 0, name: 'Anzahl der Prüfungen', type: 'number', unit: 'Prüfungen' },
          { id: '0_userdata.0.solar.change_counter', default: 0, name: 'Anzahl der Prüfungen mit Limitänderung', type: 'number', unit: 'Prüfungen' },
          { id: '0_userdata.0.solar.no_change_counter', default: 0, name: 'Anzahl der Prüfungen ohne Limitänderung', type: 'number', unit: 'Prüfungen' },
          { id: '0_userdata.0.solar.wr_haus_difference', default: 0, name: 'WR - Haus Leistung Differenz', type: 'number', unit: 'Watt' },
          { id: '0_userdata.0.solar.low_power_mode', default: false, name: 'Low Power Mode aktiv', type: 'boolean' }
      ];
      
      statesToInit.forEach(dp => {
          if (!existsState(dp.id)) {
              createState(dp.id, dp.default, {
                  name: dp.name,
                  type: dp.type,
                  unit: dp.unit,
                  read: true,
                  write: true
              });
          }
      });
      
      // ===========================
      // Limitberechnung
      // ===========================
      function calculateLimit(wrPower, housePower) {
          let powerDiff = wrPower - housePower;
          let limit;
      
          if (powerDiff >= thresholdDifferenceMax && powerDiff <= thresholdDifferenceMin) {
              limit = housePower + thresholdDifferenceMin;
          } else {
              limit = wrPower - thresholdDifferenceMin;
          }
      
          if (limit < 0) limit = 0;
          else if (limit > maxWRPower) limit = maxWRPower;
      
          return limit;
      }
      
      // ===========================
      // Hauptfunktion
      // ===========================
      function checkPower() {
          const wrPower = getState(wrPowerDP)?.val ?? 0;
          const housePower = getState(housePowerDP)?.val ?? 0;
          const powerDifference = parseFloat((wrPower - housePower).toFixed(2));
          const isLowPower = getState('0_userdata.0.solar.low_power_mode')?.val ?? false;
          const currentLimit = getState(mqttLimitDP)?.val ?? 0;
      
          // Prüfungszähler erhöhen
          let checkCount = getState('0_userdata.0.solar.check_counter')?.val ?? 0;
          setState('0_userdata.0.solar.check_counter', ++checkCount);
      
          if (wrPower < thresholdWR) {
              if (!isLowPower) {
                  if (debug) {
                      console.log(`WR-Leistung unter ${thresholdWR} W – Low Power Mode aktiviert`);
                      console.log(`Limit wird geändert von ${currentLimit} W auf ${maxWRPower} W`);
                  }
                  setState(mqttLimitDP, maxWRPower);
                  setState('0_userdata.0.solar.low_power_mode', true);
      
                  let changeCount = getState('0_userdata.0.solar.change_counter')?.val ?? 0;
                  setState('0_userdata.0.solar.change_counter', ++changeCount);
              } else {
                  if (debug) {
                      console.log(`Low Power Mode aktiv – WR-Leistung weiter unter ${thresholdWR} W`);
                      console.log(`Limit bleibt unverändert bei ${currentLimit} W`);
                  }
      
                  let noChangeCount = getState('0_userdata.0.solar.no_change_counter')?.val ?? 0;
                  setState('0_userdata.0.solar.no_change_counter', ++noChangeCount);
              }
          } else {
              if (isLowPower) {
                  if (debug) console.log(`WR-Leistung über ${thresholdWR} W – Low Power Mode deaktiviert`);
                  setState('0_userdata.0.solar.low_power_mode', false);
              }
      
              if (powerDifference >= 0) {
                  const newLimit = calculateLimit(wrPower, housePower);
                  const diff = Math.abs(currentLimit - newLimit);
      
                  if (diff >= changeThreshold) {
                      if (debug) console.log(`Limit wird geändert von ${currentLimit} W auf ${newLimit} W`);
                      setState(mqttLimitDP, newLimit);
      
                      let changeCount = getState('0_userdata.0.solar.change_counter')?.val ?? 0;
                      setState('0_userdata.0.solar.change_counter', ++changeCount);
                  } else {
                      if (debug) console.log(`Limit bleibt unverändert bei ${currentLimit} W – Änderung (${diff} W) unterhalb Schwelle (${changeThreshold} W)`);
                      let noChangeCount = getState('0_userdata.0.solar.no_change_counter')?.val ?? 0;
                      setState('0_userdata.0.solar.no_change_counter', ++noChangeCount);
                  }
              } else {
                  if (debug) console.log(`Keine Regelung – WR-Haus Differenz negativ (${powerDifference} W)`);
              }
          }
      
          setState('0_userdata.0.solar.wr_haus_difference', powerDifference);
      }
      
      // ===========================
      // Event- und Zeitsteuerung
      // ===========================
      on({ id: producingDP, val: true }, function () {
          if (debug) console.log('Produktion gestartet – Starte erste Prüfung der Leistung');
          checkPower();
      });
      
      // Zyklische Prüfung alle 60 Sekunden
      setInterval(() => {
          if (getState(producingDP)?.val === true) {
              checkPower();
          }
      }, 60000);
      

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

      1 Antwort Letzte Antwort
      0
      • agreenA Offline
        agreenA Offline
        agreen
        schrieb am zuletzt editiert von agreen
        #3

        Da du sowieso OPENDTU verwendest, verwende OpenDTU on Battery.
        Damit kannst du den Wechselrichter nach aktuellem Strombedarf steuern.

        https://github.com/hoylabs/OpenDTU-OnBattery

        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

        727

        Online

        32.6k

        Benutzer

        82.1k

        Themen

        1.3m

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

        • Du hast noch kein Konto? Registrieren

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