Programmatischer Lesender - UND Schreibender Zugriff auf Kostal Plenticore - z.B. MinSoC Parameter verändern um Batterieladung zu optimieren

  • Hier ist was ich erreichen will

    Ich will mir die Möglichkeit schaffen alle Parameter - und Events des Kostal WR auszulesen - und auch die Parameter, die man als Anlagenbetreiber ändern kann programmatisch zu verändern -also zu schreiben.

    Dadurch kann man dann dem WR z.B. das Laden / Entladen der Batterie programmatisch vorgaukeln um beispielsweise die Defizite des prognosebasierten Ladens die der Kostal WR hat zu kompensieren. Oder man könnte es auch dazu verwenden um das Laden zwischen Batteriespeicher und einer Wallbox zu optimieren etc etc.

    Normalerweise poste ich hier Skripts, die ich bei mir produktiv im Einsatz habe - z.B. das LESEN der Parameter über die modbus Schnittstelle:

    Kostal Plenticore Daten per skript über Modbus auslesen

    Allerdings ist da wie gesagt nur lesender Zugriff möglich.

    Durch Zufall bin ich darüber gestolpert, dass der WR auch auf

    http://IPdesWechselrichters/api/v1

    eine REST API zur Verfügung stellt.

    Jetzt versuche ich mir ein Skript zu basteln womit ich die REST API richtig ansteuere um auch das SCHREIBEN hinzukriegen- aber da beisse ich mir die Zähne aus.

    Hier ist wie weit ich gekommen bin:

    1) Ich kann mich programmatisch am WR anmelden

    2) Ich kann programmatisch Werte auslesen (z.B. Events)

    3) Wo ich bisher kläglich scheitere ist das Schreiben eines Parameters -wie eben z.B. das Setzen des minSOC Wertes

    Anbei der aktuelle Stand meines Skripts (das ist wirklich noch Spaghetti code..) Irgendwie kriege ich nicht den richtigen JSON String an den WR übergeben. Es wäre nett, wenn mir da jemand helfen könnte.

    Unten auch ein paar Links, wo ich Anleihen genommen habe - sowie ein Screenshot der Webseite die der WR exposed (ist wohl Swagger..) :

    https://stackoverflow.com/ques…ostal-plenticore-inverter

    https://github.com/StrathCole/ioBroker.plenticore

    Tips / Hinweise gerne willkommen (auch über PN) :-) . Und ja der Kostal Support hatte mich dankenswerter Weise auf die ioBroker Lösung hingewiesen - konnte/wollte mir aber bei der Python Implementierung als Einzelbaustein nicht weiterhelfen...


  • Ok - ich antworte mir mal selber ... - hab ein kleines Erfolgserlebnis ;-)

    anbei eine aktualisierte Routine, die es mir erlaubt einige Parameter (wie z.B. den minSOC) zu programmatisch zu ändern

    Aufruf:

    python webapi_kostal3.txt

    Output:

    Authentication successful

    Successfully changed Parameter : Battery:MinSoc to value 45

    Successfully changed Parameter : Battery:MinHomeComsumption to value 100

    Successfully changed Parameter : Battery:DynamicSoc:Enable to value 1

    I am done ....


    Das ist immer noch sehr rudimentär - aber es ist klar, dass man damit nicht nur die paar Parameter schreiben kann - sondern eigentlich auch das ganze Modbus Gezockse um lesend die Werte auszulesen nicht mehr braucht.

    Das ist jetzt nicht schön implementiert (das String Handling mit den JSON Objekten hab ich noch nicht so im Griff) - aber es zeigt das Potential. Ich hab auch das Gefühl, dass die Authentifizierung und das Schreiben der Werte via REST API schneller geht als der lesende Modbus Zugriff

  • Klasse kruki, dein Skript enthält genau die mir fehlenden Berechnungen für finish und createSession :love::danke:

    Das werde ich morgen gleich mal ausprobieren. Von Python habe ich keine Ahnung, mal gucken wie man das unbekannte Zertifikat vom WR akzeptieren kann, wenn man die Base url von http auf https ändert. Für mein Shell-Skript mit wget hatte ich den Parameter schon gefunden. Als default für deine IP könntest du auch den hostname "scb" verwenden. Trotz dass ich meinen WR-Namen geändert habe und der geänderte Name in download-Log und der Weboberfläche auftaucht, bleibt der Hostname scb bei mir erhalten.

  • Hi Dachbeleger - ich würde zuerst mal schauen ob das Ding bei Dir unverändert zum Fliegen kommt.

    Der WR verschickt keine Zertifikate. Der Authentifizierungsmechanismus, den der WR implementiert hat basiert auf nem Nonce bzw. Session key. Das hat mit nem Zertifikat nix zu tun. Aber trotzdem viel Spass beim Testen..

  • ob das Ding bei Dir unverändert zum Fliegen kommt

    An der Zeile "from Crypto.Cipher import AES #windows" habe ich mir fast die Zähne ausgebissen, noch den Quelltext von crypto kompilieren lassen und dann festgestellt, dass dann doch nicht alles bei war.

    Auf meinem Linux-Laptop hat stattdessen letztendlich folgende Alternative Zeile zum Erfolg geführt:

    from Cryptodome.Cipher import AES


    Super, dann funktionierte das Einloggen mit deinem Skript!


    Als kleine Verbesserung habe ich die base_url durch Angabe des Hostnamens statt der IP-Adresse verallgemeinert

    BASE_URL = "http://scb/api/v1"


    und von Port 80 auf Port 443 umgestellt, um die Zugangsdaten nicht direkt im Klartext zu übertragen

    BASE_URL = "https://scb/api/v1"

    Dabei kam es dann wie erwartet zum Zertifikatsfehler

    Der WR verschickt keine Zertifikate

    Klar, dass die Authentifizierung des Clients nicht mit einem Clientzertifikat, sondern mit dem spannenden Algorithmus stattfindet. Hier geht es um das Serverzertifikat, welches nicht nur selbst signiert, sondern auch bereits vor über 30 Jahren abgelaufen ist.

    Mein Versuch das Zertifikat in eine Datei zu speichern und das abgerufene Zertifikat gegen die Datei zu validieren klappte bei mir nicht. Stattdessen habe ich als nicht so saubere Lösung bei allen (!) HTTPS-Aufrufen die clientseitige Prüfung des erhaltenen Serverzertifikats mit verify=False deaktiviert, z.B. beim ersten Request

    response = requests.post(url, data=step1, headers=headers, verify=False)


    Nun bin ich für meinen Teil zufrieden. Mit der von deinem Programm erzeugten Session kann mein bash-Skript nun die Leistungswerte herunterladen

    wget --no-check-certificate --header='Content-Type:application/json' --header="Authorization:$(python3 getsession.py)" --post-data='{"begin":"2020-04-03"}' -O rohdaten/eschensued$(date +%Y%m%d%H%M).csv https://scb/api/v1/logdata/download

    und anschließend auf dem Server zum Import in meine Ertragsdatenbank laden.


    kruki, du hast mir sehr geholfen, habe vielen lieben Dank dafür!


    Frohe Ostern :-)

  • Ok - ich antworte mir mal wieder selber - ich schaffe es in der Zwischenzeit auch neben dem Schreiben von ein paar Batteriedaten auch die Events des Eventlogs, die Statiskdaten, sowie DC und AC Werte auszulesen (manche dieser Werte kriegt man nicht über das normale Modbus Gedönse raus).

    Bevor ich ein aktualisiertes Skript reinstelle, will ich einige Parameter verstehen, die ich erhalte....


    Wenn ich /processdata/devices:local abfrage kriege ich auch ne ganze Menge - da ist mir aber unklar was

    Iso_R', und 'LimitEvuAbs': sind:

    { 'Dc_P': 341.9002685547,

    'DigitalIn': 0.0,

    'EM_State': 0.0,

    'Grid_L1_I': 0.7430000305,

    'Grid_L1_P': 38.7999992371,

    'Grid_L2_I': 0.8870000243,

    'Grid_L2_P': 29.0,

    'Grid_L3_I': 0.3580000103,

    'Grid_L3_P': -66.9000015259,

    'Grid_P': 0.0,

    'Grid_Q': -273.8000183105,

    'Grid_S': -273.8000183105,

    'HomeBat_P': 324.0,

    'HomeGrid_P': 0.0,

    'HomeOwn_P': 324.0,

    'HomePv_P': 0.0,

    'Home_P': 324.0,

    'Inverter:State': 6.0,

    'Iso_R': 7065000.0,

    'LimitEvuAbs': 6890.9560546875,

    'LimitEvuRel': 100.0,

    'WorkTime': 35434015.0}


    Bei der Abfrage von:

    /processdata/devices:local:ac"

    Sind mir 'ResidualCDc_I' unklar

    { 'CosPhi': 1.0,

    'Frequency': 50.0335693359,

    'InvIn_P': 0.0,

    'InvOut_P': 377.0,

    'L1_I': 0.6815592051,

    'L1_P': 126.5322113037,

    'L1_U': 223.7294921875,

    'L2_I': 0.6785074472,

    'L2_P': 123.350227356,

    'L2_U': 225.5269470215,

    'L3_I': 0.7253010869,

    'L3_P': 127.5827560425,

    'L3_U': 222.8836364746,

    'P': 377.0,

    'Q': 269.1614379883,

    'ResidualCDc_I': 0.0019795187,

    'S': 463.6031188965}


    Anybody out there ? :saint:

  • Cool - merci - das wären also (wenn´s stimmt) - wahrscheinlich 7 Megaohm - was ist da "normal" ? Sorry, bin kein Elektriker - nur "Softie" :-)