Weiter zum Inhalt
  • Home
  • Aktuell
  • Tags
  • 0 Ungelesen 0
  • Kategorien
  • Unreplied
  • Beliebt
  • GitHub
  • Docu
  • Hilfe
Skins
  • Hell
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dunkel
  • 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

  • Monatsrückblick Januar/Februar 2026 ist online!
    BluefoxB
    Bluefox
    18
    1
    663

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

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

Hoymiles WR mit 1600W regeln

Geplant Angeheftet Gesperrt Verschoben JavaScript
3 Beiträge 3 Kommentatoren 299 Aufrufe 4 Beobachtet
  • Ä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

        Hey! Du scheinst an dieser Unterhaltung interessiert zu sein, hast aber noch kein Konto.

        Hast du es satt, bei jedem Besuch durch die gleichen Beiträge zu scrollen? Wenn du dich für ein Konto anmeldest, kommst du immer genau dorthin zurück, wo du zuvor warst, und kannst dich über neue Antworten benachrichtigen lassen (entweder per E-Mail oder Push-Benachrichtigung). Du kannst auch Lesezeichen speichern und Beiträge positiv bewerten, um anderen Community-Mitgliedern deine Wertschätzung zu zeigen.

        Mit deinem Input könnte dieser Beitrag noch besser werden 💗

        Registrieren Anmelden
        Antworten
        • In einem neuen Thema antworten
        Anmelden zum Antworten
        • Älteste zuerst
        • Neuste zuerst
        • Meiste Stimmen


        Support us

        ioBroker
        Community Adapters
        Donate

        232

        Online

        32.7k

        Benutzer

        82.6k

        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