Forum: Haus & Smart Home Shelly 3EM pro. Leistung über http beziehen.


von Hadmut F. (hadmut)


Lesenswert?

Zwei varianten. RPC und skript.

Mit RPC:
anfrage:
http://192.168.178.26/rpc/EM.GetStatus?id=0
antwort:
{"id":0,"a_current":0.030,"a_voltage":0.1,"a_act_power":-0.0,"a_aprt_pow 
er":0.0,"a_pf":1.00,"b_current":0.027,"b_voltage":0.1,"b_act_power":0.0, 
"b_aprt_power":0.0,"b_pf":1.00,"c_current":0.028,"c_voltage":237.5,"c_ac 
t_power":0.1,"c_aprt_power":6.7,"c_pf":1.00,"n_current":null,"total_curr 
ent":0.085,"total_act_power":0.084,"total_aprt_power":6.679}

Mit skript:
anfrage:
http://192.168.178.30/script/1/pwr
antwort:
PWR: -0.219000

Skript dazu:
function GetPwr(request, response)
 {
   //print('Executing function open');
   let EMpower = Shelly.getComponentStatus("em:0");
   response.body = "PWR: " + JSON.stringify(EMpower.total_act_power);
   response.code = 200;
   response.send();
 }

 HTTPServer.registerEndpoint('pwr', GetPwr)

 // http://192.168.178.26/script/1/pwr

Ich hab dafür stunden gebraucht! Die doku ist katastrophal.
Ziel war möglichst wenig WiFi traffic für sekunden-abfrage.

: Bearbeitet durch User
von Alexander (alecxs)


Lesenswert?

Auf mein erstes Shell Skript war ich auch so stolz dass ich einen neuen 
Thread eröffnet habe. Interessiert hat es keinen. Zu 
Dokumentationszwecken für Dich selbst nutze bitte gitlab oder github.

von Hadmut F. (hadmut)


Lesenswert?

Was hast du denn gescripted?

von Mathias M. (atuditu)


Lesenswert?

Hallo,
ja, genau das will ich auch: Shelly 3EM pro. Leistung über http 
beziehen.
Ich bin auch auf die gleiche Lösung gekommen wie der TO:
1
http://192.168.0.151/rpc/EM.GetStatus?id=0
Wenn ich das in meinen Browser eingebe, bekomme ich auch die 
entsprechende Liste als Antwort.

Ich möchte aber innerhalb eines Python-Scripts auf die einzelnen Werte 
zugreifen, und komme da nicht weiter. Ich brauche die momentane 
Gesamtleistung um damit weiter zu rechnen.

Die Doku für den Pro 3EM verwirrt mich mehr, als dass sie mir hilft. 
Kann mir da jemand weiterhelfen?

Vielen Dank,
atuditu

von Cyblord -. (cyblord)


Lesenswert?

Mathias M. schrieb:
> Wenn ich das in meinen Browser eingebe, bekomme ich auch die
> entsprechende Liste als Antwort.
>
> Ich möchte aber innerhalb eines Python-Scripts auf die einzelnen Werte
> zugreifen

Den JSON String muss man halt parsen. Hat mit Shelly wenig zu tun. Eher 
so die ganz grundlegenden Basics der SW Entwicklung.

von Hadmut F. (hadmut)


Lesenswert?

Cyblord -. schrieb:
> Den JSON String muss man halt parsen.

Ja.
Du kannst das im shelly parsen und nur den interessanten wert 
übertragen, oder du kannst das ganze json garbage übertragen und das im 
client parsen.

Wie man das im shelly parst hab ich oben gezeigt.

: Bearbeitet durch User
von Cyblord -. (cyblord)


Lesenswert?

Hadmut F. schrieb:
> Ja.
> Du kannst das im shelly parsen und nur den interessanten wert
> übertragen, oder du kannst das ganze json garbage übertragen und das im
> client parsen.

Ja nun, wenn man sowieso am Ende Python verwenden will, dann lässt man 
das JSON dort parsen.

von Karl-Heinz P. (karlheinz_p)


Lesenswert?

Hallo Mathias.
Du wirst es inzwischen wahrscheinlich herausgefunden haben.
Ich wäre an der Lösung interessiert.
Die Antwort mit dem Parsen scheint mir sowieso nicht die richtige 
gewesen zu sein.
Ich stehe vor einem ähnlichen Problem:
-Sicher funktioniert die Anfrage über den Browser.
-Ich möchte die Anfrage aber aus einem Shelly Script heraus stellen.
-mit
let sta=Shelly.call("http.get", 
"http://10.0.0.16/rpc/EM.GetStatus?id=0";);
bekomme ich aber immer nur Null als Antwort.

????

von Karl-Heinz P. (karlheinz_p)


Lesenswert?

So fast selbst gelöst (hab mir Hilfe bei ChatGPT geholt - hat aber auch 
nicht funktioniert!):
Hier die Lösung, damit es sonst jemandem helfen kann:

function getShelly3EMPower() {
    let shelly3EM_IP = "10.0.0.16";
    let url = "http://"; + shelly3EM_IP + "/rpc/EM.GetStatus?id=0";

    Shelly.call("HTTP.GET", {url: url}, function(result, error_code, 
error_message) {
        if (error_code === 0 && result) {
            let data = JSON.parse(result.body);
            let totalPower = data.total_act_power;
            print("Total Actual Power:", totalPower, "W");
        } else {
            print("Error fetching data:", error_message);
        }
    });
}

...so recht ist mir aber nicht klar, wo sich dieser Code von meinem 
unterscheidet - scheinbar lässt sich Ergebnis nicht direkt zuweisen?
Naja, ich werde weiter in meinem Java Buch lesen und hoffe, dass es mir 
etwas weiterhilft, obwohl ich bezweifle ob dies an Java oder eher an 
Shelly liegt!?

von Mathias M. (atuditu)


Lesenswert?

Hallo Karl-Heinz,
Sorry, dass ich mich erst so spät melde; ich hatte diesen Thread schon 
aus den Augen verloren.

Bei mir geht das mit zwei Shelly 3EM so:


    try:
        power_1 = 
requests.get(f'http://{192.168.0.151}/rpc/EM.GetStatus?id=0',headers={'Content-Type':'application/json'}).json()['total_act_power';]
        power_2 = 
requests.get(f'http://{192.168.0.152}/rpc/EM.GetStatus?id=0',headers={'Content-Type':'application/json'}).json()['total_act_power';]


    except:
        print('Fehler beim Abrufen der Daten von Shelly 3EM')

von Mathias M. (atuditu)


Lesenswert?

Oh, die Formatierung ist leider verloren gegangen:
Alles was hinter 'power_1' bzw. 'power_2' steht, ist in einer Zeile.

LG, Mathias

von Ein T. (ein_typ)


Lesenswert?

Mathias M. schrieb:
>     try:
>         power_1 =
> 
requests.get(f'http://{192.168.0.151}/rpc/EM.GetStatus?id=0',headers={'Content-Type':'application/json'}).json()['total_act_power';]
>         power_2 =
> 
requests.get(f'http://{192.168.0.152}/rpc/EM.GetStatus?id=0',headers={'Content-Type':'application/json'}).json()['total_act_power';]
>
>
>     except:
>         print('Fehler beim Abrufen der Daten von Shelly 3EM')

Dein Code benutzt zwar F-Strings, aber die Variablennamen 
(192.168.0.15[12]) sind ungültig. In diesem Fall kannst Du Dir die 
geschweiften Klammern ebenso sparen wie das "f".

Direkte Schlüsselzugriffe wie hier auf 'total_act_power' am Ende eines 
oder gar mehrerer Befehle... Wie wäre es eine Abfrage mit 
".get('total_act_power', None)" mit Prüfung auf "None"?

Besonders häßlich finde ich allerdings, daß Du den Informationsgehalt 
aller Exceptions wegwirfst und stattdessen eine völlig nichtssagende 
Fehlermeldung ausgibt. Völlig gleichgültig, ob der Request fehlschlägt, 
weil der Host nicht erreichbar war, der Host einen unerwarteten 
HTTP-Statuscode zurückgegeben hat, ob sich der Body der Response nicht 
als JSON parsen ließ oder Du nicht auf den Schlüssel 'total_act_power' 
zugreifen konntest, die Fehlermeldung ist immer dieselbe: 'Fehler beim 
Abrufen der Daten von Shelly 3EM'...

... und so ganz grundsätzlich würde ich bei jeder Art von 
Netzwerkverbindung niemals ohne Timeout arbeiten. ;-)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.