Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Einsteigerfragen
    4. Einbindung von Geräten
    5. Erfahrung: Hoymiles MS-A2 Akku via MQTT iobroker steuern

    NEWS

    • Neuer Blog: Fotos und Eindrücke aus Solingen

    • ioBroker@Smart Living Forum Solingen, 14.06. - Agenda added

    • ioBroker goes Matter ... Matter Adapter in Stable

    Erfahrung: Hoymiles MS-A2 Akku via MQTT iobroker steuern

    This topic has been deleted. Only users with topic management privileges can see it.
    • BertDerKleine
      BertDerKleine last edited by BertDerKleine

      Ich schildere hier mal, wie ich den Hoymiles MS-A2 standalone (kein WR, keine Balkonstrom-Panels, kein Shelly, kein Uni-Meter) per MQTT zum laufen bringe - als Nachrüstlösung für eine PV-Anlage.

      Vielleicht kann das ja jemand gebrauchen als Idee. Kann man bestimmt alles noch besser machen, aber als Basis kann ich sagen, dass es funktioniert. 😃

      Eventuell

      Hintergrund:
      Speziell für das Szenario, dass der MS-A2 standalone "als große Powerbank" betrieben werden soll, also ohne eingestöpselte Balkonstrom-Panels, braucht es eine Lade/Entladesteuerung, die auf Überschuß und Mangel reagiert.
      Seit Anfang Juni 2025 beherrscht der MS-A2 nativ MQTT, was nun eine noch einfachere Lösung ermöglicht, nämlich die direkte Steuerung über iobroker.

      Die offizielle Doku zum MQTT Feature findet man hier :

      • https://www.photovoltaikforum.com/core/file-download/507290/
      • https://www.photovoltaikforum.com/core/file-download/507291/
      • Der User "Rong" in dem Thread ist übrigens anscheinend ein Mitarbeiter des Herstelllers Hoymiles.

      Was braucht man also an Zutaten?

      • eine laufende iobroker Installation und einen eingestöpselten und mit dem WLAN verbundenen MS-A2, dessen Firmware über die Handy-App aktualisiert wurde.
      • einen MQTT Broker Adapter im iobroker
      • in der S-Miles App unter Zahnrad / MQTT-Service die Daten konfigurieren (Server IP Adresse des iobrokers, den Port (meist 1883) und Benutzernamen / Passwort.

      Dann tauscht der Akku mit iobroker Daten aus und im iobroker Objekt-Baum findet man unter mqtt / 0 / homeassistant nun die Datenpunkte.

      Standardmäßig lassen sich die Datenpunkte nur auslesen, aber nichts steuern. Um den Akku steuern zu können, muss man in mqtt.0.homeassistant.select.MSA-123456789.ems_mode.command manuell den Befehl mqtt_ctrl einmalig absetzen (der bleibt dann da).

      Die Steuerbefehle (Angaben in Watt) zum Laden/Entladen setzt man später in mqtt.0.homeassistant.number.MSA-123456789.power_ctrl.set ab. Dort stehen positive Werte für Entladen und negative für Laden des Akkus.

      Genutzte Aliase:

      Mein Steuerungsskript basiert auf ein paar Alias-Datenpunkten:

      • alias.0.Akku_befohlene_Entladeleistung --> mqtt.0.homeassistant.number.MSA-123456789.power_ctrl.set
      • alias.0.Akku_Ladezustand --> mqtt.0.homeassistant.sensor.MSA-123456789.quick.state mit Alias-Konverter beim Lesen JSON.parse(val).soc
      • alias.0.Akku_grid_on_power --> mqtt.0.homeassistant.sensor.MSA-123456789.quick.state mit Alias-Konverter beim Lesen JSON.parse(val).grid_on_p

      Mehr braucht es nicht. Man kann deutlich mehr Infos auslesen, aber zur Steuerung reicht das.

      Benötigte Datenquelle:

      Natürlich braucht es zusätzlich einen Datenpunkt im iobroker, der den aktuell vorliegenden Stromüberschuss im Haus liefert.

      In meinem Skript wird aktuell alias.0.Stromüberschuss_IR-Lesekopf verwendet, was den Überschuss direkt vom offiziellen Stromzähler ausliest (mittels eines Tasmota-basierten Infrarot Lesekopfs, den man sich leicht für kleines Geld beschaffen kann und der ebenfalls seine daten via  MQTT zu iobroker sendet). Diese Daten können aber auch von einem PV-Wechselrichter oder Stromzähler kommen, Hauptsache es ist der Stromüberschuss (positive Watt-Werte für einen Überschuss, d.h. Strom der sonst ins öffentliche Netz eingespeist wird und negative Werte für Netzbezug).

      Begrenzungen der Leistung und Entladung via App:

      Egal, was Ihr per MQTT an Befehlen sendet, die Lade- und Entladeleistung des Akkus hält sich an die Vorgaben, die Ihr via der S-Miles App eingegeben habt unter

      • Zahnrad / Einstellung der Ausgangsleistung (meist 800 W)
      • Zahnrad / Netzgebundene Eingangseinstellung (meist 800 W)
      • Zahnrad / Betriebsmodus / Eigenverbrauch / Entladeschlussstufe (meist 10%)

      Das ist im Skript alles auch mit abgefangen, aber m.W. passt der Akku da auch drauf auf.

      Besonderheit: Vergesslichkeit nach 59 Sekunden & Ignoranz bei immer gleichen Zahlen

      Es gibt eine Besonderheit, die zu beachten ist, nämlich vergisst der Akku nach 59 Sekunden den per MQTT vorgegebenen Befehl zum Laden/Entladen wieder. Und außerdem ignoriert er auch simple Wiederholungen einer Vorgabe der exakt selben Wattzahl.

      Sobald er diese Eure Vorgabe vergessen hat, führt der Akku das aus, was unter Zahnrad / Hauslasteinstellungen / Lastleistungskurve / Kurve 1 / (alle Tage und Uhrzeiten) in der App hinterlegt ist. Falls da also z.B. 100 W steht, wird der Akku dann mit 100 W entladen. Man kann in der App hier auch einfach "0 W" hinterlegen, so dass der Akku dann nix macht.

      Aus diesem Grund sendet mein Skript alle 30 Sekunden eine neue Wattvorgabe und zusätzlich alterniert diese immer um 0,1 Watt. So wird die Steuerung aufrechterhalten.

      Skript:

      Und hier findet Ihr mein Javascript als Denkanstoß.
      Ein großer Teil des Skripts ist Doku, Logging und Fehlerfindung gewidmet, man kann es also auch kürzen.

      /**
       * AKKU-MANAGEMENT-SKRIPT FÜR IO BROKER
       * 
       * Dieses Skript steuert einen Batteriespeicher basierend auf dem aktuellen Stromüberschuss.
       * Es lädt den Akku bei PV-Überschuss und entlädt ihn bei Strombedarf.
       * Entwurf von BertDerKleine
       * 
       * Merkmale:
       * - Kontinuierliche Regelung unabhängig von Tageszeit
       * - Getrennte Zielfaktoren für Lade- und Entladevorgänge
       * - PI-Regler für stabile Regelung
       * - SOC-Schutz gegen Überladung und Tiefentladung
       * - Alternierende Steuerbefehle für zuverlässige Akku-Kommunikation
       * - Ausführliche Diagnosefunktionen
       * - Konfigurierbares Logging
       */
      
      // ========== KONFIGURATION ==========
      const AUSFUEHRLICHES_LOGGING = false;  // Auf TRUE setzen für detaillierte Regel-Logs (nur für Debugging)
      const MAX_LOG_LAENGE = 100;             // Maximale Anzahl gespeicherter Log-Einträge für Diagnose
      
      // ========== GLOBALE VARIABLEN ==========
      /**
       * Intervall für das Senden von Steuerbefehlen (in Millisekunden)
       * Der Akku benötigt regelmäßige Aktualisierungen, da er Befehle nach 60-90 Sekunden "vergisst"
       * 30000 = 30 Sekunden ist ein bewährter Wert für zuverlässige Kommunikation
       */
      const alternierIntervall = 30000;
      
      /**
       * Datenpunkt für Akku-Steuerbefehle
       * - Positive Werte: Entladen (Leistungsabgabe)
       * - Negative Werte: Laden (Leistungsaufnahme)
       */
      const AKTIONS_DATENPUNKT = 'alias.0.Akku_befohlene_Entladeleistung';
      
      /** Datenpunkt für die aktuell gemessene Akku-Leistung */
      const AKTUELLE_AKKULEISTUNG = 'alias.0.Akku_grid_on_power';
      
      // Betriebsstatus
      let regelungAktiv = false;  // Gibt an, ob die Regelung aktuell läuft
      
      // Intervalle
      let messIntervall = null;    // Intervall für Leistungsmessungen
      let regelIntervall = null;   // Intervall für Regelberechnungen
      let sendeIntervall = null;   // Intervall für Steuerbefehle
      
      // Regelvariablen
      let mittelungArray = [];     // Speichert die letzten Messwerte für die Mittelwertbildung
      let aktuellerSollwert = 0;   // Aktuell berechneter Sollwert für Akku-Leistung
      let toggleFlag = true;       // Steuert die Alternierung der Steuerbefehle (+0.1W Wechsel)
      let integral = 0;            // Integralanteil des PI-Reglers
      
      // ========== PARAMETER ==========
      /**
       * Maximale Ladeleistung in Watt
       * Sollte unterhalb der technischen Grenzen des Akkus liegen.
       */
      const maxLadeleistung = 800;
      
      /**
       * Maximale Entladeleistung in Watt
       * Abhängig von Akku-Kapazität und Wechselrichter.
       */
      const maxEntladeleistung = 800;
      
      /**
       * Intervall für Leistungsmessungen in Millisekunden
       * 10000 = 10 Sekunden ist ein guter Kompromiss zwischen Aktualität und Stabilität
       */
      const samplingIntervall = 10000;
      
      /**
       * Faktor für den Integralanteil des PI-Reglers
       * Ein höherer Wert reagiert stärker auf anhaltende Abweichungen
       * 0.2 ist ein moderater Wert für stabile Regelung ohne zu starkes Überschwingen
       */
      const integralFaktor = 0.2;
      
      /** Ladezustand bei dem das Laden gestoppt wird (Vermeidung von Überladung) */
      const SOC_LADESTOPP = 98;
      
      /** Ladezustand bei dem das Entladen gestoppt wird (Vermeidung von Tiefentladung) */
      const SOC_ENTLADESTOPP = 10;
      
      /**
       * Zielfaktoren für Regelung
       * 
       * zielFaktorLaden: Anteil des Überschusses der fürs Laden genutzt wird (0-1)
       *   - 0.8 = 80% des Überschusses werden zum Laden genutzt (konservativ)
       *   - Höhere Werte nutzen mehr Überschuss, können aber zu Netzinstabilität führen
       * 
       * zielFaktorEntladen: Anteil des Bedarfs der durch Entladen gedeckt wird (0-1)
       *   - 1.0 = 100% des Bedarfs werden durch Entladen gedeckt (maximale Autarkie)
       *   - Niedrigere Werte schonen den Akku, erhöhen aber Netzbezug
       */
      const zielFaktorLaden = 0.8;
      const zielFaktorEntladen = 1.0;
      
      // ========== LOGGING SYSTEM ==========
      let logHistorie = [];  // Speichert die letzten Log-Einträge für Diagnosezwecke
      
      /**
       * Verbesserte Log-Funktion mit Historie-Speicherung und Level-Steuerung
       * 
       * @param {string} nachricht - Die zu loggende Nachricht
       * @param {string} level - Log-Level ('debug', 'info', 'warn', 'error')
       */
      function log(nachricht, level = 'info') {
          // Erstelle formatierten Log-Eintrag
          const timestamp = new Date().toISOString();
          const logEintrag = `[${timestamp}] [${level.toUpperCase()}] ${nachricht}`;
          
          // Füge zur Historie hinzu (begrenzt auf MAX_LOG_LAENGE)
          logHistorie.push(logEintrag);
          if (logHistorie.length > MAX_LOG_LAENGE) {
              logHistorie.shift();
          }
          
          // Ausgabe basierend auf Level und Konfiguration
          switch(level) {
              case 'error':
                  console.error(logEintrag);
                  break;
              case 'warn':
                  console.warn(logEintrag);
                  break;
              case 'info':
                  console.log(logEintrag);
                  break;
              case 'debug':
                  // Debug-Logs nur bei aktiviertem ausführlichen Logging
                  if (AUSFUEHRLICHES_LOGGING) {
                      console.log(logEintrag);
                  }
                  break;
              default:
                  console.log(logEintrag);
          }
      }
      
      // ========== HELFERFUNKTIONEN ==========
      /**
       * Setzt den Steuerungsdatenpunkt mit Fehlerbehandlung
       * 
       * @param {number} wert - Der zu setzende Wert
       * @returns {boolean} True bei Erfolg, False bei Fehler
       */
      function sicherSetState(wert) {
          try {
              setState(AKTIONS_DATENPUNKT, wert, false);
              return true;
          } catch (e) {
              log(`Fehler beim Setzen des Datenpunkts: ${e.message}`, 'error');
              return false;
          }
      }
      
      /**
       * Bereinigt den gemessenen Überschuss um den aktuellen Akku-Beitrag
       * 
       * @param {number} ueberschussGemessen - Gemessener Stromüberschuss
       * @param {number} akkuLeistung - Aktuelle Akku-Leistung (positiv = Entladen, negativ = Laden)
       * @returns {number} Bereinigter Überschuss
       */
      function bereinigeLeistung(ueberschussGemessen, akkuLeistung) {
          return ueberschussGemessen - akkuLeistung;
      }
      
      // ========== FLEXIBLE REGELUNG ==========
      /**
       * Startet die kontinuierliche Akku-Regelung
       */
      function starteFlexibleRegelung() {
          if (regelungAktiv) {
              log("Regelung bereits aktiv - Start abgebrochen", 'debug');
              return;
          }
          
          stoppeRegelung();
          log("Starte flexible Regelung...");
          
          regelungAktiv = true;
          mittelungArray = [];
          aktuellerSollwert = 0;
          integral = 0;
          toggleFlag = true;
      
          // Initialer Status-Log mit Konfiguration
          log(`Regelung gestartet mit:
        Max Laden: ${maxLadeleistung}W
        Max Entladen: ${maxEntladeleistung}W
        Laden-Zielfaktor: ${zielFaktorLaden}
        Entladen-Zielfaktor: ${zielFaktorEntladen}
        SOC-Limits: Ladestopp >${SOC_LADESTOPP}%, Entladestopp <${SOC_ENTLADESTOPP}%`, 'info');
      
          // Messintervall - Sammelt regelmäßig Leistungsdaten
          messIntervall = setInterval(() => {
              try {
                  const ueberschussGemessen = getState('alias.0.Stromüberschuss_IR-Lesekopf').val;
                  const akkuLeistung = getState(AKTUELLE_AKKULEISTUNG).val;
                  const bereinigteLeistung = bereinigeLeistung(ueberschussGemessen, akkuLeistung);
                  
                  mittelungArray.push(bereinigteLeistung);
                  if (mittelungArray.length > 6) mittelungArray.shift();
              } catch (e) {
                  log("Messfehler: " + e.message, 'error');
              }
          }, samplingIntervall);
      
          // Regelintervall - Berechnet alle 20 Sekunden neue Sollwerte
          regelIntervall = setInterval(() => {
              try {
                  if (mittelungArray.length < 3) {
                      log("Nicht genug Messwerte für Regelung", 'debug');
                      return;
                  }
                  
                  // Berechne gleitenden Mittelwert der letzten Messungen
                  const summe = mittelungArray.reduce((a, b) => a + b, 0);
                  const mittelwert = summe / mittelungArray.length;
                  
                  // Bestimmung des Betriebsmodus
                  const istLadebetrieb = mittelwert > 0; // Positiver Wert = Überschuss = Laden
                  const zielFaktor = istLadebetrieb ? zielFaktorLaden : zielFaktorEntladen;
                  
                  // Berechnung der benötigten Akku-Leistung
                  const zielLeistung = Math.abs(mittelwert) * zielFaktor;
                  const zielwert = istLadebetrieb ? -zielLeistung : zielLeistung;
                  
                  // PI-Regler berechnet Anpassung
                  const differenz = zielwert - aktuellerSollwert;
                  integral += differenz * integralFaktor;
                  
                  // Integrator-Begrenzung
                  const integratorLimit = istLadebetrieb ? maxLadeleistung : maxEntladeleistung;
                  integral = Math.min(Math.max(integral, -integratorLimit), integratorLimit);
                  
                  // Neuen Sollwert berechnen
                  let neuerSollwert = aktuellerSollwert + differenz + integral;
                  
                  // Physikalische Grenzen einhalten
                  if (istLadebetrieb) {
                      neuerSollwert = Math.min(neuerSollwert, 0); // Max 0 = keine Entladung
                      neuerSollwert = Math.max(neuerSollwert, -maxLadeleistung); // Min = -maxLadeleistung
                  } else {
                      neuerSollwert = Math.max(neuerSollwert, 0); // Min 0 = kein Laden
                      neuerSollwert = Math.min(neuerSollwert, maxEntladeleistung); // Max = maxEntladeleistung
                  }
                  
                  // Sanfte Anpassung (30% pro Schritt)
                  const aenderung = neuerSollwert - aktuellerSollwert;
                  if (Math.abs(aenderung) > 10) {
                      aktuellerSollwert += aenderung * 0.3;
                  } else {
                      aktuellerSollwert = neuerSollwert;
                  }
                  
                  // Ausführliches Logging nur bei Bedarf
                  if (AUSFUEHRLICHES_LOGGING) {
                      log(`Regelberechnung:
        Überschuss (gemittelt): ${mittelwert.toFixed(1)}W
        Ziel-Leistung: ${zielLeistung.toFixed(1)}W
        Zielwert (Akku): ${zielwert.toFixed(1)}W
        Neuer Sollwert: ${neuerSollwert.toFixed(1)}W
        Aktueller Sollwert: ${aktuellerSollwert.toFixed(1)}W
        Differenz: ${differenz.toFixed(1)}W
        Integral: ${integral.toFixed(1)}
        Faktor: ${zielFaktor}
        Modus: ${istLadebetrieb ? 'Laden' : 'Entladen'}`, 'debug');
                  }
              } catch (e) {
                  log("Regelfehler: " + e.message, 'error');
              }
          }, 20000);
      
          // Sendeintervall - Sendet alle 30 Sekunden Steuerbefehle
          sendeIntervall = setInterval(() => {
              if (!regelungAktiv) return;
              
              // SOC-Schutz - Verhindert Überladung und Tiefentladung
              const akkuSOC = getState('alias.0.Akku_Ladezustand').val;
              let effektiverSollwert = aktuellerSollwert;
              
              if (effektiverSollwert < 0 && akkuSOC > SOC_LADESTOPP) {
                  effektiverSollwert = 0;
                  log(`LADESTOPP: Akku > ${SOC_LADESTOPP}% (SOC: ${akkuSOC.toFixed(1)}%)`, 'warn');
              }
              
              if (effektiverSollwert > 0 && akkuSOC < SOC_ENTLADESTOPP) {
                  effektiverSollwert = 0;
                  log(`ENTLADESTOPP: Akku < ${SOC_ENTLADESTOPP}% (SOC: ${akkuSOC.toFixed(1)}%)`, 'warn');
              }
              
              // Alternierende Werte senden (jeder 2. Befehl +0.1W)
              const wert = toggleFlag ? effektiverSollwert : effektiverSollwert + 0.1;
              sicherSetState(wert);
              toggleFlag = !toggleFlag;
              
              // Protokolliere nur die ersten 20 Minuten oder bei Moduswechsel
              log(`Steuerbefehl gesendet: ${wert.toFixed(1)}W (${toggleFlag ? 'nächstes Mal Basiswert' : 'nächstes Mal +0.1W'})`, 'debug');
          }, alternierIntervall);
      
          log("Flexible Regelung erfolgreich gestartet", 'info');
      }
      
      /**
       * Stoppt die laufende Regelung
       */
      function stoppeRegelung() {
          if (!regelungAktiv) return;
          
          clearInterval(messIntervall);
          clearInterval(regelIntervall);
          clearInterval(sendeIntervall);
          regelungAktiv = false;
          
          sicherSetState(0);
          log("Regelung gestoppt", 'info');
      }
      
      // ========== HAUPTPROGRAMM ==========
      /**
       * Initialisiert das Skript
       */
      function initSkript() {
          try {
              starteFlexibleRegelung();
              log("Skript initialisierung abgeschlossen");
              
              // Aktiviere temporäres ausführliches Logging für die ersten 10 Minuten
              setTimeout(() => {
                  if (!AUSFUEHRLICHES_LOGGING) {
                      log("Initiale Debug-Periode beendet - Detaillogs deaktiviert");
                  }
              }, 600000); // 10 Minuten
          } catch (e) {
              log("Initialisierungsfehler: " + e.message, 'error');
          }
      }
      
      // Startverzögerung für Systeminitialisierung
      setTimeout(initSkript, 5000);
      
      // ========== EVENT-HANDLER ==========
      // Überwacht Ladezustandsänderungen
      on({ id: 'alias.0.Akku_Ladezustand', change: 'ne' }, (state) => {
          const soc = state.val;
          
          // Protokolliere nur bei relevanten Änderungen
          if (soc > SOC_LADESTOPP && aktuellerSollwert < 0) {
              log(`AKTION: Ladung pausiert (SOC: ${soc}% > ${SOC_LADESTOPP}%)`, 'warn');
          } else if (soc < SOC_ENTLADESTOPP && aktuellerSollwert > 0) {
              log(`AKTION: Entladung pausiert (SOC: ${soc}% < ${SOC_ENTLADESTOPP}%)`, 'warn');
          } else if (soc <= SOC_LADESTOPP && soc >= SOC_ENTLADESTOPP) {
              log(`SOC im normalen Bereich: ${soc}%`, 'debug');
          }
      });
      
      // ========== DIAGNOSE & MONITORING ==========
      // Regelmäßige Systemdiagnose
      const diagIntervall = setInterval(() => {
          const ueberschuss = getState('alias.0.Stromüberschuss_IR-Lesekopf').val || 0;
          const akkuLeistung = getState(AKTUELLE_AKKULEISTUNG).val || 0;
          const akkuSOC = getState('alias.0.Akku_Ladezustand').val || 0;
          const istLadebetrieb = aktuellerSollwert < 0;
          
          log(`Systemdiagnose:
        Regelstatus: ${regelungAktiv ? "AKTIV" : "INAKTIV"}
        Betriebsmodus: ${istLadebetrieb ? 'LADEN' : 'ENTLADEN'}
        Sollleistung: ${aktuellerSollwert.toFixed(1)}W
        Istleistung: ${akkuLeistung}W
        Überschuss: ${ueberschuss}W
        SOC: ${akkuSOC.toFixed(1)}%
        Messwerte: ${mittelungArray.length} gespeichert
        Letzte Logs: ${logHistorie.slice(-3).join('\n  ')}`, 
        'info');
      }, 300000); // Alle 5 Minuten
      
      // Datenpunkt-Prüfung
      function pruefeDatenpunkte() {
          const datenpunkte = [
              'alias.0.Stromüberschuss_IR-Lesekopf',
              'alias.0.Akku_Ladezustand',
              AKTUELLE_AKKULEISTUNG,
              AKTIONS_DATENPUNKT
          ];
          
          let fehler = false;
          datenpunkte.forEach(id => {
              if (getState(id) === undefined) {
                  fehler = true;
                  log(`KRITISCH: Datenpunkt ${id} nicht gefunden!`, 'error');
              }
          });
          
          if (fehler) {
              log("Fehlende Datenpunkte - Skriptfunktionalität eingeschränkt", 'error');
          } else {
              log("Alle benötigten Datenpunkte verfügbar", 'debug');
          }
      }
      
      // Verzögerte Datenpunktprüfung
      setTimeout(pruefeDatenpunkte, 15000);
      
      // ========== NOTFALL-SYSTEM ==========
      // Automatischer Neustart bei Inaktivität
      const watchdogIntervall = setInterval(() => {
          if (!regelungAktiv) {
              log("Watchdog: Regelung inaktiv - Neustart wird versucht", 'warn');
              initSkript();
          }
      }, 600000); // Prüft alle 10 Minuten
      
      B H A 3 Replies Last reply Reply Quote 0
      • B
        besimo @BertDerKleine last edited by

        @bertderkleine
        Kann man den MS-A2 im Mqtt-Mode in den Standby zwingen z.B. durch Set Power = 0 W ?
        Hat jemand den Eigenverbrauch gemessen bei Power = 0 W ?

        BertDerKleine 2 Replies Last reply Reply Quote 0
        • BertDerKleine
          BertDerKleine @besimo last edited by

          @besimo
          Wenn Du in "mqtt.0.homeassistant.number.MSA-123456789.power_ctrl.set" eine Null sendest, dann macht er halt nix (lädt nicht & entlädt nicht), was für mich "Standby" bedeutet".

          Den Eigenverbrauch kenne ich nicht.

          1 Reply Last reply Reply Quote 0
          • B
            besimo last edited by

            @bertderkleine
            Danke für die schnelle Antwort. Also eine schleichende Reduzierung des SOC, wenn set power einige Stunden auf 0 stand, ist dir nicht aufgefallen ?

            Zum Vergleich beim EZHI von APsystems hat ein Nutzer von einer Reduzierung des SOC von 14% auf 8% in der Nacht, nachdem abends der eingestellte min SOC erreicht war, berichtet.

            BertDerKleine 1 Reply Last reply Reply Quote 0
            • BertDerKleine
              BertDerKleine @besimo last edited by

              @besimo
              Ich kann zumindest sagen, dass der Akku wirklich nicht unter die eingestellte "Entladeschlussstufe" fällt, wenn er die mal erreicht hat.
              Darum kümmert sich die fest eingebaute Logik anscheinend.

              Was er da an Energie reinsteckt, weiss ich nicht. Ich gehe davon aus, dass die Geräte hier einen klar messbaren Eigenverbrauch haben.

              Siehe: https://www.photovoltaik.eu/solarspeicher/wie-viel-schluckt-der-speicher

              Also auch bei den teureren und größeren Gerätschaften sind 15 W nichts überraschendes.

              Je nachdem wo man den Hoymiles hinstellt, gibt es im Winter auch noch die Stromkosten für die eingebaute "Heizung", die an sich ein sinnvolles Feature ist.

              B 1 Reply Last reply Reply Quote 0
              • B
                besimo @BertDerKleine last edited by besimo

                @bertderkleine
                Angeblich kann man in der App Langzeitspeicherung unterer SOC z.B. 10% einstellen, dann macht er keine Erhaltungsladung, wenn der SOC unter 10% fällt. Ist Langzeitspeicherung nicht eingestellt, macht er dann eine Erhaltungsladung.
                Hast du die Langzeitspeicherung aktiviert ?

                Grundsätzlich ist der MS-A2 ja sehr sparsam (3W im Standby) im Vergleich zu den grossen Speichern. Aber erreicht er das auch bei aktiviertem Mqtt ?

                Und Heizung ist kein Thema, die Temperatur kann man überwachen. Fällt sie unter 1°, muss man nur den Aufstellort ins Haus verlegen.

                Mein Ziel ist ja, im Winter auch noch einen bestmöglichen Autarkiegrad zu erreichen. Einen Fehlkauf habe ich ja schon mit der Huawei Luna2000-S1-10kWh. Da gehen jeden Tag von den 10kWh Nettokapazität 2kWh für den Eigenverbrauch drauf, also effektiv bleiben 8kWh echte Nettokapazität.

                BertDerKleine 1 Reply Last reply Reply Quote 0
                • BertDerKleine
                  BertDerKleine @besimo last edited by

                  @besimo sagte in Erfahrung: Hoymiles MS-A2 Akku via MQTT iobroker steuern:

                  Hast du die Langzeitspeicherung aktiviert ?

                  Was meinst Du damit? Es gibt in der App nichts mit dem Namen.

                  Ich habe (wie oben beschrieben) Zahnrad / Betriebsmodus / Eigenverbrauch / Entladeschlussstufe auf 10% gesetzt bzw. dieses Default so stehengelassen.

                  B 1 Reply Last reply Reply Quote 0
                  • B
                    besimo @BertDerKleine last edited by

                    @bertderkleine
                    Ich glaube, da hat chatgpt wieder Unwahrheiten geschrieben. Die Option Langzeitspeicherung scheint es wohl doch nicht zu geben. Die Erhaltungsladung kann bei Erreichen min SOC nur Manuell durch Ziehen des Schukostecker vermieden werden.
                    Evtl. gäbe es noch die Option über den Zeitplan in der App auf kein Betrieb zu stellen und in iobroker den Ems-mode auf "General". Der SOC sollte bei dem Test deutlich grösser, als der min SOC sein, um eine Erhaltungsladung zu vermeiden.

                    BertDerKleine 1 Reply Last reply Reply Quote 0
                    • BertDerKleine
                      BertDerKleine @besimo last edited by

                      @besimo
                      Ich verstehe noch nicht, was Du erreichen willst.
                      Wenn Du den Speicher nutzen willst, muss er voll im betrieb sein. Ob er jetzt über die App/Cloud gesteuert wird oder per MQTT dürfte keinen fundamentalen Unterscheid machen. Er muss ganz normal am Netz hängen und dann kostet die Erhaltungsladung Strom.

                      Wenn ihn abklemmst gibts natürlich keine Erhaltungsladung, aber das Ding bringt Dir natürlich so nix.

                      Statt Abklemmen kannst Du auch den Kopf 8 Sekunden drücken und den Speicher in den Inselmodus (off grid) versetzen. Dann ist auch Ruhe.

                      Ich kann mir aber keinen vernünftigen Fall vorstellen, wo tägliches oder gar stündliches An/Abklemmen irgendeinen wirtschaftlichen Sinn macht.

                      Ich schau die Tage mal, was ich über Stromverbrauch zur Erhaltung finden kann. Dazu brauche ich wieder Sonne und einen vollen Speicher.

                      Hoymiles schreibt in der BDA übrigens:

                      "• Die optimale Lebensdauer des Akkus wird durch regelmäßiges Aufladen erreicht. Laden Sie den Akku
                      stets alle paar Monate auf, selbst wenn er nicht verwendet wird.

                      • Wenn Sie den Akku über einen längeren Zeitraum einlagern, laden Sie das MS-A2 vor der Lagerung bei Raumtemperatur auf 40 % bis 50 % auf. "

                      S B 2 Replies Last reply Reply Quote 0
                      • S
                        spiffel1234 @BertDerKleine last edited by spiffel1234

                        Hi ich finde es jetzt schon mal super das das Hoymiles MSA 2 dann jetzt auch mqtt kann. Was kann es alles für Werte liefern auch wenn evtl. nur Read Only. Evtl gibt es ja dann mal einen Adapter wo man Einstellungen vornehmen kann... so hat man halt die Datenpunkte einzeln.

                        BertDerKleine 1 Reply Last reply Reply Quote 0
                        • B
                          besimo @BertDerKleine last edited by

                          @bertderkleine
                          Da der Akku sehr klein ist, würde bei mir die tägliche Nutzungszeit sehr kurz sein, etwa 2 Stunden Laden am Tag und 6-8 Stunden Entladen in der Nacht, also i.M. 15 Stunden möglicher Standby pro Tag. Wäre blöd, wenn er in dieser Zeit wegen dem MQtt-Modus im vollen Betrieb bleibt. Wenn er da z.B. 33 W brauchen würde, also 30 W mehr, als im echten Standby, wären das 30x15x365=164kWh Jahres-Mehrverbrauch, mehr als mein Gefrierschrank.

                          Und generell will ich am Ende alles in ioBroker automatisiert steuern, am besten per javascript, so dass ich die Abfrageintervalle über den Tagesverkauf variabel gestalten kann.
                          Die manuelle Geschichte war ja nur zu Testzwecken gedacht, um rauszubekommen, wie hoch der Eigenverbrauch im "Mqtt-Standby" ist.

                          BertDerKleine 1 Reply Last reply Reply Quote 0
                          • BertDerKleine
                            BertDerKleine @spiffel1234 last edited by

                            @spiffel1234 sagte in Erfahrung: Hoymiles MS-A2 Akku via MQTT iobroker steuern:

                            Was kann es alles für Werte liefern auch wenn evtl. nur Read Only.

                            Schau oben in den ersten Link in die Entwicklerdoku. Da sind Kapitel 10 und 11 mit allen ausgegebenen Werten drin. Die landen in zwei JSONs.

                            1 Reply Last reply Reply Quote 0
                            • BertDerKleine
                              BertDerKleine @besimo last edited by

                              @besimo sagte in Erfahrung: Hoymiles MS-A2 Akku via MQTT iobroker steuern:

                              Wäre blöd, wenn er in dieser Zeit wegen dem MQtt-Modus im vollen Betrieb bleibt.

                              Erstens verstehe ich nicht, warum die annimmst, dass ein "MQTT-Modus" anders Strom verbraucht als ein anderer, wo Cloud und App steuern. Ich denke, die Nutzung des Protokolls hat keine grosse Bedeutung.

                              Zweitens wirst Du im Schnitt (!) länger Aufladen und öfters, wiederholend. Das deutsche Wetter bietet ja üblicherweise was anderes als digital blauen Himmel oder gar keine Sonne. D.h. beim Laden/Entladen wird es oft hin- und hergehen.

                              1 Reply Last reply Reply Quote 0
                              • BertDerKleine
                                BertDerKleine @besimo last edited by BertDerKleine

                                @besimo sagte in Erfahrung: Hoymiles MS-A2 Akku via MQTT iobroker steuern:

                                Hat jemand den Eigenverbrauch gemessen bei Power = 0 W ?

                                Ich habe MQTT aktuell lesend verbunden (d.h. der Akku sendet alle paar Sekunden den Status) und jetzt gerade ist er voll.
                                Der Eigenverbrauch des Akkus in der Gammelphase, den ein zwischengestecktes Strommessgerät anzeigt liegt bei 6,5 W (in dem Fall bei zwei in Reihe geschalteten Akkus).

                                Das sagt natürlich nicht automatisch etwas aus darüber, ob er irgendwann mal etwas nachlädt.

                                PS:
                                Hier https://www.smartzone.de/hoymiles-ms-a2-speicher-test/ ganz unten gibt es auch Angaben zur Effizienz und Eigenverbrauch

                                S 1 Reply Last reply Reply Quote 1
                                • S
                                  spiffel1234 @BertDerKleine last edited by spiffel1234

                                  Hi ich muss nochmal einhaken weis jemand ob der MS-A2 Akku auch im "OpenDTU on Battery" supported wird? Hier kann man ja angeblich eine Nulleinspeisung machen. Evtl. Ich stelle jetzt erst mal von OPENDTU auf OPENDTU on Battery um.

                                  @BertDerKleine vielen Dank für den Hinweis.

                                  1 Reply Last reply Reply Quote 0
                                  • H
                                    hschief @BertDerKleine last edited by

                                    @bertderkleine danke für dein tolles Script, ich werde dies mal ausprobieren und im nächsten Schritt erweitern. Ich bin zwar weit nicht so gut in der Programmierung, aber wird schon klappen.
                                    Da ich einen dynamischen Tarif habe, würde ich folgende Funktion noch reinbringen.

                                    1. Entladung zu einem Zeitpunk wo der Bezugspreis am maximal ist (meist Abends & Morgens)
                                    2. Netzladung bei niedrigen Preisen

                                    Ich kann ja berichten, wird aber ein paar Tage dauern.
                                    Liebe Grüße
                                    Helmut

                                    BertDerKleine 1 Reply Last reply Reply Quote 0
                                    • BertDerKleine
                                      BertDerKleine @hschief last edited by

                                      @hschief sagte in Erfahrung: Hoymiles MS-A2 Akku via MQTT iobroker steuern:

                                      Da ich einen dynamischen Tarif habe, würde ich folgende Funktion noch reinbringen

                                      Wenn Du das zusätzlich zur bisherigen Steuerung nach Überschüssen einbringen willst, bin ich mal gespannt auf die Logik.
                                      Ich denke nämlich, dass eine Programmierung hier der leichtere Teil ist im Vergleich dazu, eine wünschenswerte Logik zu ersinnen.
                                      Einzeln eine Überschusssteuerung geht und einzeln eine Steuerung nach Preisen auch, aber das miteinander zu vermengen - schwierig.

                                      Beispiel: Willst Du wirklich den Rest im Akku morgens entladen, wegen hoher Preise, obwohl vielleicht (!) nachmittags dicke Wolken aufziehen werden und Du dann den Strom selber brauchst?
                                      Natürlich kann man hier centgenaue Arbitragen machen auf Basis von statistischer Erwartung der Sonneneinstrahlung, aber das wird dann schon sehr wissenschaftlich und umfangreich.

                                      H 1 Reply Last reply Reply Quote 0
                                      • H
                                        hschief @BertDerKleine last edited by hschief

                                        @bertderkleine
                                        Ja, stimmt, ich tast mich mal langsam ran und vielleicht hilft auch der Mittelweg. Erstmal habe ich dein Script heute zum laufen gebracht. Ich habe die Logik zwar noch nicht ganz verstande, aber ich taste mich mal ran.
                                        Folgende Änderungen habe ich mal reingebracht:

                                        1. Zwei weitere Datenpunkte:
                                          const NetzLaden = '0_userdata.0.Technik.Strom.Speicher.MSA-280024340941.NetzLadung';
                                          const Entladen = '0_userdata.0.Technik.Strom.Speicher.MSA-280024340941.Entladung';

                                        Wenn der erste auf True ist, dann wird zwangsweise vom Netz geladen
                                        Wenn der zweite auf True ist, dann wird der Akku entladen. Mit diesem kann ich in einem ersten Schritt das Entladen am Tage blockieren und die Entladung zu einem späteren Zeitpunkt starten (Wenn der Preis oben ist)

                                        In einem anderen Script habe ich nun zB. die Idee, die Tibberpreiskurve auszuwerten und zB. 2h vor dem max Preis && nach 18:00Uhr die Entladung zu starten. In der Regel ist der Akku dann durch den Verbrauch am Abend bis 24:00 Uhr leer.

                                        Den Code habe ich wie folgt angepasst. Wenn du magst, kannst du das natürlich übernehmen oder an eine bessere Stelle überführen.

                                        Zusätzlich habe ich was eingebaut, dass der Ladestrom reduziert wird, wenn die obere Ladegrenze erreicht ist. Ich meine, dies beobachtet zu haben, dass Hoymiles selber reduziert wenn es an die obere Grenze geht.

                                        Ich berichte von meinen weiteren Versuchen 🙂

                                        1 Reply Last reply Reply Quote 1
                                        • A
                                          assz @BertDerKleine last edited by assz

                                          Hallo,

                                          ich möchte mich hier mal mit einklinken, um meine Erfahrungen von parallel betriebenen Batteriesystemen zu teilen,
                                          da ich selbst zwei MS-A2 (4,48kwh) als STAND ALLONE parallel zur Bestandsanlage E3DC mit 13kwh Batteriespeicher BETREIBEN MÖCHTE 😉

                                          Grundidee:
                                          Dem MS-A2 nur erlauben UNTERHALB der maximalen Grundlast in der Nacht zu vordefinierten Zeiten den E3DC Hauptsystemspeicher zu entlasten.
                                          Also nur im General tätig sein, wenn genug PV Energie für alles vorhanden ist jedoch auch am Tag im mqtt mode in die Schranken weisen was er darf und nicht.
                                          Dazu aber weiter unten im Text...

                                          Punkt 1: Die deutsche Bürokratie und der NETZBETREIBER
                                          Erstmal... Anfrage beim Netzbetreiber da !Meldepflichtig wegen Anschluss am Niederspannungsnetz!
                                          Hier habe ich aufgrund der nicht wirklichen aufwändigen Installation (Salopp gesagt: Stecker rein...fertig) mal als gewissenhafter Bürger beim Netzbetreiber nach einer vereinfachten Anmeldung via Markstammregister
                                          --- telefonisch, --- per Mail, --- nochmals telefonisch, --- nochmals Mail... mit allen Datenblättern und Fakten 800W Begrenzung und so... angefragt.
                                          Es hieß.... Fachabteilung Einspeisung leitet an Fachabteilung XY weiter... wir melden uns.

                                          Nochmals telefonische Nachfrage auf Bearbeitungsstand da keine Antwort nach 4 Wochen...
                                          Antwort: Ich teile der Fachabteilung mit, dass sie nochmals angerufen haben.

                                          2 Monate später.... ich warte noch immer.
                                          Hier scheint fachlich keiner in der Lage zu sein eine Aussage machen zu können außer evtl. das was ich aus der Vergangenheit schon kenne:
                                          "Bitte wenden sie sich an einen eingetragenen Elektroinstallateur! Bitte senden sie uns eine E8 Inbetriebnahme Erklärung!"

                                          skip this chapter 😉

                                          Punkt 2: Hardware

                                          • 2x MS-A2,
                                            • Shelly 3EM Pro an der Hauptleitung
                                            • Shelly Plug an einer separaten 16A abgesicherten Schuko Steckdose für die beiden in Reihe geschalteten MS-A2
                                          • ioBroker Skript für mqtt Ansteuerung MS-A2 und Signalaustausch E3DC via Modbus
                                            (*by the way... bin EFK)

                                          Punkt 3: Probleme
                                          Wer den MS-A2 einfach "STAND ALLONE" zu seinem bestehenden PV Systemspeicher parallel betreiben möchte um seinen Batteriespeicher kostengünstig zu erweitern
                                          wird feststellen, dass sich die beiden Systeme im GENERAL MODE nicht vertragen.

                                          Was man also in solch einem Vorhaben unbedingt berücksichtigen muss sind Lastwechsel bzw. Zeiten von unzureichender PV Ertrag im General Mode des MS-A2!
                                          Der eine versucht den anderen zu Laden bzw. zu entladen da sie ja nichts voneinander wissen!
                                          Hier muss man schon einiges im Skript einbauen damit das nicht passiert!

                                          Lösungsansätze:

                                          • Bei unzureichendem PV Ertrag oder Lastwechsel von General in mqtt Mode wechseln um ein Eingenleben hart zu unterbinden.
                                          • Nur feste Entladezeiten im mqtt Mode in der Nacht über Astro oder Zeit z.B. 22:00 - 05:00 Uhr = 500W (unterhalb der min Grundlast)
                                          • Trotz Shelly 3EM Pro feste Freigaben definieren wann MS-A2 im General Überschuss laden darf. [PV Überschuss ausreichend?; Hauptspeicher geladen?; Brauchwassererwärmung ausreichen?; E-Fahrzeug wird geladen?; usw... ]
                                          • Entladen grundsätzlich am Tag unterbinden! (Energie ist nur für die Nacht!)
                                            Hier wird schnell klar das auch am Tage der General Mode zwischendurch weichen muss!

                                          Ergo: Man könnte sich theoretisch einen Shelly 3EM Pro an der Hauptleitung sparen und alles komplett über den ioBroker realisieren.

                                          BertDerKleine 1 Reply Last reply Reply Quote 1
                                          • BertDerKleine
                                            BertDerKleine @assz last edited by

                                            @assz sagte in Erfahrung: Hoymiles MS-A2 Akku via MQTT iobroker steuern:

                                            Ergo: Man könnte sich theoretisch einen Shelly 3EM Pro an der Hauptleitung sparen und alles komplett über den ioBroker realisieren.

                                            Absolut. Mein Skript oben tut ja im Prinzip genau das per MQTT über iobroker, was die herstellereigene Logik im "general mode" macht.
                                            Ich habe auch gar keinen Shelly 3EM Pro an der Hauptleitung, sondern benutze einen Wattwächter direkt auf dem offiziellen Zähler, der sich über MQTT und die Software Uni-Meter als Shelly 3EM ausgibt.

                                            Das Skript oben habe ich dann direkt an den MQTT Datenpunkt des Wattwächters angebunden.

                                            Statt sowas wie Wattwächter kann man natürlich jede iobroker Datenquelle für bezogene oder eingespeiste Leistung benutzen, die man hat (z.B. aus der PV Anlage), daher schreibe ich oben ja einfach von einem Alias.

                                            Du kannst das obige MQTT Skript so erweitern, wie es für Dein Szenario passt. Du brauchst dazu halt zusätzliche Datenpunkte direkt aus Deinem Systemspeicher.

                                            Wie bei @hschief hast Du auch ein ganz spezifisches, anderes Szenario, das eigene Logik benötigt. Wenn Du die Logik für Dich mal klar hast, dürfte das Skripten der einfachere Teil werden.

                                            A 1 Reply Last reply Reply Quote 0
                                            • First post
                                              Last post

                                            Support us

                                            ioBroker
                                            Community Adapters
                                            Donate

                                            572
                                            Online

                                            31.9k
                                            Users

                                            80.1k
                                            Topics

                                            1.3m
                                            Posts

                                            akku hoymiles mqtt
                                            5
                                            21
                                            1020
                                            Loading More Posts
                                            • Oldest to Newest
                                            • Newest to Oldest
                                            • Most Votes
                                            Reply
                                            • Reply as topic
                                            Log in to reply
                                            Community
                                            Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
                                            The ioBroker Community 2014-2023
                                            logo