lumapu / ahoy

Various tools, examples, and documentation for communicating with Hoymiles microinverters
https://ahoydtu.de
Other
948 stars 222 forks source link

Limit setzen über API klappt nicht mehr seit 0.8.70 #1415

Closed Ollipop030 closed 7 months ago

Ollipop030 commented 7 months ago

Platform

ESP32

Assembly

I did the assebly by myself

nRF24L01+ Module

nRF24L01+ plus

Antenna

external antenna

Power Stabilization

Elko (~100uF)

Connection picture

Version

0.8.76

Github Hash

7c532ca

Build & Flash Method

AhoyDTU Webinstaller

Setup

none

Debug Serial Log output

none

Error description

Seit der Ahoy Version 0.8.70 klappt das Limit senden über die API nicht mehr, wenn in Ahoy ein Passwort vergeben ist. Wenn das Passwort gelöscht wird klappt es wieder. http://AhoyIP/api/ ist aber erreichbar, ob mit oder ohne Passwort.

Das Limit setze ich hiermit: https://github.com/reserve85/HoymilesZeroExport

Gibt auch dort ein Issue: https://github.com/reserve85/HoymilesZeroExport/issues/132

MetaChuh commented 7 months ago

ich hab's auch mit v0.8.77 noch nicht geschafft 🫤

auch curl --header "Content-Type:application/json" --user "user:password" --request POST --data '{"id": 4, "cmd": "limit_nonpersistent_relative", "val": 50}' "http://dtu_ip/api/ctrl"

liefert nur {"success":false,"error":"nicht angemeldet, Kommando nicht möglich!"}

die älteren versionen funktionieren auch bei mir wie gewohnt.

lumapu commented 7 months ago

ich bin dabei und habe auch schon eine bessere Version parat. Aktuell habe ich nur das Problem, das der ESP durch API Anfragen neu startet. Ich weiß noch nicht warum und was der Auslöser ist, das wollte ich heute noch herausfinden. In der aktuellen Version hatte ich auch nicht erwartet, dass die API requests besser gehen, ich habe nur schon die Verbesserung vorbereitet.

lumapu commented 7 months ago

ab Version 0.8.78 muss man sich erst authentifizieren, bevor man über die API was verändern darf.

Das Passwort muss nur einmalig in Klartext übertragen werden. Nach 20 Minuten erlischt ein generierter Token, sofern in der Zwischenzeit nicht ein weiteres Kommando gesendet wurde. Jedes Kommando setzt das Timeout der 20 Minuten wieder zurück. Zur weiteren Absicherung wird die IP-Adresse der API ausgewertet. Das heißt, wenn im Netzwerk der Token mitgelesen werden sollte, kann trotzdem nicht auf die API zugegriffen werden, da beim Authenifizieren die IP-Adresse im ESP gespeichert wird.

Jede Authentifizierung führt zu einem neuen Token. Theoretisch wäre auch ein zugriff von zwei versch. Clients möglich, diese müssten sich aber für jedes Kommando neu authentifizieren. Dafür müsste jedes mal das Passwort im Klartext übertragen werden was nicht zu empfehlen ist.

Ich bin sehr gespannt, wie ihr meine Umsetzung findet und wie ihr damit zurecht kommt. 😊

Python Test Script (Limit auf 100% setzen) Die IP-Adresse muss geändert werden. Passwort ist hier `admin`. Man kann den Token beliebig oft wiederverwenden - man muss nur innerhalb des Timeouts von 20 Minuten bleiben. ```python import requests import json url = 'http://192.168.0.81/api/ctrl' myobj = {'cmd': 'limit_nonpersistent_relative', 'val': '1000', 'id': 0} x = requests.post(url, json = myobj) print(x.text) myobj = {'cmd': 'auth', 'val': 'admin'} x = requests.post(url, json = myobj) print(x.text) y = json.loads(x.text) myobj = {'cmd': 'limit_nonpersistent_relative', 'val': '1000', 'id': 0, 'token': y["token"]} x = requests.post(url, json = myobj) print(x.text) myobj = {'cmd': 'limit_nonpersistent_relative', 'val': '1000', 'id': 0, 'token': y["token"]} x = requests.post(url, json = myobj) print(x.text) ```
Python Test Script - Output ```bash {"success":false,"error":"not logged in, command not possible!"} {"success":true,"token":"I6NWJ91ITOU39CTW"} {"success":true,"id":0} {"success":true,"id":0} ```
MetaChuh commented 7 months ago

fragen:

1) warum ab jetzt 1000 für 100% statt wie früher 100 für 100% ?

grund der frage:

jedes api nutzende projekt muss dann beide routinen beinhalten (x1 / x10) und wissen, welche ahoy dtu version gerade läuft. viel zusätzlicher case/if/else code in allen steuerungs projekten. die 100 für 100% beizubehalten, macht einbauen von auth rückwärtskompatibel mit älteren versionen, da auth und token in älteren versionen ignoriert wird (gleiche api ansteuerung sind dann, bereits getestet, für alle versionen möglich)

2) ginge in zukunft als single line alternative {'cmd': 'limit_nonpersistent_relative', 'val': '1000', 'id': 0, 'auth': "password"} (one pass auth und cmd) ?

gründe der frage:

a) um kein 20 minuten tracking, für die gültigkeit des tokens zu speichern, wird nahezu jeder in seiner steuerung, einfach aus jedem befehl, eine doppelbefehl abfolge (auth und danach limit_nonpersistent_relative) machen. dadurch wird jedes mal ein neuer token erstellt und im esp mit referenz zur ip zwischengespeichert. muss wie reserve85 noch testen, ob dies die ahoydtu bei normaler bis erhöhter befehlsrate zum abstürzen bringt.

b) eine möglichkeit eines einzeilers, hilft sämtlichen projekten, die derzeit nur ein single pass template für ahoy und opendtu api befehlsaufrufe haben.

thx

reserve85 commented 7 months ago

@lumapu : hier bin ich grad beim implementieren drübergestolpert: bei mir geht das mit jedem "ausgedachten" Token, dann kommt immer successful = true zurück und das Limit wird eingestellt. Auch ohne abgerufenem token.

edit: irgendwie komisch, ich kann es nicht mehr nachstellen. Es war aber definitiv so, da ich mich wunderte wieso es funktioniert obwohl ich den Token noch gar nicht implementiert hatte...

lumapu commented 7 months ago

Danke für euer Feedback. Folgendes habe ich angepasst:

Python Test Script (Limit auf 100% setzen) Die IP-Adresse muss geändert werden. Passwort ist hier `admin`. Man kann den Token beliebig oft wiederverwenden - man muss nur innerhalb des Timeouts von 20 Minuten bleiben. Zuerst eine Anfrage, die mit gesetztem Passwort fehlschlägt. Dann kommt eine Anfrage mit eingebetteter Authentifizierung. Die nächsten beiden Anfragen nutzen den zurückgegebenen Token. Die letzten Beiden Zeilen zeigen eine Option, die Authentifizierung gesondert zu machen. ```python import requests import json url = 'http://192.168.0.81/api/ctrl' myobj = {'cmd': 'limit_nonpersistent_relative', 'val': '100.0', 'id': 0} x = requests.post(url, json = myobj) print(x.text) myobj = {'auth': 'admin', 'cmd': 'limit_nonpersistent_relative', 'val': '1000', 'id': 0} x = requests.post(url, json = myobj) print(x.text) y = json.loads(x.text) myobj = {'cmd': 'limit_nonpersistent_relative', 'val': '100.0', 'id': 0, 'token': y["token"]} x = requests.post(url, json = myobj) print(x.text) myobj = {'cmd': 'limit_nonpersistent_relative', 'val': '99.9', 'id': 0, 'token': y["token"]} x = requests.post(url, json = myobj) print(x.text) myobj = {'auth': 'admin'} x = requests.post(url, json = myobj) print(x.text) y = json.loads(x.text) myobj = {'cmd': 'limit_nonpersistent_relative', 'val': '99.8', 'id': 0, 'token': y["token"]} x = requests.post(url, json = myobj) print(x.text) ```
Python Test Script - Output ```bash {"success":false,"error":"ERR_PROTECTED"} {"success":true,"token":"5OH37BUUQP1SWOT3","id":0} {"success":true,"id":0} {"success":true,"id":0} {"success":true,"token":"U8BFVP2UYKDO6N8X"} {"success":true,"id":0} ```

edit: mögliche Fehler:

ERR_AUTH
ERR_INDEX
ERR_UNKNOWN_CMD
ERR_LIMIT_NOT_ACCEPT
ERR_PROTECTED
MetaChuh commented 7 months ago

thx, bereits geflasht und wir beginnen zu testen 👍

thx & greetings 👍🙏

MetaChuh commented 7 months ago

@Ollipop030

wie sieht's bei dir aus ? auch alles ok und schließbar, bezüglich dieses ahoy issues ?

ps, weil cross projects: bei hoymileszeroexport fehlt imho "nur noch" revert vom "ahoy_factor" 10er multiplikator als critical task.

(die non localized error message auswertung bei auth fehlern ist optional, solange man die englische ahoy firmware verwendet. ansonsten ist die bisherige auth routine, seit hoymileszeroexport 1.73 weiterhin kompatibel mit ahoydtu v0.8.80)

reserve85 commented 7 months ago

ne passt noch nicht von der DTU (ich konnte nur in der Pause schnell schauen, werde das nachher implementieren), wenn das Passwort im AHOY vergeben wird und die DTU neu gestartet wird, dann akzeptiert die DTU auch ohne auth das Kommando. command (leeres Token): command

result (successful): result

wurde ein mal ein Token abgerufen, dann gehen die cmd-befehle auf error. (wie gewünscht)

@lumapu kannst du das nachstellen?

lumapu commented 7 months ago

@reserve85 tatsächlich, leerer Token geht bei mir auch, echt komisch. Utnersuche ich gleich.