Skip to content
  • Home
  • Recent
  • Tags
  • 0 Unread 0
  • Categories
  • Unreplied
  • Popular
  • 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

  • Default (No Skin)
  • No Skin
Collapse
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
    694

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

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

Hoymiles WR mit 1600W regeln

Scheduled Pinned Locked Moved JavaScript
3 Posts 3 Posters 299 Views 4 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • N Offline
    N Offline
    NobbyNobs
    wrote on last edited by
    #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 Reply Last reply
    0
    • B Offline
      B Offline
      Beowolf
      wrote on last edited by 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 Reply Last reply
      0
      • agreenA Offline
        agreenA Offline
        agreen
        wrote on last edited by 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 Reply Last reply
        0

        Hello! It looks like you're interested in this conversation, but you don't have an account yet.

        Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.

        With your input, this post could be even better 💗

        Register Login
        Reply
        • Reply as topic
        Log in to reply
        • Oldest to Newest
        • Newest to Oldest
        • Most Votes


        Support us

        ioBroker
        Community Adapters
        Donate

        326

        Online

        32.7k

        Users

        82.6k

        Topics

        1.3m

        Posts
        Community
        Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen | Einwilligungseinstellungen
        ioBroker Community 2014-2025
        logo
        • Login

        • Don't have an account? Register

        • Login or register to search.
        • First post
          Last post
        0
        • Home
        • Recent
        • Tags
        • Unread 0
        • Categories
        • Unreplied
        • Popular
        • GitHub
        • Docu
        • Hilfe