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. Einsteigerfragen
  4. Einbindung von Geräten
  5. Erfahrung: Hoymiles MS-A2 Akku via MQTT iobroker steuern

NEWS

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

  • Monatsrückblick – September 2025
    BluefoxB
    Bluefox
    13
    1
    2.2k

  • Neues Video "KI im Smart Home" - ioBroker plus n8n
    BluefoxB
    Bluefox
    16
    1
    3.1k

Erfahrung: Hoymiles MS-A2 Akku via MQTT iobroker steuern

Geplant Angeheftet Gesperrt Verschoben Einbindung von Geräten
akkuhoymilesmqtt
37 Beiträge 10 Kommentatoren 5.5k Aufrufe 10 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.
  • B besimo

    @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.

    BertDerKleineB Offline
    BertDerKleineB Offline
    BertDerKleine
    schrieb am zuletzt editiert von
    #13

    @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 Antwort Letzte Antwort
    0
    • B besimo

      @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 ?

      BertDerKleineB Offline
      BertDerKleineB Offline
      BertDerKleine
      schrieb am zuletzt editiert von BertDerKleine
      #14

      @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 Antwort Letzte Antwort
      1
      • BertDerKleineB 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 Offline
        S Offline
        spiffel1234
        schrieb am zuletzt editiert von spiffel1234
        #15

        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 Antwort Letzte Antwort
        0
        • BertDerKleineB 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. :smiley:

          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
          
          H Offline
          H Offline
          hschief
          schrieb am zuletzt editiert von
          #16

          @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

          BertDerKleineB 1 Antwort Letzte Antwort
          0
          • H hschief

            @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

            BertDerKleineB Offline
            BertDerKleineB Offline
            BertDerKleine
            schrieb am zuletzt editiert von
            #17

            @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 Antwort Letzte Antwort
            0
            • BertDerKleineB BertDerKleine

              @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 Offline
              H Offline
              hschief
              schrieb am zuletzt editiert von hschief
              #18

              @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 Antwort Letzte Antwort
              1
              • BertDerKleineB 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. :smiley:

                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
                
                A Offline
                A Offline
                assz
                schrieb am zuletzt editiert von assz
                #19

                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.

                BertDerKleineB H 2 Antworten Letzte Antwort
                1
                • A 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.

                  BertDerKleineB Offline
                  BertDerKleineB Offline
                  BertDerKleine
                  schrieb am zuletzt editiert von
                  #20

                  @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 Antwort Letzte Antwort
                  0
                  • BertDerKleineB BertDerKleine

                    @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 Offline
                    A Offline
                    assz
                    schrieb am zuletzt editiert von assz
                    #21

                    @bertderkleine
                    Wollte nur andere User mit solch einem Vorhaben über das gegenseitige Speichergeschaukel im Vorfeld informieren.
                    system runs bug-free ;)

                    Hat denn jemand Info`s bezüglich Markstammregister für n MS-A2 als Stand Allone?

                    BertDerKleineB 1 Antwort Letzte Antwort
                    0
                    • A assz

                      @bertderkleine
                      Wollte nur andere User mit solch einem Vorhaben über das gegenseitige Speichergeschaukel im Vorfeld informieren.
                      system runs bug-free ;)

                      Hat denn jemand Info`s bezüglich Markstammregister für n MS-A2 als Stand Allone?

                      BertDerKleineB Offline
                      BertDerKleineB Offline
                      BertDerKleine
                      schrieb am zuletzt editiert von
                      #22

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

                      @bertderkleine
                      Wollte nur andere User mit solch einem Vorhaben über das gegenseitige Speichergeschaukel im Vorfeld informieren.
                      system runs bug-free ;)

                      Wenn's gut läuft, magst Du das Skript hier als Anregung für andere posten?

                      1 Antwort Letzte Antwort
                      0
                      • A Offline
                        A Offline
                        assz
                        schrieb am zuletzt editiert von
                        #23

                        @bertderkleine
                        Sorry,
                        dafür ist es zu speziell,
                        da ich 4 Skripte parallel laufen habe, die ineinander greifen und Schrittketten sowie Datenpunkte für meine Visualisierung mit eingebaut habe.

                        1 Antwort Letzte Antwort
                        0
                        • H Offline
                          H Offline
                          harvey637
                          schrieb am zuletzt editiert von
                          #24

                          Hi, ich schaue mir das auch an und habe winzige Anpassungen (bzw. Vorschläge, dies in Post 1 in das Script einzubauen)

                          • alle Datenpunkte als const, also auch den Verbrauchszähler, z.B.
                          /** Datenpunkt für den aktuell gemessene Akku Ladungzustand in % */
                          const AKTUELLER_AKKULADEZUSTAND = 'alias.0.MSA-000000000000.q_soc'; // q = aus quick
                          
                          /** Datenpunkt für den aktuell gemessene Verbrauch plus=Überschuss/Einspeisung minus=Verbrauch/Kauf*/
                          const VERBRAUCHSZAEHLER = '0_userdata.0.Blockly.ShellyEmu.Power-Total-Raw';
                          
                          • neben "laden" und "entladen" gibt es noch "standby" als Status des Akku, wenn er voll ist. Dies könnte auch bei der Loganzeige verwendet werden, da ein Akku > SOC_Ladeschwelle nicht mehr geladen wird.
                          const akkuSOC = getState(AKTUELLER_AKKULADEZUSTAND).val;
                          const istAkkuVoll = akkuSOC > SOC_LADESTOPP; // grösser als Ladestopp bedeutet Akku voll
                          
                          • die internen Werte könnten auch optional als iobroker-Werte gespeichert werden, dann kann man sie auch in Grafen verwenden, eventuell in einstellbarem Zeitraster, um nicht zuviele Punkte in die DB zu schreiben

                          • eine Variable zum einfachen Pausieren der Regelung, etwa um Akkuswapping bei mehreren Akkus zu verhindern

                          Ansonsten vielen Dank für deine Mühe, läuft schon ganz gut, mal auf Erfahrungen warten
                          cu
                          Harvey

                          1 Antwort Letzte Antwort
                          1
                          • I Offline
                            I Offline
                            isolator
                            schrieb am zuletzt editiert von
                            #25

                            Hallo Bert,

                            vielen dank für dein Script.
                            Läuft ganz gut, bekomme aber ein paar Warnungen angezeigt. Da muss ich nochmal nachschauen an was das liegt, bin aber ein absoluter Neuling in Java ;)

                            Also die Steuerung über Nacht und die Ladung mit Rest PV-Strom funktioniert prima.

                            Einzig bei Lastwechsel (E-Herd) ist noch nicht so zufriedenstellend ;)
                            Irgendwie ist der Speicher zu langsam. Habe überschuss, speicher lädt, Last vom E-Herd geht rein, Speicher speist noch ein, obwohl Fremdbezug ist.

                            Könnte man die Interwalle kürzer setzen oder Zerschießt es dann das Script ?

                            Oder gibt es eine andere Lösung, für das "kleine" Problem

                            mfg

                            BertDerKleineB 1 Antwort Letzte Antwort
                            0
                            • I isolator

                              Hallo Bert,

                              vielen dank für dein Script.
                              Läuft ganz gut, bekomme aber ein paar Warnungen angezeigt. Da muss ich nochmal nachschauen an was das liegt, bin aber ein absoluter Neuling in Java ;)

                              Also die Steuerung über Nacht und die Ladung mit Rest PV-Strom funktioniert prima.

                              Einzig bei Lastwechsel (E-Herd) ist noch nicht so zufriedenstellend ;)
                              Irgendwie ist der Speicher zu langsam. Habe überschuss, speicher lädt, Last vom E-Herd geht rein, Speicher speist noch ein, obwohl Fremdbezug ist.

                              Könnte man die Interwalle kürzer setzen oder Zerschießt es dann das Script ?

                              Oder gibt es eine andere Lösung, für das "kleine" Problem

                              mfg

                              BertDerKleineB Offline
                              BertDerKleineB Offline
                              BertDerKleine
                              schrieb am zuletzt editiert von
                              #26

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

                              Einzig bei Lastwechsel (E-Herd) ist noch nicht so zufriedenstellend ;)
                              Irgendwie ist der Speicher zu langsam. Habe überschuss, speicher lädt, Last vom E-Herd geht rein, Speicher speist noch ein, obwohl Fremdbezug ist.

                              Lastwechsel sind so ein Ding, denn die Steuerung soll ja tatsächlich gedämpft reagieren und nicht wild oszillieren.
                              Da musst Du Dein Optimum durch ausprobieren finden.
                              Du kannst das Samplingintervall etwas runtersetzen um mehr daten schneller zu bekommen und den Integralfaktor raufsetzen.
                              Außerdem kannst Du mit der Schrittweite spielen (Zeile 254). Das ist aktuell auf 30% begrenzt.

                              Ich habe hier auch mal die hardware-integrierte Logik über Unimeter-Emulation laufen gelassen und die ist zwar schneller in der Anpassung als das Skript oben mit den vorgeschlagenen Parametern, aber z.B. Wasserkocher sind dem auch eher zu schnell da und wieder weg.

                              Am Ende bleibt daher nur Ausprobieren für das persönliche Verbrauchsprofil.

                              Wenn Du bessere Parameter findest, kannst Du sie ja hier teilen.

                              O 1 Antwort Letzte Antwort
                              0
                              • BertDerKleineB BertDerKleine

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

                                Einzig bei Lastwechsel (E-Herd) ist noch nicht so zufriedenstellend ;)
                                Irgendwie ist der Speicher zu langsam. Habe überschuss, speicher lädt, Last vom E-Herd geht rein, Speicher speist noch ein, obwohl Fremdbezug ist.

                                Lastwechsel sind so ein Ding, denn die Steuerung soll ja tatsächlich gedämpft reagieren und nicht wild oszillieren.
                                Da musst Du Dein Optimum durch ausprobieren finden.
                                Du kannst das Samplingintervall etwas runtersetzen um mehr daten schneller zu bekommen und den Integralfaktor raufsetzen.
                                Außerdem kannst Du mit der Schrittweite spielen (Zeile 254). Das ist aktuell auf 30% begrenzt.

                                Ich habe hier auch mal die hardware-integrierte Logik über Unimeter-Emulation laufen gelassen und die ist zwar schneller in der Anpassung als das Skript oben mit den vorgeschlagenen Parametern, aber z.B. Wasserkocher sind dem auch eher zu schnell da und wieder weg.

                                Am Ende bleibt daher nur Ausprobieren für das persönliche Verbrauchsprofil.

                                Wenn Du bessere Parameter findest, kannst Du sie ja hier teilen.

                                O Offline
                                O Offline
                                opöl
                                schrieb am zuletzt editiert von
                                #27

                                @bertderkleine ,

                                sehr interessanter Beitrag.
                                Wenn ich Dich recht verstehe, betreibst Du den Speicher „stand alone“, also nur am Netz, ohne angeschlossene PV Anlage als „Powerbank“. Zur Verbrauchsmessung nutzt Du einen IR Sensor (Hichi IR Sensor?) am Zähler.

                                Da kommt mir doch die Idee, meine Balkon PV so zu lassen, wie sie ist (ohne Speicher mit Deye WR direkt ans Netz angeschlossen) und den HM MS-A2 in der Wohnung ebenfalls nur ans Hausnetz anzuschließen.
                                Dann könnte ich den Verbrauch am Zähler über meinen Hichi erfassen und via iobroker und Java Script die Ladung und Entladung (nur über das Hausnetz) steuern.
                                Das ließe dann (theoretisch) auch den Betrieb mehrerer Speicher sowie eine Nulleinspeisung zu.
                                Ist das so grob richtig oder bin ich irgendwo komplett falsch abgebogen?

                                Gruß

                                BertDerKleineB 1 Antwort Letzte Antwort
                                0
                                • O opöl

                                  @bertderkleine ,

                                  sehr interessanter Beitrag.
                                  Wenn ich Dich recht verstehe, betreibst Du den Speicher „stand alone“, also nur am Netz, ohne angeschlossene PV Anlage als „Powerbank“. Zur Verbrauchsmessung nutzt Du einen IR Sensor (Hichi IR Sensor?) am Zähler.

                                  Da kommt mir doch die Idee, meine Balkon PV so zu lassen, wie sie ist (ohne Speicher mit Deye WR direkt ans Netz angeschlossen) und den HM MS-A2 in der Wohnung ebenfalls nur ans Hausnetz anzuschließen.
                                  Dann könnte ich den Verbrauch am Zähler über meinen Hichi erfassen und via iobroker und Java Script die Ladung und Entladung (nur über das Hausnetz) steuern.
                                  Das ließe dann (theoretisch) auch den Betrieb mehrerer Speicher sowie eine Nulleinspeisung zu.
                                  Ist das so grob richtig oder bin ich irgendwo komplett falsch abgebogen?

                                  Gruß

                                  BertDerKleineB Offline
                                  BertDerKleineB Offline
                                  BertDerKleine
                                  schrieb am zuletzt editiert von
                                  #28

                                  @opöl sagte in Erfahrung: Hoymiles MS-A2 Akku via MQTT iobroker steuern:

                                  @bertderkleine ,
                                  sehr interessanter Beitrag.
                                  Wenn ich Dich recht verstehe, betreibst Du den Speicher „stand alone“, also nur am Netz, ohne angeschlossene PV Anlage als „Powerbank“.

                                  Ohne kleines Balkopanel, ja. Den Strom erzeugen PV-Panels auf dem Dach ohne direkte Verkabelung zum Speicher.

                                  Zur Verbrauchsmessung nutzt Du einen IR Sensor (Hichi IR Sensor?) am Zähler.

                                  Ein Wattwächter, was quasi das gleiche ist, nur out-of-the Box benutzerfreundlich in Betrieb zu nehmen.

                                  Dann könnte ich den Verbrauch am Zähler über meinen Hichi erfassen und via iobroker und Java Script die Ladung und Entladung (nur über das Hausnetz) steuern.

                                  Korrekt.
                                  Wobei ich selbst aktuell in diesem Setup aktuell die aktive Steuerung (eher aus Bequemlichkeit) wieder der eingebauten Logik übertragen habe und MQTT nur zum Daten-Auslesen nutze.
                                  Die Wattwächter-Daten emulieren via Uni-Meter-Emulatorsoftware einen Shelly, den der Speicher dann erkennt und für Steuersignale nutzt.
                                  Für mein Setup reicht das aus.

                                  Das ließe dann (theoretisch) auch den Betrieb mehrerer Speicher sowie eine Nulleinspeisung zu.
                                  Ist das so grob richtig oder bin ich irgendwo komplett falsch abgebogen?
                                  Korrekt.

                                  Die "Nulleinspeisung" geht auf beide Wege.

                                  Der Betrieb komplexerer Logiken wie disjunkte Speicher oder das, was weiter oben diskutiert wurde hier im Thread, geht natürlich out of the box mit der eingebauten Steuerung nicht. Da spielt dann eine persönlich ausgestaltete Steuerung über iobroker ihre Stärken aus. Dafür ist das hier beschrieben: damit man es nach Gusto so formt, wie man es braucht.

                                  Zwei baugleiche 2kWh Speicher kann man natürlich auch mit der internen Steuerung einfach in Reihe schalten plug-and-play. Erst wenn man noch mehr will oder die unbedingt an unterschiedlichen Orten aufgestellt werden sollen, muss man zwingend selbst eine Steuerung schreiben in iobroker.

                                  O 1 Antwort Letzte Antwort
                                  0
                                  • BertDerKleineB BertDerKleine

                                    @opöl sagte in Erfahrung: Hoymiles MS-A2 Akku via MQTT iobroker steuern:

                                    @bertderkleine ,
                                    sehr interessanter Beitrag.
                                    Wenn ich Dich recht verstehe, betreibst Du den Speicher „stand alone“, also nur am Netz, ohne angeschlossene PV Anlage als „Powerbank“.

                                    Ohne kleines Balkopanel, ja. Den Strom erzeugen PV-Panels auf dem Dach ohne direkte Verkabelung zum Speicher.

                                    Zur Verbrauchsmessung nutzt Du einen IR Sensor (Hichi IR Sensor?) am Zähler.

                                    Ein Wattwächter, was quasi das gleiche ist, nur out-of-the Box benutzerfreundlich in Betrieb zu nehmen.

                                    Dann könnte ich den Verbrauch am Zähler über meinen Hichi erfassen und via iobroker und Java Script die Ladung und Entladung (nur über das Hausnetz) steuern.

                                    Korrekt.
                                    Wobei ich selbst aktuell in diesem Setup aktuell die aktive Steuerung (eher aus Bequemlichkeit) wieder der eingebauten Logik übertragen habe und MQTT nur zum Daten-Auslesen nutze.
                                    Die Wattwächter-Daten emulieren via Uni-Meter-Emulatorsoftware einen Shelly, den der Speicher dann erkennt und für Steuersignale nutzt.
                                    Für mein Setup reicht das aus.

                                    Das ließe dann (theoretisch) auch den Betrieb mehrerer Speicher sowie eine Nulleinspeisung zu.
                                    Ist das so grob richtig oder bin ich irgendwo komplett falsch abgebogen?
                                    Korrekt.

                                    Die "Nulleinspeisung" geht auf beide Wege.

                                    Der Betrieb komplexerer Logiken wie disjunkte Speicher oder das, was weiter oben diskutiert wurde hier im Thread, geht natürlich out of the box mit der eingebauten Steuerung nicht. Da spielt dann eine persönlich ausgestaltete Steuerung über iobroker ihre Stärken aus. Dafür ist das hier beschrieben: damit man es nach Gusto so formt, wie man es braucht.

                                    Zwei baugleiche 2kWh Speicher kann man natürlich auch mit der internen Steuerung einfach in Reihe schalten plug-and-play. Erst wenn man noch mehr will oder die unbedingt an unterschiedlichen Orten aufgestellt werden sollen, muss man zwingend selbst eine Steuerung schreiben in iobroker.

                                    O Offline
                                    O Offline
                                    opöl
                                    schrieb am zuletzt editiert von opöl
                                    #29

                                    @bertderkleine ,

                                    vielen Dank für Deine Erklärungen. Eine Frage hätte ich noch. Du schriebst:

                                    „Die Wattwächter-Daten emulieren via Uni-Meter-Emulatorsoftware einen Shelly, den der Speicher dann erkennt und für Steuersignale nutzt.“

                                    Wo läuft die Uni-Meter Software und wird ein/mein Hichi WLAN IR Sensor genauso als Shelly erkannt wie Dein Wattwächter, also out of the box ohne zusätzliche HW/SW?

                                    Danke und Gruß

                                    BertDerKleineB 1 Antwort Letzte Antwort
                                    0
                                    • O opöl

                                      @bertderkleine ,

                                      vielen Dank für Deine Erklärungen. Eine Frage hätte ich noch. Du schriebst:

                                      „Die Wattwächter-Daten emulieren via Uni-Meter-Emulatorsoftware einen Shelly, den der Speicher dann erkennt und für Steuersignale nutzt.“

                                      Wo läuft die Uni-Meter Software und wird ein/mein Hichi WLAN IR Sensor genauso als Shelly erkannt wie Dein Wattwächter, also out of the box ohne zusätzliche HW/SW?

                                      Danke und Gruß

                                      BertDerKleineB Offline
                                      BertDerKleineB Offline
                                      BertDerKleine
                                      schrieb am zuletzt editiert von
                                      #30

                                      @opöl sagte in Erfahrung: Hoymiles MS-A2 Akku via MQTT iobroker steuern:

                                      @bertderkleine ,

                                      vielen Dank für Deine Erklärungen. Eine Frage hätte ich noch. Du schriebst:

                                      „Die Wattwächter-Daten emulieren via Uni-Meter-Emulatorsoftware einen Shelly, den der Speicher dann erkennt und für Steuersignale nutzt.“

                                      Wo läuft die Uni-Meter Software und wird ein/mein Hichi WLAN IR Sensor genauso als Shelly erkannt wie Dein Wattwächter, also out of the box ohne zusätzliche HW/SW?

                                      Danke und Gruß

                                      Schau hier: https://github.com/sdeigm/uni-meter

                                      Bei mir läuft das auf demselben Raspi wie iobroker als Java.

                                      Die Portnutzung ist zu beachten und man braucht halt ein passendes Konfigurationsfile.

                                      Das Rumprobieren für genau Dein Setup wird eher unvermeidbar sein. Aber schau Dich im Netz um, da gibt es schon viele ausprobiere Kombis.

                                      1 Antwort Letzte Antwort
                                      0
                                      • mcm1957M Online
                                        mcm1957M Online
                                        mcm1957
                                        schrieb am zuletzt editiert von
                                        #31

                                        Nur falls es jemand noch nicht gesehen hat:
                                        Es gibt auch einen dedizierten Adapter für hoymiles-ms-a2:

                                        ioBroker.hoymiles-ms

                                        Derzeit (nur) im LATEST Repo verfügbar.
                                        Auslesen aller Werte die der Akku liefert sowie Steuern der Abgabeleistung ist implementiert.
                                        Irgendeine Art von Regelung (z.B. '0-Einspeisung') ist zumindest derzeit nicht im Adapter implementiert.

                                        Entwicklung u Betreuung: envertech-pv, hoymiles-ms, ns-client, pid, snmp Adapter;
                                        Support Repositoryverwaltung.

                                        Wer Danke sagen will, kann nen Kaffee spendieren: https://paypal.me/mcm1957atiobroker

                                        LESEN - gute Forenbeitrage

                                        1 Antwort Letzte Antwort
                                        0
                                        • A 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.

                                          H Offline
                                          H Offline
                                          HMMS-A2
                                          schrieb am zuletzt editiert von
                                          #32

                                          @assz Hallo, genau das Problem habe ich aktuell. Wir hatten bereits ein Balkonkraftwerk mit MS-A2 Speicher - mit Hilfe eines Shelly pro 3em ist der Speicher an eine Steckdose angeschlossen, also nicht mit dem BKW Wechselrichter verbunden.
                                          Nun ist eine PV-Anlage mit Speicher dazu gekommen. Wenn nun der MS-A2 sich entladen hat, erkennt der Shelly, dass ja noch Stromüberschuss (Speicher PV) vorhanden ist und der MS-A2 lädt sich aus dem PV-Speicher auf.
                                          Ich löse das z.Zt. so, dass ich den MS-A2 tagsüber aufladen lasse (BKW und PV), dass funktioniert. Wenn er dann voll ist, setze ich ihn auf Standby. Und wenn der PV-Speicher früh morgens leer ist, wecke ich den MS-A2 auf. Alles manuell - also total bescheuert. Ich kenne mich leider überhaupt nicht mit MQTT aus... Gibt es ein entsprechendes Skript - oder könnte so eines entwickelt werden, dass eine automatisierte Einbindung des MS-A2 in ein PV-System möglich macht? Das wäre eine Lösung, die sicherlich auch für andere interessant wäre, denn eine "normale" Speichernachrüstung für eine PV-Anlage ist ja viel teurer, als einen kleinen AC-Speicher in Eigenregie aufzustellen. VG

                                          mcm1957M 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

                                          363

                                          Online

                                          32.4k

                                          Benutzer

                                          81.5k

                                          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