Haustechnik, Wert aus Webinterface auslesen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
JayJay_86
User
Beiträge: 8
Registriert: Sonntag 4. September 2022, 06:58

Hallo liebes Forum,

vorab, ich habe mit Python wenig Erfahrung. Meine Programmiererfahrung beschränkt sich auf VBA um in Excel zu optimieren.
Ich habe lediglich ein paar Python Grundlagen, als IDE benutze ich Phycharm. Aber ich bin motiviert zu lernen :D

Mein Ziel ist es, alle 5 Minuten einen Temperaturwert aus meiner Wärmepumpe auszulesen. Diese ist im Netzwerk und hat eine statische IP.

Leider kenne ich mich mit Http Request nicht wirklich aus. Was ich jedoch bereits herausgefunden habe, dass es anscheinend ein 2 stufiger Prozess ist:

1. Anmelden
http://192.168.1.128/cgi/login?username ... waterkotte

2. Wert auslesen
http://192.168.1.128/cgi/readTags?n=1&t1=A19


Anbei mal das Ergebnis des Anmeldebildschirm, wenn ich die URL unter 1. in den Webbrowser eingebe:
1
#S_OK
IDALToken=60121a03d7876c4e011c59fc289a3f50

Die zweite URL liefert folgendes:
#A19 S_OK
192 461
Der Wert den ich auslesen möchte sind die letzten 3 Zahlen, hier muss noch durch 10 dividert werden. In diesem Fall also 46,1 °C.


Bisher habe ich folgenden Code

Code: Alles auswählen

import urllib
from urllib import request

Anmelden = request.urlopen('http://192.168.1.128/cgi/login?username=waterkotte&password=waterkotte')
print(Anmelden.code)
print(Anmelden.read())


Wert_Abfragen = request.urlopen('http://192.168.1.128/cgi/readTags?n=1&t1=A19')
print(Wert_Abfragen.code)
print(Wert_Abfragen.read())
Das Anmelden klappt also und ich kann den Token auch in der Konsole sehen, der zweite Schritt scheitert aber, da ich vermutlich nur mit einer gültigen Anmeldung den Wert auslesen kann.
Im Webbrowser klappt das ganze, da er sich den Login wahrscheinlich merkt.

Das Problem habe ich bereits in einem anderen Forum gefunden, hier wurde aber nicht Python verwendet. Aber vielleicht kann es euch helfen.
https://homematic-forum.de/forum/viewto ... 26&t=42261

Ich sage schonmal vielen Dank für eure Hilfe, und habt Rücksicht, ich bin Anfänger :wink:
imonbln
User
Beiträge: 149
Registriert: Freitag 3. Dezember 2021, 17:07

Wenn ich die andere Webseite richtig überflogen habe, speichert der erste Request ein Cookie, welches der zweite Request übergeben muss, um zu zeigen, dass er authentifiziert ist.

Du kannst also entweder deinen urllib aufrufen, ein CookieJar mitgeben, um so das Cookie vom ersten in den zweiten Aufruf zu übernehmen, oder du benutzt das Module requests und startest dort eine Session. Requests ist zwar ein Modul, welches nicht im Standard Python drin ist, wird aber so oft verwendet, dass es defakto der Standard ist um mit Python Webrequests zu machen.

Probiere mal Folgendes, vielleicht reicht das schon, um dein Problem zu lösen.

Code: Alles auswählen

import requests

with requests.Session() as session:
 	session_token = session.get("http://192.168.1.128/cgi/login?username=waterkotte&password=waterkotte")
        current_settings = session.get("http://192.168.1.128/cgi/readTags?n=1&t1=A19")
JayJay_86
User
Beiträge: 8
Registriert: Sonntag 4. September 2022, 06:58

Hallo imonbln,

perfekt, ich danke dir. Das hat geklappt!
Ich füge nun noch ein bisschen Code hinzu um nur den Wert, also die letzten 3 Zeichen (inkl. Vorzeichen, wenn Minus) auszugeben und poste das Ergebnis hier, damit es ggf. auch anderen Usern hilft!

Vielen Dank und viele Grüße!
Benutzeravatar
__blackjack__
User
Beiträge: 13116
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@JayJay_86: Ich würde da noch den Teil der URL der sich nicht ändert als Konstante heraus ziehen. Und die Parameter nicht fest manuell in die URL kodieren, sondern requests das machen lassen.

Die Namen `session_token` und `current_settings` sind IMHO auch nicht so gut, denn die stehen ja nicht direkt für diese Dinge, sondern für ein `Response`-Objekt das diese Dinge indirekt enthält. Also vielleicht/hoffentlich, denn die Antwort könnte auch eine Fehlermeldung vom Webserver sein, was man besser prüfen sollte, oder zumindest dafür sorgen sollte, dass eine Ausnahme ausgelöst wird, und das Programm nicht einfach weiter macht als wäre alles in Ordnung.

Ungetestet:

Code: Alles auswählen

#!/usr/bin/env python3
import requests

BASE_URL = "http://192.168.1.128/cgi"
USERNAME = PASSWORD = "waterkotte"


def main():
    with requests.Session() as session:
        session.get(
            f"{BASE_URL}/login",
            params={"username": USERNAME, "password": PASSWORD},
        ).raise_for_status()

        response = session.get(
            f"{BASE_URL}/readTags", params={"n": "1", "1": "A19"}
        )
        response.raise_for_status()
        
        _, tab, value_text = response.text.splitlines()[-1].partition("\t")
        if not tab:
            raise ValueError(
                "expected tabulator in last line of response text"
            )
        value = int(value_text) / 10
        print(value)


if __name__ == "__main__":
    main()
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
JayJay_86
User
Beiträge: 8
Registriert: Sonntag 4. September 2022, 06:58

Hallo blackjack,

ich bin sprachlos, Code läuft. An einer Stelle params={"n": "1", "1": "A19"} fehlte ein t. => params={"n": "1", "t1": "A19"}
Aber ohne dass du es testen konntest sowas zu schreiben. Respekt! Hier kann ich noch eine Menge lernen :)

Ich danke euch für eure Unterstützung.

Viele Grüße
JayJay
Antworten