neues Modul 50_Alfen.pm zur Steuerung von Alfen Wallboxen über die HTTPS API

Begonnen von mahil, 01 Juli 2023, 17:03:41

Vorheriges Thema - Nächstes Thema

mahil

Hallo,

im Anhang findet ihr ein Modul zur Steuerung einer Alfen Wallbox über die HTTPS API.

Prinzipiell kann man eine Alfen Wallbox auch über Modbus steuern. Dazu ist aber meist eine eigene Lizenz notwendig, welche mal schlappe 200€ kostet. Die Steuerung über die HTTPS API ist kostenlos.

Folgendes ist über dieses Modul möglich:
  • Einstellen des maximalen Ladestroms je Phase
  • Umstellung zwischen 1-/3- phasigem Laden. Um dies während einer Ladesession durchführen zu können wird mindestens die Wallbox Firmware 6.4.0-4210 benötigt.
  • Reboot der Wallbox
  • verschiedene Wallbox Parameter zyklisch auslesen und anzeigen
  • Setzen der Wallbox Logindaten

Entwickelt und getestet wurde dieses Modul mit einer Alfen Eve Single Pro-Line und der Firmware 5.8.1-4123 und 6.4.0-4210. Soweit mir bekannt, ist zur Steuerung über die HTTPS API mindestens eine Firmware >= 5.x notwendig. Ab 5.x wurde auch ein Usermanagement eingeführt.

Installation

  • Kopieren der angehängten Datei in euer Modulverzeichnis, normalerweise /opt/fhem/FHEM
  • Anlegen eines Gerätes mit
    define <name> Alfen <IP of wallbox> <interval to query the wallbox>
  • Setzen des Wallbox Passworts
    set <name> password <Wallbox password>
  • falls der Wallbox User nicht admin lautet, muss dieser noch angepasst werden
    set <name> user <Wallbox user>

Falls dieses Modul bei euch läuft, wäre ein kurzes Feedback über den Wallbox Typ und die Firmware hilfreich.

Hilfreich bei der Entwicklung dieses Moduls war die Dokumentation des Homeassistant Alfen Addons.

Updates
  • 05.07.2023: Version 1.1, Umstellung der Kommunikation zur Wallbox von LWP auf HttpUtils_NonblockingGet
  • 12.07.2023: Version 1.2, Lesen der maximal einstellbaren Leistung von der Wallbox, Serialisierung mehrerer get/set Befehle
Raspberry Pi4; CUL_MAX: MAX! Heizkörperthermostat basic; Zigbee über Deconz ConBee II: Xiaomi (Thermostate, Fenstersensoren, Bewegungsmelder), Ikea (Bewegungsmelder, Repeater, Leuchtkörper); Shelly: Dimmer, Schalter; Tasmota: Steckdosen, Rollladenschalter

betateilchen

Du solltest in Deinem "Modul" besser die Standardverfahren für die Kommunikation verwenden, die FHEM von Haus aus bereitstellt (HTTPutils.pm, DevIo.pm usw.) anstatt das alles selbst nachbauen zu wollen.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

mahil

Zitat von: betateilchen am 01 Juli 2023, 17:39:11Du solltest in Deinem "Modul" besser die Standardverfahren für die Kommunikation verwenden, die FHEM von Haus aus bereitstellt (HTTPutils.pm, DevIo.pm usw.) anstatt das alles selbst nachbauen zu wollen.
Ist mein erstes FHEM Modul :D. Werde ich mir genauer anschauen. Danke für den Hinweis.
Raspberry Pi4; CUL_MAX: MAX! Heizkörperthermostat basic; Zigbee über Deconz ConBee II: Xiaomi (Thermostate, Fenstersensoren, Bewegungsmelder), Ikea (Bewegungsmelder, Repeater, Leuchtkörper); Shelly: Dimmer, Schalter; Tasmota: Steckdosen, Rollladenschalter

rudolfkoenig

Das Problem mit LWP ist, dass es FHEM auf diverse Weise blockieren kann (Name-Lookup, Connect, Daten holen).

HttpUtils_NonblockingGet tut das nicht, man benutzt sie, wenn man HTTP (oder HTTPS) Abfragen hat.
DevIo.pm ist fuer die "direkte" TCP/IP Kommunikation, ohne HTTP "Overhead".

mahil

Zitat von: rudolfkoenig am 01 Juli 2023, 17:52:49Das Problem mit LWP ist, dass es FHEM auf diverse Weise blockieren kann (Name-Lookup, Connect, Daten holen).

HttpUtils_NonblockingGet tut das nicht, man benutzt sie, wenn man HTTP (oder HTTPS) Abfragen hat.
DevIo.pm ist fuer die "direkte" TCP/IP Kommunikation, ohne HTTP "Overhead".
Das Problem mit blockieren bei FHEM ist mir durchaus bekannt. Ich dachte das allerdings durch den Aufruf von BlockingCall zu umgehen. Alle LWP Zugriffe sollten damit in einem geforkten Prozess laufen und damit sollte dann der Hauptprozess nicht blockiert werden. Nochmal Danke für die Hinweise. Ich werde das entsprechend umarbeiten.
Raspberry Pi4; CUL_MAX: MAX! Heizkörperthermostat basic; Zigbee über Deconz ConBee II: Xiaomi (Thermostate, Fenstersensoren, Bewegungsmelder), Ikea (Bewegungsmelder, Repeater, Leuchtkörper); Shelly: Dimmer, Schalter; Tasmota: Steckdosen, Rollladenschalter

rudolfkoenig

ZitatDas Problem mit blockieren bei FHEM ist mir durchaus bekannt. Ich dachte das allerdings durch den Aufruf von BlockingCall zu umgehen.
BlockingCall ist die "Holzhammer-Methode", wenn keine bessere Alternativen zur Verfuegung stehen.
HttpUtils_NonblockingGet ist effizienter, und "nebenwirkungsfrei".

mahil

Zitat von: rudolfkoenig am 02 Juli 2023, 11:33:55BlockingCall ist die "Holzhammer-Methode", wenn keine bessere Alternativen zur Verfuegung stehen.
HttpUtils_NonblockingGet ist effizienter, und "nebenwirkungsfrei".

Habe das mit HttpUtils_NonblockingGet mal ausprobiert, aber leider nicht zum Laufen gebracht.

Prinzipiell ist bei der Kommunikation mit der Alfen Wallbox der Ablauf wie folgt:
  • Login
  • Datenabfrage bzw. setzen von Wallbox Parametern
  • Logout

Dies muss über mehrere HTTPS Aufrufe realisiert werden. Die Verbindung darf dazwischen nicht geschlossen werden. Damit die Verbindung zwischen den Abfragen nicht geschlossen wird, muss bei der Kommunikation über LWP 'keep_alive' gesetzt werden:
$ua = LWP::UserAgent->new(keep_alive => 1);
Gleiches habe ich bei HttpUtils_NonblockingGet gesetzt:
my $param = {
    timeout    => 5,
    hash       => $hash,
    keepalive  => 1,
    loglevel   => 1,
    sslargs    => { SSL_verify_mode => 0},
    callback   => \&Alfen_ParseHttpResponse,
    actions    => $actions # Liste der noch durchzuführenden Aktionen (Login, Datenabfrage, Logout), wird in Alfen_ParseHttpResponse ausgewertet
    ..... die Parameter zur auszuführenden Aktion, beim ersten Aufruf z.B. die Loginparameter
  };
HttpUtils_NonblockingGet($param);

In Alfen_ParseHttpResponse wird dann das Abfrageergebnis ausgewertet und falls in $param->{'actions'} noch ein Eintrag steht, die nächste HTTPS Abfrage ausgelöst.

Das Login hat so auch funktioniert. Bei den anderen Abfragen bekomme ich einen 'HTTP response code 401'. Der FHEM Log sieht dazu wie folgt aus:
2023.07.03 19:48:40.870 1: performing HttpRequest of type login
2023.07.03 19:48:40.871 2: HttpUtils url=https://192.168.2.91/api/login NonBlocking via https
2023.07.03 19:48:40.871 1: IP: 192.168.2.91 -> 192.168.2.91
2023.07.03 19:48:41.568 2: HttpUtils request header:
POST /api/login HTTP/1.0
Host: 192.168.2.91
User-Agent: fhem
Accept-Encoding: gzip,deflate
Connection: keep-alive
Content-Type: application/json
Content-Length: 62

2023.07.03 19:48:41.973 1: https://192.168.2.91/api/login: HTTP response code 200
2023.07.03 19:48:41.973 2: HttpUtils https://192.168.2.91/api/login: Got data, length: 0
2023.07.03 19:48:41.974 2: HttpUtils response header:
HTTP/1.1 200 OK
Content-Type: alfen/json; charset=UTF-8
Connection: keep-alive
Content-Length: 0
2023.07.03 19:48:41.974 1: parsing HTTPS request
2023.07.03 19:48:41.974 1: init next HTTPS request
2023.07.03 19:48:41.974 1: performing HttpRequest of type get_props
2023.07.03 19:48:41.975 2: HttpUtils url=https://192.168.2.91/api/prop?ids=2221_16 NonBlocking via https
2023.07.03 19:48:41.975 1: IP: 192.168.2.91 -> 192.168.2.91
2023.07.03 19:48:42.664 2: HttpUtils request header:
GET /api/prop?ids=2221_16 HTTP/1.0
Host: 192.168.2.91
User-Agent: fhem
Accept-Encoding: gzip,deflate
Connection: keep-alive
Authorization: Basic YWRtaW46ZjJHcW02TFBxL3FDQ2hMVGQ4c241MFBVeTJrPQ==
Content-Type: application/json

2023.07.03 19:48:42.694 1: https://192.168.2.91/api/prop?ids=2221_16: HTTP response code 401
2023.07.03 19:48:42.694 1: parsing HTTPS request
2023.07.03 19:48:42.694 1: error while requesting https://192.168.2.91/api/prop?ids=2221_16 - https://192.168.2.91/api/prop?ids=2221_16: wrong authentication
2023.07.03 19:48:42.695 1: init next HTTPS request
2023.07.03 19:48:42.695 1: performing HttpRequest of type logout
2023.07.03 19:48:42.696 2: HttpUtils url=https://192.168.2.91/api/logout NonBlocking via https
2023.07.03 19:48:42.696 1: IP: 192.168.2.91 -> 192.168.2.91
2023.07.03 19:48:43.348 2: HttpUtils request header:
POST /api/logout HTTP/1.0
Host: 192.168.2.91
User-Agent: fhem
Accept-Encoding: gzip,deflate
Connection: keep-alive
Authorization: Basic YWRtaW46ZjJHcW02TFBxL3FDQ2hMVGQ4c241MFBVeTJrPQ==
Content-Type: application/json

2023.07.03 19:48:43.372 1: https://192.168.2.91/api/logout: HTTP response code 401
2023.07.03 19:48:43.372 1: parsing HTTPS request
2023.07.03 19:48:43.372 1: error while requesting https://192.168.2.91/api/logout - https://192.168.2.91/api/logout: wrong authentication

Beim Coding habe ich mich am Beispiel für HttpUtils_NonblockingGet() für Modulprogrammierer orientiert.

Das sieht für mich irgendwie aus, als ob der keep_alive nicht funktioniert. Hat hier jemand eine Idee, was ich noch probieren könnte?

Habe es in meiner Testumgebung auch mal mit HttpUtils_BlockingGet probiert. Hat leider auch nicht funktioniert:
2023.07.03 20:14:35.858 1: performing HttpRequest of type login
2023.07.03 20:14:35.858 2: HttpUtils url=https://192.168.2.91/api/login Blocking via https
2023.07.03 20:14:36.560 2: HttpUtils request header:
POST /api/login HTTP/1.0
Host: 192.168.2.91
User-Agent: fhem
Accept-Encoding: gzip,deflate
Connection: keep-alive
Content-Type: application/json
Content-Length: 62

2023.07.03 20:14:37.133 1: https://192.168.2.91/api/login: HTTP response code 200
2023.07.03 20:14:37.134 2: HttpUtils https://192.168.2.91/api/login: Got data, length: 0
2023.07.03 20:14:37.134 2: HttpUtils response header:
HTTP/1.1 200 OK
Content-Type: alfen/json; charset=UTF-8
Connection: keep-alive
Content-Length: 0
2023.07.03 20:14:37.134 1: performing HttpRequest of type get_props
2023.07.03 20:14:37.134 2: HttpUtils url=https://192.168.2.91/api/prop?ids=2221_16 Blocking via https
2023.07.03 20:14:42.140 1: error while requesting https://192.168.2.91/api/prop?ids=2221_16 - https://192.168.2.91/api/prop?ids=2221_16: Can't connect(2) to https://192.168.2.91:443:  SSL wants a read first
2023.07.03 20:14:42.140 1: performing HttpRequest of type logout
2023.07.03 20:14:42.140 2: HttpUtils url=https://192.168.2.91/api/logout Blocking via https
2023.07.03 20:14:47.147 1: error while requesting https://192.168.2.91/api/logout - https://192.168.2.91/api/logout: Can't connect(2) to https://192.168.2.91:443:  SSL wants a read first
Hier bekomme ich allerdings eine andere Fehlermeldung.
Raspberry Pi4; CUL_MAX: MAX! Heizkörperthermostat basic; Zigbee über Deconz ConBee II: Xiaomi (Thermostate, Fenstersensoren, Bewegungsmelder), Ikea (Bewegungsmelder, Repeater, Leuchtkörper); Shelly: Dimmer, Schalter; Tasmota: Steckdosen, Rollladenschalter

mifu

Hallo,
hab gerade nach einer Alfen Sterunung gesucht und direkt gefunden. Super :-)

So ich habe auch die Alfen Pro Line Single mit der Firmware 5.8.1-4123. Das Modul läuft so weit, ich kann die Daten auslesen.Laden muss ich mal noch ausprobieren.

rudolfkoenig

ZitatDas sieht für mich irgendwie aus, als ob der keep_alive nicht funktioniert. Hat hier jemand eine Idee, was ich noch probieren könnte?
keepalive sollte funktionieren, dafuer muss man beim zweiten Aufruf den gleichen $param an HttpUtils_NonblockingGet uebergeben, wie beim ersten mal.
Callback kann man aendern, genauso wie data und header.
Wichtig ist nur, dass die Gegenseite die Laenge der Antwortdaten mitgibt.

SSL_verify_mode = 0 ist die Voreinstellung.

mahil

Zitat von: rudolfkoenig am 04 Juli 2023, 19:35:09keepalive sollte funktionieren, dafuer muss man beim zweiten Aufruf den gleichen $param an HttpUtils_NonblockingGet uebergeben, wie beim ersten mal.
Das mit dem gleichen $param war der Fehler. Ich hatte $param immer neu aufgebaut. Habe jetzt eine Version auf Basis von HttpUtils_NonblockingGet bereitgestellt. Vielen Dank für die Hilfestellung.
Raspberry Pi4; CUL_MAX: MAX! Heizkörperthermostat basic; Zigbee über Deconz ConBee II: Xiaomi (Thermostate, Fenstersensoren, Bewegungsmelder), Ikea (Bewegungsmelder, Repeater, Leuchtkörper); Shelly: Dimmer, Schalter; Tasmota: Steckdosen, Rollladenschalter

Axxl

Danke für das Modul ! Funktioniert bei mir auf Anhieb mit meiner Wallbox sehr gut.