OpenDTU WEB-api

#7698406
Lesenswert?

Hallo, ich habe zwei HM800 Wechselrichter an einer OpenDTU. Von meinem Laptop kann ich mit

curl --no-progress-meter http://192.168.0.153/api/livedata/status | jq

alle möglichen Livedaten in Form einer langen Liste auslesen, die so aussieht:

{ "inverters": [ { "serial": "114190651346", "name": "WR-1", "order": 0, "data_age": 0, "poll_enabled": true, "reachable": true, "producing": true, "limit_relative": 100, "limit_absolute": 800, "AC": { "0": { "Power": { "v": 323.7999878, "u": "W", "d": 1 }, "Voltage": { "v": 227.6999969, "u": "V", "d": 1 }, . . . ], "total": { "Power": { "v": 542.2999878, "u": "W", "d": 1 }, "YieldDay": { "v": 721, "u": "Wh", "d": 0 }, "YieldTotal": { "v": 611.6069946, "u": "kWh", "d": 3 } }, "hints": { "time_sync": false, "radio_problem": false, "default_password": false } }

Mit

curl --no-progress-meter http://192.168.0.153/api/livedata/status | jq '.total | .Power.v'

erhalte ich die momentan gelieferte Leistung beider WR zusammen.

Ich hätte aber gerne die Leistungen beider Wechselrichter getrennt.

Mit

curl --no-progress-meter http://192.168.0.153/api/livedata/status?inv=114190651346 | jq

bekomme ich genau die selbe lange Liste. Die Doku zur WEB-api habe ich zwar gelesen, verstehe aber trotzdem nicht, wie ich an den Wert

1
  "AC": {
2
    "0": {
3
      "Power": {
4
        "v": 323.7999878

des Wechselrichters 114190651346 komme. Ich möchte die momentane Leistung (also hier 323.7999878) in eine Variable schreiben. Kann mir da bitte jemand weiterhelfen?

Oh, ich sehe gerade in der Vorschau, dass die Formatierung der Liste verloren gegangen ist. Ich weiß auch nicht, wie ich das verhindern kann.

#7699132
Lesenswert?

Na ja, ich hätte mir ja eigentlich denken können, dass ich mich zu früh gefreut habe. Das mit "curl" funktioniert wunderbar auf der Befehlszeile, ich erhalte den richtigen Wert. Aber diesen Wert möchte ich ja in einem Python-Script einer Variablen zuweisen, und Python kann mit "curl" wohl nichts anfangen. Nach etwas Stöbern bin ich auf die requests-library gestoßen, und habe folgendes probiert:

1
#! /usr/bin/env python3
2

3
import requests
4

5
r = requests.get(f"http://192.168.0.153/api/livedata/status")
6

7
print(r.content)

Hiermit erhalte ich diese lange Liste, die aber auch enthält, was ich suche:


1
b'{"inverters":[{"serial":"114190651346","name":"WR-1","order":0,"data_age":1,"poll_enabled":true,"reachable":true,"producing":true,"limit_relative":100,"limit_absolute":800,"AC":{"0":{"Power":{"v":453.6000061,"u":"W","d":1},"Voltage":{"v":229.3999939,"u":"V","d":1},"Current":{"v":1.980000019,"u":"A","d":2},"Power DC":{"v":476.5,"u":"W","d":1},"YieldDay":{"v":990,"u":"Wh","d":0},"YieldTotal":{"v":358.7929993,"u":"kWh","d":3},"Frequency":{"v":49.97999954,"u":"Hz","d":2},"PowerFactor":{"v":1,"u":"","d":3},"ReactivePower":{"v":0,"u":"var","d":1},"Efficiency":{"v":95.19412231,"u":"%","d":3}}},"DC":{"0":{"name":{"u":"West"},"Power":{"v":221.1000061,"u":"W","d":1},"Voltage":{"v":25.70000076,"u":"V","d":1},"Current":{"v":8.609999657,"u":"A","d":2},"YieldDay":{"v":473,"u":"Wh","d":0},"YieldTotal":{"v":170.3939972,"u":"kWh","d":3},"Irradiation":{"v":48.59340668,"u":"%","d":3,"max":455}},"1":{"name":{"u":"Mitte"},"Power":{"v":255.3999939,"u":"W","d":1},"Voltage":{"v":27.79999924,"u":"V","d":1},"Current":{"v":9.180000305,"u":"A","d":2},"YieldDay":{"v":517,"u":"Wh","d":0},"YieldTotal":{"v":188.3990021,"u":"kWh","d":3},"Irradiation":{"v":56.13187027,"u":"%","d":3,"max":455}}},"INV":{"0":{"Temperature":{"v":48.90000153,"u":"\xc2\xb0C","d":1}}},"events":3},{"serial":"114190138728","name":"WR-2","order":1,"data_age":2,"poll_enabled":true,"reachable":true,"producing":true,"limit_relative":100,"limit_absolute":800,"AC":{"0":{"Power":{"v":352.2000122,"u":"W","d":1},"Voltage":{"v":230.3999939,"u":"V","d":1},"Current":{"v":1.529999971,"u":"A","d":2},"Power DC":{"v":370,"u":"W","d":1},"YieldDay":{"v":640,"u":"Wh","d":0},"YieldTotal":{"v":260.0679932,"u":"kWh","d":3},"Frequency":{"v":49.97999954,"u":"Hz","d":2},"PowerFactor":{"v":1,"u":"","d":3},"ReactivePower":{"v":0.300000012,"u":"var","d":1},"Efficiency":{"v":95.18919373,"u":"%","d":3}}},"DC":{"0":{"name":{"u":"Balkon"},"Power":{"v":116.4000015,"u":"W","d":1},"Voltage":{"v":31.79999924,"u":"V","d":1},"Current":{"v":3.660000086,"u":"A","d":2},"YieldDay":{"v":128,"u":"Wh","d":0},"YieldTotal":{"v":67.64900208,"u":"kWh","d":3},"Irradiation":{"v":58.20000076,"u":"%","d":3,"max":200}},"1":{"name":{"u":"Ost"},"Power":{"v":253.6000061,"u":"W","d":1},"Voltage":{"v":27.70000076,"u":"V","d":1},"Current":{"v":9.170000076,"u":"A","d":2},"YieldDay":{"v":512,"u":"Wh","d":0},"YieldTotal":{"v":192.4190063,"u":"kWh","d":3},"Irradiation":{"v":55.73626709,"u":"%","d":3,"max":455}}},"INV":{"0":{"Temperature":{"v":43.29999924,"u":"\xc2\xb0C","d":1}}},"events":1}],"total":{"Power":{"v":805.8000488,"u":"W","d":1},"YieldDay":{"v":1630,"u":"Wh","d":0},"YieldTotal":{"v":618.8609619,"u":"kWh","d":3}},"hints":{"time_sync":false,"radio_problem":false,"default_password":true}}'

Sieht ja schon mal gut aus. ich brauche aus der Zeile

"AC":{"0":{"Power":{"v":453.6000061,"u":"W","d":1}

also diesen Wert 453.6. Dann habe ich (analog zur curl-Zeile) folgendes versucht:

1
r = requests.get(f"http://192.168.0.153/api/livedata/status").json()['.inverters[0].AC."0".Power.v']

bekomme aber damit den Fehler:

1
KeyError: '.inverters[0].AC."0".Power.v'

Natürlich habe ich in die requests Doku geschaut, aber auch hier wird ein Grundwissen vorausgesetzt, das ich einfach nicht habe. Ich kann {},[],(),:,' nicht richtig interpretieren. Ich sehe zwar, dass ein Fehler aufgetreten ist, aber ich weiß nicht, wie ich ihn vermeiden kann. Vermutlich ist das ganz einfach, man muss nur wissen, wie.

Wie lautet die alte Weisheit?:

1
Wissen ist Macht!
2
Weißt' nix?
3
Macht nix!
4
Frag halt!

Das mache ich dann hiermit. Kann mir jemand den richtigen Tip geben?

#7699196
Lesenswert?

@Uwe L.

Nö,

1
TypeError: list indices must be integers or slices, not str

Lasse ich bei der ersten 0 die Hochkommata weg:

1
AttributeError: 'float' object has no attribute 'status_code'

Also mache ich die Hochkommas da wieder hin und entferne sie bei der zweiten 0.

1
TypeError: list indices must be integers or slices, not str

Mache ich sie bei beiden weg:

1
KeyError: 0

???

#7699219
Lesenswert?

gerade online (https://www.online-python.com/kM5vqwXzlA) ausprobiert:

import json x = json.loads(b'{"inverters":[{"serial":"114190651346","name":"WR-1","order":0,"data_age":1,"poll_enabled":true,"reachable":true,"producing":true,"limit_relative":100,"limit_absolute":800,"AC":{"0":{"Power":{"v":453.6000061,"u":"W","d":1},"Voltage":{"v":229.3999939,"u":"V","d":1},"Current":{"v":1.980000019,"u":"A","d":2},"Power DC":{"v":476.5,"u":"W","d":1},"YieldDay":{"v":990,"u":"Wh","d":0},"YieldTotal":{"v":358.7929993,"u":"kWh","d":3},"Frequency":{"v":49.97999954,"u":"Hz","d":2},"PowerFactor":{"v":1,"u":"","d":3},"ReactivePower":{"v":0,"u":"var","d":1},"Efficiency":{"v":95.19412231,"u":"%","d":3}}},"DC":{"0":{"name":{"u":"West"},"Power":{"v":221.1000061,"u":"W","d":1},"Voltage":{"v":25.70000076,"u":"V","d":1},"Current":{"v":8.609999657,"u":"A","d":2},"YieldDay":{"v":473,"u":"Wh","d":0},"YieldTotal":{"v":170.3939972,"u":"kWh","d":3},"Irradiation":{"v":48.59340668,"u":"%","d":3,"max":455}},"1":{"name":{"u":"Mitte"},"Power":{"v":255.3999939,"u":"W","d":1},"Voltage":{"v":27.79999924,"u":"V","d":1},"Current":{"v":9.180000305,"u":"A","d":2},"YieldDay":{"v":517,"u":"Wh","d":0},"YieldTotal":{"v":188.3990021,"u":"kWh","d":3},"Irradiation":{"v":56.13187027,"u":"%","d":3,"max":455}}},"INV":{"0":{"Temperature":{"v":48.90000153,"u":"\xc2\xb0C","d":1}}},"events":3},{"serial":"114190138728","name":"WR-2","order":1,"data_age":2,"poll_enabled":true,"reachable":true,"producing":true,"limit_relative":100,"limit_absolute":800,"AC":{"0":{"Power":{"v":352.2000122,"u":"W","d":1},"Voltage":{"v":230.3999939,"u":"V","d":1},"Current":{"v":1.529999971,"u":"A","d":2},"Power DC":{"v":370,"u":"W","d":1},"YieldDay":{"v":640,"u":"Wh","d":0},"YieldTotal":{"v":260.0679932,"u":"kWh","d":3},"Frequency":{"v":49.97999954,"u":"Hz","d":2},"PowerFactor":{"v":1,"u":"","d":3},"ReactivePower":{"v":0.300000012,"u":"var","d":1},"Efficiency":{"v":95.18919373,"u":"%","d":3}}},"DC":{"0":{"name":{"u":"Balkon"},"Power":{"v":116.4000015,"u":"W","d":1},"Voltage":{"v":31.79999924,"u":"V","d":1},"Current":{"v":3.660000086,"u":"A","d":2},"YieldDay":{"v":128,"u":"Wh","d":0},"YieldTotal":{"v":67.64900208,"u":"kWh","d":3},"Irradiation":{"v":58.20000076,"u":"%","d":3,"max":200}},"1":{"name":{"u":"Ost"},"Power":{"v":253.6000061,"u":"W","d":1},"Voltage":{"v":27.70000076,"u":"V","d":1},"Current":{"v":9.170000076,"u":"A","d":2},"YieldDay":{"v":512,"u":"Wh","d":0},"YieldTotal":{"v":192.4190063,"u":"kWh","d":3},"Irradiation":{"v":55.73626709,"u":"%","d":3,"max":455}}},"INV":{"0":{"Temperature":{"v":43.29999924,"u":"\xc2\xb0C","d":1}}},"events":1}],"total":{"Power":{"v":805.8000488,"u":"W","d":1},"YieldDay":{"v":1630,"u":"Wh","d":0},"YieldTotal":{"v":618.8609619,"u":"kWh","d":3}},"hints":{"time_sync":false,"radio_problem":false,"default_password":true}}') print(x['inverters'][0]['AC']['0']['Power']['v'])

gibt aus: 453.60000 ....

#7699278
Lesenswert?

@Uwe L.

Ja, das war's, das geht bei mir jetzt auch. Der Knackpunkt war wohl das fehlende "import json" und die "json.loads" Anweisung.

Merkwürdig finde ich allerdings, dass ich im gleichen Script schon auf zwei unterschiedliche shellys zugreife (ein- und dreiphasiger Leistungsmesser). Auch hier benutze ich die requests-library und json, und das funktioniert, ohne dass ich explizit json importieren musste.

Nur zur Info: den einphasigen shelly lese ich so aus:

1
sh_1=requests.get(f'http://ipaddr/rpc/PM1.GetStatus?id=0').json()["apower"]

und den dreiphasigen so:

1
sh_3=requests.get(f'http://ipaddr/rpc/EM.GetStatus?id=0').json()["total_act_power"]

Die entsprechenden Zeilen habe ich irgendwo im Netz gefunden, alleine wäre ich da nie drauf gekommen. Diese Zeilen habe ich mir zum Vorbild genommen, um auch auf den Wechselrichter (über OpenDTU) zuzugreifen. Aber das war wohl nichts.

Dir ganz herzlichen Dank, jetzt kann ich endlich weiterbasteln, das nächste Problem wartet schon auf mich (und die mikrocontroller-Gemeinde).

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren