APSystems EZ-1

Begonnen von rubberduck67, 15 August 2023, 11:40:39

Vorheriges Thema - Nächstes Thema

rubberduck67

So, das mit dem Python ist am laufen

Power PV-Input 1: 0 W
Power PV-Input 2: 0 W
Generation today 0.071 kWh

Jetzt mal wegen der Integration überlegen

Lehmi54

Hallo rubberduck67,
habe die Datenübergabe nach fhem mit einem Pythonscript und der Python FHEM API in einen Dummy und einem cronjob aller Minute von 8 bis 16 Uhr gelöst. Das Einstellen des  Powerlimits erfolgt über ein DOIF und GetHttpFile. Habe es auch mit MQTT probiert. Funktioniert auch ohne Probleme.
Es ist, wie schon geschrieben, eine Anfängerlösung ohne schnick schnack und Fehlerbehandlung. Hatte bisher mit Python noch nie Kontakt...
Schönes WE
Uwe 
2x Raspberry 4 und 3 - FHEM 6.2
z-wave Netzwerk, SIGNALduino

AlexMuc

Hallo Uwe,
seit heute läuft bei mir auch ein AP EZ1-M. Leider bin ich bereits beim Installieren der Pythongeschichte (auf einem Raspberry) für das lokale API auf die Nase gefallen, s.u.
Magst / kannst du eine detailiertere (für doofe wie mich) Anleitung schreiben wie du genau vorgegangen bist. Dann brauchen wir nur noch jemanden, der sich gut mit FHEM und "Modulen" auskennt, der uns das formal korrekt in FHEM einbaut :-)

Mein aktueller Stand scheitert bereits bei der Installation des "lokalen APIs" auf dem Raspberry...
"pip install apsystems-ez1" liefert bei mir den Fehler
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
ERROR: Could not find a version that satisfies the requirement apsystems-ez1
ERROR: No matching distribution found for apsystems-ez1
Python hat bei mir noch die V 3.9.2, die 3.12.1, bei der dieser Fehler angeblich nicht mehr auftritt, krieg ich irgendwie nicht installiert. Da fehlt mir wohl noch die richtige Anleitung.

Gruß
Michael

rubberduck67

Zitat von: Lehmi54 am 16 Dezember 2023, 11:00:41Hallo rubberduck67,
habe die Datenübergabe nach fhem mit einem Pythonscript und der Python FHEM API in einen Dummy und einem cronjob aller Minute von 8 bis 16 Uhr gelöst. Das Einstellen des  Powerlimits erfolgt über ein DOIF und GetHttpFile. Habe es auch mit MQTT probiert. Funktioniert auch ohne Probleme.
Es ist, wie schon geschrieben, eine Anfängerlösung ohne schnick schnack und Fehlerbehandlung. Hatte bisher mit Python noch nie Kontakt...
Schönes WE
Uwe 
Wie übergibst Du das Phyton Script? Direct aus dem Dummy? Hast du im Fhem noch ein Modul installiert? Es gibt etwas mit  dem du Phyton über FHEM ausführen kannst.

Gruß
Sven

rubberduck67

ZitatPython hat bei mir noch die V 3.9.2, die 3.12.1, bei der dieser Fehler angeblich nicht mehr auftritt, krieg ich irgendwie nicht installiert. Da fehlt mir wohl noch die richtige Anleitung.


Bei mir ging das mit 
sudo apt install python3
python --version

Lehmi54

Zitat von: rubberduck67 am 16 Dezember 2023, 17:16:45Wie übergibst Du das Phyton Script?
Hallo Sven, hallo Michael,
ich  versuchs mal mit einem ersten längeren Beitrag überhaupt, also Nachsicht :-)
Die Installation
pip install apsystems-ez1brachte eine Fehlermeldung externally managed, die ich behoben habe mit
sudo rm /usr/lib/python3.11/EXTERNALLY-MANAGEDdannach habe konnt ich die API und die fhem api installieren
pip install fhemdas neu zusammengebaute Script "aps_basis_3.py"
#!/usr/bin/python3
from APsystemsEZ1 import APsystemsEZ1M
import asyncio
import fhem
import time
# Initialize the inverter with the specified IP address and port number.
inverter = APsystemsEZ1M("192.168.2.XXX", 8050)
fh = fhem.Fhem("192.168.2.XXX")
async def main():
      try:
        # Fetch output data from the inverter.
        response = await inverter.get_output_data()

        # Display power input from PV-Input 1 and 2.
        print("Power PV-Input 1: " + str(response.p1) + " W")
        print("Power PV-Input 2: " + str(response.p2) + " W")
        fh.send_cmd("setreading ez1_m Power_1 " + str(response.p1))
        fh.send_cmd("setreading ez1_m Power_2 " + str(response.p2))
        fh.send_cmd("setreading ez1_m Energie_1 " + str(response.e1))
        fh.send_cmd("setreading ez1_m Energie_2 " + str(response.e2))
        fh.send_cmd("setreading ez1_m Energie_1_bisher " + str(response.te1))
        fh.send_cmd("setreading ez1_m Energie_2_bisher " + str(response.te2))


        # Display total energy generation for the current day.
        print("Generation today " + str(round(response.e1 + response.e2, 3)) + " kWh")
        fh.send_cmd("setreading ez1_m Gesamt_heute " + str(round(response.e1 + response.e2, 3)))
        fh.send_cmd("setreading ez1_m BKW_bisher " + str(round(response.te1 + response.te2, 3)))

        maxPower = await inverter.get_max_power()
        fh.send_cmd("setreading ez1_m t_akt_max_power " + str(maxPower))
       
       
      except Exception as e:
        # Handle any exceptions that occur during the data fetch and print the error.
        print(f"An error occurred: {e}")
# Run the main coroutine.
# This is the entry point of the script and it runs the main function in an asynchronous manner.
asyncio.run(main())
habe ich mit WinSCP nach /home/pi/kopiert und lauffähig (755) gemacht
in FHEM habe ich einen Dummy definiert
define ez1_m dummy
attr ez1_m readingList state
attr ez1_m room Dummy
attr ez1_m setList state:selectnumbers,100,50,800,0,lin
attr ez1_m webCmd state
mit crotab -e habe ich am Ende ergänzt
*/1 8-16 * * * /home/pi/aps_basis_3.py >/dev/null 2>&1
00 12 * * * /home/pi/aps_wr_daten.py /dev/null 2>&1
zu Setzen des Powerlimits habe ich ein DOIF definiert
#***************Power Limit EZ1_M setzen *************************
define di_max_power DOIF ([ez1_m:?state])({my $max_power = Value("ez1_m");;GetHttpFile("192.168.2.XXX:8050", "/setMaxPower?p=$max_power")})
setuuid di_max_power 657dc21f-f33f-942f-ed4f-5b310c999e88057c
attr di_max_power addStateEvent 1
attr di_max_power do always
attr di_max_power room Balkonkraftwerk,Dummy
mit "setreading ez1_m state 312" oder direkt am Dummy über set kann ich damit das Powerlimit setzen.
Die Visualisierung mache ich mit Damians genialen SVG-uiTable-Funktionen realisiert z.B.
define di_ha_power DOIF ##
attr di_ha_power event_Readings ha_power_ges_av:{[MQTT2_DVES_A65A29:GS303_Power_cur]-([ez1_m:Power_1:d]+[ez1_m:Power_2:d])},ha_power_einspeisung:{[$SELF:ha_power_ges_av:d]<0 ? [$SELF:ha_power_ges_av:d]:"0"}
attr di_ha_power room Balkonkraftwerk
attr di_ha_power state [#sum:d2:"wallplug":power_1]
attr di_ha_power uiTable {package ui_Table;;\
$TC{0..4}="style='padding-left: 3px;;padding-right: 3px'"\
}\
card([ez1_m:Power_1:144col],"Leistung West","solar",0,300,120,0,"W",\&temp_hue,"1","400,,,,,1")\
card([ez1_m:Power_2:144col],"Leistung Ost","solar",0,300,120,0,"W",\&temp_hue,"1","400,,,,,1")\
card([ez1_m:Gesamt_heute:144col],"BKW Energy","solar",0,3000,120,0,"kWh",\&temp_hue,"1","400,,,,,1")
"MQTT2_DVES_A65A29:GS303_Power_cur" ist der Verbrauch am Stromzaehler
Ich hoffe, ich habe nichts vergessen und nicht in der Luft zerreissen, ich bin absoluter Pythonanfänger!
Freuen würde ich mich, wenn ein Profi eine Idee hat, wie ich überprüfen kann, ob der Wechselrichter erreichbar ist. ich glaube requests sollte man nutzen.
Das ganze funktioniert natürlich nur tagsüber, wenn der Wechselrichter Power von den Modulen bekommt.
Schönen 3. Advent
Uwe




2x Raspberry 4 und 3 - FHEM 6.2
z-wave Netzwerk, SIGNALduino

rubberduck67

Klingt einfach, mal sehen das ich das einmal morgen in Angriff nehme.

Danke! das gibt erst einmal Ideen!


Gruß
Sven

AlexMuc

Ich hab mir wohl mein System total zerschossen, muß das zwischen den Feiertagen erstmal ,,bereinigen  >:(
So wie ich das (leider) bis jetzt verstehe, muß man die Daten aktiv am Gerät abholen und bis jetzt habe ich noch nirgends etwas über irgendwelche ,,Sicherheitsfunktionen" gelesen die beim Zugriff auf das ,,lokale API" vorhanden sein sollten.
Viel besser wäre es doch eigentlich, wenn man in der App bei der Konfiguration des APIs einfach einen MQTT Server mit Anmeldedaten angeben könnte und dann sendet der Wechselrichter nicht mehr zum Cloudserver sondern direkt an einen lokalen Server. Das wäre einfach und universal für alle :-) Werde das mal auf der Projektseite zur Diskussion stellen. Das Projekt ist ja noch jung.

Wer Spaß und Lust hat, könnte ja mal den Verkehr zwischen WR und dem Cloudserver mitschneiden und untersuchen. Sofern man da was brauchbares mitlesen kann.

rubberduck67

Zitat von: rubberduck67 am 16 Dezember 2023, 20:16:19Klingt einfach, mal sehen das ich das einmal morgen in Angriff nehme.

Läuft jetzt
Änderung: es muß zwingend das FHEM Modul eingebunden werden
 Im Cronjob den Pfad zum Phyton eintragen

AlexMuc

Mein aktueller Stand ist:
Python ist immer noch im Eimer aber: das braucht man garnicht :-)
Der Wechselrichter läßt sich ganz simple mit einigen wenigen HTTP-Zeilen abfragen wenn das lokale API aktiviert ist. Hier der Link zur Anleitung: Local API EZ1-m

Aktuell hab ich mir 2 Devices per HTTPmod zusammengestückelt. Ist leider nicht besonders schön und elegant weil ich kaum Ahnung hab, aber zumindest bekomme ich jetzt schonmal alle 30 Sekunden die aktuellen Daten direkt vom Wechselrichter.
Ein kleiner Fortschritt wäre es schon, wenn sich diese 4 Anfragen und die 2 Setbefehle in ein Device integrieren ließen und dann per doif aktualisiert würden.
- http://ipadresse/getDeviceInfo
- http://ipadresse/getOutputData
- http://ipadresse/getMaxPower
- http://ipadresse/getAlarm

- http://ipadresse/setMaxPower?p=600.  [30..800]
- http://ipadresse/setOnOff?status=1   0=on, 1 = off

Wesentlich cooler wäre es aber, wenn man sich diesen Wechselrichter einfach per Template einrichten könnte und dann alles "automagisch" passiert, also so in etwa:
defmod meinWechselrichter AP_System_EZ1m ipAdresse Abfrageinterval_Daten Abfrageinterval_Status Abfrageinterval_Alarm

Gibt es irgendwo Beispiele für solch ein Vorhaben? Bei den bisherigen Wechselrichtern die ich gesehen habe war mir das als Anfänger leider alles zu kompliziert oder ich hab nur noch nicht das "richtige Musterdevice" gefunden was sich ähnlich abfragen / steuern läßt. Wer kann mich da in die richtige Richtung schubsen damit  da "was schönes" bei raus kommt. Gerne liefere ich auch "echte Antworten" vom Wechselrichter denn die in der Doku sind bereits formatiert. In Wirklichkeit kommt das alles in einer Zeile "angeschwommen" :-)
Falls Interesse an meinen Versuchen besteht, dann poste ich gerne. Einfach Bescheid sagen.


Michael

huri-kane

#25
Na da kann ich vielleicht ein wenig helfen. Ich hab eher zufällig vor wenigen Wochen mitbekommen, dass APSystems diese Funktion quasi "stillschweigend" eingebaut hat und war sehr erfreut, dass man den Wechselrichter damit nun von der Cloud abkoppeln kann. Die Template-Variante wäre natürlich ein Extraschleifchen. Aber einmal eingerichtet tut es auch so seinen Dienst.

Ich hab mir das Ganze als ein Device mit dem HttpMod-Modul eingerichtet.
define EZ1_inverter HTTPMOD http://apsystems:8050/getOutputData 60
attr EZ1_inverter get1JSON data_maxPower
attr EZ1_inverter get1Name MaxPower
attr EZ1_inverter get1Poll 1
attr EZ1_inverter get1URL http://apsystems:8050/getMaxPower
attr EZ1_inverter get2Name OutputData
attr EZ1_inverter get2Poll 1
attr EZ1_inverter get2URL http://apsystems:8050/getOutputData
attr EZ1_inverter get3Name Alarm
attr EZ1_inverter get3Poll 1
attr EZ1_inverter get3URL http://apsystems:8050/getAlarm
attr EZ1_inverter get4Name Disabled
attr EZ1_inverter get4Poll 1
attr EZ1_inverter get4URL http://apsystems:8050/getOnOff
attr EZ1_inverter get5Name DeviceInfo
attr EZ1_inverter get5Poll 1
attr EZ1_inverter get5PollDelay 3600
attr EZ1_inverter get5URL http://apsystems:8050/getDeviceInfo
attr EZ1_inverter icon measure_photovoltaic_inst
attr EZ1_inverter reading101JSON data_maxPower
attr EZ1_inverter reading101Name MaxPower
attr EZ1_inverter reading201JSON data_e1
attr EZ1_inverter reading201Name e1
attr EZ1_inverter reading202JSON data_e2
attr EZ1_inverter reading202Name e2
attr EZ1_inverter reading203JSON data_te1
attr EZ1_inverter reading203Name te1
attr EZ1_inverter reading204JSON data_te2
attr EZ1_inverter reading204Name te2
attr EZ1_inverter reading205JSON data_p1
attr EZ1_inverter reading205Name p1
attr EZ1_inverter reading206JSON data_p2
attr EZ1_inverter reading206Name p2
attr EZ1_inverter reading301JSON data_og
attr EZ1_inverter reading301Name alarm_off_grid
attr EZ1_inverter reading302JSON data_oe
attr EZ1_inverter reading302Name alarm_output_fault
attr EZ1_inverter reading303JSON data_isce1
attr EZ1_inverter reading303Name alarm_dc1_short
attr EZ1_inverter reading304JSON data_isce2
attr EZ1_inverter reading304Name alarm_dc2_short
attr EZ1_inverter reading401JSON data_status
attr EZ1_inverter reading401Name disabled
attr EZ1_inverter reading501JSON data_deviceId
attr EZ1_inverter reading501Name deviceId
attr EZ1_inverter reading502JSON data_devVer
attr EZ1_inverter reading502Name deviceVersion
attr EZ1_inverter reading503JSON data_ssid
attr EZ1_inverter reading503Name SSID
attr EZ1_inverter set1Hint slider,30,10,800
attr EZ1_inverter set1JSON data_maxPower
attr EZ1_inverter set1Name MaxPower
attr EZ1_inverter set1ParseResponse 1
attr EZ1_inverter set1URL http://apsystems:8050/setMaxPower?p=$val
attr EZ1_inverter set4Hint 0,1
attr EZ1_inverter set4Name Disabled
attr EZ1_inverter set4ParseResponse 1
attr EZ1_inverter set4URL http://apsystems:8050/setOnOff?status=$val
attr EZ1_inverter stateFormat {\
  sprintf("%.2fkWh / %.2fkWh / %.0fW",\
          ReadingsVal($name, "total_energy", 0),\
          ReadingsVal($name, "total_energy_today", 0),\
          ReadingsVal($name, "total_power", 0));;\
}
attr EZ1_inverter userReadings total_power:p.* { ReadingsVal($name, "p1", 0) + ReadingsVal($name, "p2", 0) },\
total_energy_today:e.* { ReadingsVal($name, "e1", 0) + ReadingsVal($name, "e2", 0) },\
total_energy:te.* { ReadingsVal($name, "te1", 0) + ReadingsVal($name, "te2", 0) },\
energy_today:e.* monotonic { ReadingsVal($name, "e1", 0) + ReadingsVal($name, "e2", 0) },\
energy_month:te.* monotonic { ReadingsVal($name, "te1", 0) + ReadingsVal($name, "te2", 0) }

Über die einzelnen get*Poll- bzw. get*PollDelay-Attribute lässt sich für die individuelle URI das Polling mitsamt Intervall anpassen - schließlich müssen nicht alle Informationen mit der gleichen Granularität abgefragt werden.

Die zusätzlichen UserReadings 'energy_today' und 'energy_month' summieren einfach die erzeugte Energie auf und werden einmal am Tag/Monat durch ein zusätzliches 'at' Device verarbeitet, welches dann noch "Hilfs-Readings" setzt. Ich habe bisher noch keinen Monat Laufzeit durch, daher können sich durchaus noch Fehler drin sein:
define EZ1_inverter_tag at *00:00:00 {\
  my $NAME = "EZ1_inverter";;\
  my $total_energy = ReadingsVal($NAME, "total_energy", 0);;\
  my $energy_today = ReadingsVal($NAME, "energy_today", 0);;\
  fhem("setreading $NAME energy_today 0");;\
  fhem("setreading $NAME energy_yesterday $energy_today");;\
  fhem("setreading $NAME total_energy_yesterday $total_energy");;\
  if ( (strftime("%d", localtime(time()) ) ) eq "01")  # 1. des Monats\
  {\
    my $energy_month = ReadingsVal($NAME, "energy_month", 0);;\
    fhem("setreading $NAME energy_month 0");;\
    fhem("setreading $NAME energy_lastmonth $energy_month");;\
    fhem("setreading $NAME total_energy_lastmonth $total_energy");;\
  }\
}

Die Readings "total_power", "energy_yesterday" und "energy_lastmonth" lasse ich loggen um damit den Leistungsverlauf am Tag sowie die Energieproduktion pro Tag bzw. pro Monat zu visualisieren (siehe Anhänge). Für ersteres muss man für sich entscheiden, ob einem eine "Messung" pro Minute reicht (über das define vom HTTPMOD): Das wäre dann ein Abwägen zwischen Genauigkeit und Speicherbedarf des Logs bzw. Rendering-Zeit des Graphen (bei mit ein Raspi3).

Hoffe das hilft ein wenig.

Grüße
André

AlexMuc

Hallo André,
das sieht aber gut aus.
Genau so hab ich mir das vorgestellt aber nicht hinbekommen. Mit dem Vorbild werde ich mich nachher in den Übungsraum begeben und schauen, wo ich bei meinen Versuchen jeweils gescheitert bin. Teile deines Devices hab ich ja bereits geschafft, aber ,,alles in einem", da haperte es halt :-)
Vielen Dank dafür, das du das mit uns teilst. Da können sicher viel was von lernen denen ähnliche Aufgaben bevorstehen.

Für das ,,Extraschleifchen" brauchen wir nun nur noch einen Idealisten mit Langweile der solche Templates zum Zeitvertreib baut ;-)

Huabafranze

#27
Hallo zusammen,
ich verfolge diesen Verlauf schon ein paar Wochen. Gerade habe ich gesehen, das es neue Beiträge gibt. Leider bin ich nur ein reiner Copy/Paste FHEM-Programmierer und Python ist für mir nur eine Schlange  :))
Mein geplantes vorhaben mit dem Wechselrichter wäre folgendes. Wenn ein Überschuss an Leistung produziert wird, soll dieser in einen Akku geladen werden. Die sogenannte Nachteinspeisung wollte ich dann realisieren, indem ich den Akku (evtl. über DC-DC-Wandler an einen Eingang eines zweiten EZ-1 M anschließe, und sich die einsprechend benötigte Einspeiseleistung über den Ausgang des Wechselrichters automatisch regelt. Die benötigte Leistung soll über einen bereits eingebauten  Shelly Pro 3EM passieren. Vielleicht hat jemand zu diesem Vorhaben Ideen oder auch Hardwaretipps.
Einen Punkt habe ich noch. Zur EZ1-M FHEM-Einbindung muss der Wechselrichter wohl in den Lokalen Modus gebracht werden, ich würde aber gerne weiterhin von unterwegs die APSystems App (also Cloud) nutzen. Eben auch um unterwegs in der App den Verlauf der Nachteinspeisung beobachten zu können.

Vielen Dank an alle die hier so fleißig programmieren und ihr Wissen anderen zur Verfügung stellen.

AlexMuc

Bisher hab ich noch keine Stelle im Internet gefunden, die die gleichzeitige Meldung der Wechselrichterdaten in die Cloud beschreibt. Das ist wohl vorerst nur ein entweder oder. Was du aber machen könntest wäre eine eigene Website zu betreiben auf die du von Fhem die Daten schreibst. Wäre zumindest meine Lösung zu dem Problem solange die Firmware des EZ1m nicht mehr hergibt.

Deine Batterielösung solltest du nochmal überdenken und schauen, wie das andere bereits gelöst haben. Das sollte mit nur einem Wechselrichter machbar sein. Genaueres können die aber sicher kundigere beschreiben, ich bin im Thema auch erst Anfänger, könnte mir aber jetzt schon, nach einem knappen Monat mit dem BKW, eine Erweiterung um eine Akkulösung vorstellen. Nach bisheriger Datenlage sollte selbst im Winter an sonnigen Tagen ausreichend Energie über sein, um den Grundbedarf bis zum nächsten Tag zu decken. Ist zumindest mein erster Eindruck. An trüben Tage gewinnt man allerdings nichtmal nen winzigen Blumenpott

Lehmi54

Zitat von: huri-kane am 10 Januar 2024, 07:51:50Hoffe das hilft ein wenig.

Grüße
André
Guten Abend, André und ihr Interessierten,
ja es hat sehr, ganz herzlichen Dank für die gute Lösung. Ich habe am letzten Wochenende von meiner Pythonmqtt-Version auf Deine Lösung umgestellt und dabei den Raspi gleich neu aufgesetzt. Läuft seitdem ohne Probleme bis auf den winterbedingten Ertrag :-), Super Lösung! Die Visualisierung läuft bei mir weiterhin über uiTable.
Grüße
Uwe
2x Raspberry 4 und 3 - FHEM 6.2
z-wave Netzwerk, SIGNALduino