Erste Fassung
This commit is contained in:
commit
dba0ef4a4e
29
README.md
Normal file
29
README.md
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# fritz_temperatur
|
||||||
|
|
||||||
|
## Allgemein
|
||||||
|
|
||||||
|
Dieses Script fragt die Temperatur eines an die FritzBox angeschlossenen Sensors ab.
|
||||||
|
|
||||||
|
Getestet wurde es mit einer FritzBox 7390 mit FritzOS 6.83 und einem Comet DECT-Heizkörperregler.
|
||||||
|
|
||||||
|
Das Script benötigt folgende Parameter:
|
||||||
|
|
||||||
|
-H Hostname oder IP der FritzBox
|
||||||
|
-U Benutzername zum Einloggen an der FritzBox (z.B. administrator)
|
||||||
|
-P Das Paßwort des eben genannten Benutzers
|
||||||
|
-A Die ID des Sensors.
|
||||||
|
|
||||||
|
Die Sensor-ID kann man über die Web-Oberfläche der FritzBox abfragen:
|
||||||
|
- Menü Heimnetz => Smart Home
|
||||||
|
- Beim gewünschten Sensor auf "Bearbeiten" (Stift-Symbol) klicken
|
||||||
|
- Die "Identifikationsnummer" ist die benötigte ID. Leerzeichen aus der ID entfernen.
|
||||||
|
|
||||||
|
## Voraussetzungen
|
||||||
|
|
||||||
|
Das Script ist in Python3 geschrieben und benötigt die folgenden Debian-Pakete:
|
||||||
|
|
||||||
|
* python3
|
||||||
|
* python3-urllib
|
||||||
|
|
||||||
|
Getestet wurde mit Debian 8 (Jessie).
|
||||||
|
|
127
fritz_temp
Executable file
127
fritz_temp
Executable file
@ -0,0 +1,127 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
# get target temperature from AVM/Comet Dect Heizkoerperregler (Heating Device)
|
||||||
|
# need Fritz!OS 6.50+
|
||||||
|
|
||||||
|
import getopt
|
||||||
|
import re
|
||||||
|
import requests
|
||||||
|
import sys
|
||||||
|
import xml.etree.ElementTree as etree
|
||||||
|
import urllib.parse
|
||||||
|
from hashlib import md5
|
||||||
|
|
||||||
|
DEBUG=False
|
||||||
|
|
||||||
|
def OK(text):
|
||||||
|
print("OK: " + text)
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
def Warning(text):
|
||||||
|
print("WARNING: " + text)
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
def Critical(text):
|
||||||
|
print("CRITICAL: " + text)
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
def OptionsError():
|
||||||
|
Critical("Error: not all required options are given.\n -H <hostname>\n -U <username>\n -P <password>\n -A <ID of device>")
|
||||||
|
|
||||||
|
def debug(text):
|
||||||
|
if DEBUG == True:
|
||||||
|
print("DEBUG: " + text)
|
||||||
|
|
||||||
|
def get_sid(loginurl, username, password):
|
||||||
|
if not username:
|
||||||
|
username=''
|
||||||
|
|
||||||
|
# get challenge string
|
||||||
|
response = requests.get(loginurl)
|
||||||
|
|
||||||
|
if response.status_code == 200:
|
||||||
|
tree = etree.fromstring(response.content)
|
||||||
|
challenge = tree.find("Challenge").text
|
||||||
|
sid = tree.find("SID").text
|
||||||
|
debug("challenge: " + challenge)
|
||||||
|
debug("sid: " + sid)
|
||||||
|
else:
|
||||||
|
Critical("Error: GetSid failed")
|
||||||
|
|
||||||
|
if len(sid) > 0 and re.search("^0+$", sid) and challenge:
|
||||||
|
debug("Get new SID")
|
||||||
|
# sid is null, got challenge
|
||||||
|
sid = ""
|
||||||
|
# build password response
|
||||||
|
pwd = challenge + "-" + password
|
||||||
|
# UTF-16LE encoding as required
|
||||||
|
pwd = pwd.encode("UTF-16LE")
|
||||||
|
# md5hash on top
|
||||||
|
m = md5()
|
||||||
|
m.update(pwd)
|
||||||
|
# final answer string
|
||||||
|
challenge_response = challenge + "-" + m.hexdigest()
|
||||||
|
debug("challenge_response: " + challenge_response)
|
||||||
|
# send to box
|
||||||
|
url = loginurl + "?username=" + username + "&response=" + challenge_response
|
||||||
|
response = requests.get(url)
|
||||||
|
#print(response.content)
|
||||||
|
# check answer
|
||||||
|
tree = etree.fromstring(response.content)
|
||||||
|
sid2 = tree.find("SID").text
|
||||||
|
debug("SID: " + sid2)
|
||||||
|
if (len(sid2) > 0) and not re.search("^0+$", sid2):
|
||||||
|
# is not null, bingo!
|
||||||
|
return sid2
|
||||||
|
else:
|
||||||
|
# use existing sid if sid matches an hex string
|
||||||
|
if (len(sid) > 0) and re.search("^[0-9a-f]+$", sid):
|
||||||
|
return sid
|
||||||
|
|
||||||
|
host = None
|
||||||
|
username = None
|
||||||
|
password = None
|
||||||
|
ain = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
opts, args = getopt.gnu_getopt(sys.argv[1:], 'H:U:P:A:')
|
||||||
|
except getopt.GetoptError as err:
|
||||||
|
OptionsError()
|
||||||
|
|
||||||
|
for opt, arg in opts:
|
||||||
|
if opt == "-H":
|
||||||
|
host = arg
|
||||||
|
elif opt == "-U":
|
||||||
|
username = arg
|
||||||
|
elif opt == "-P":
|
||||||
|
password = arg
|
||||||
|
elif opt == "-A":
|
||||||
|
ain = arg
|
||||||
|
|
||||||
|
if not host or not username or not password or not ain:
|
||||||
|
OptionsError()
|
||||||
|
|
||||||
|
# build urls and login
|
||||||
|
# - login_sid.lua for fritzos 5.50+
|
||||||
|
loginurl = "http://" + host + "/login_sid.lua"
|
||||||
|
ahaurl = "http://" + host + "/webservices/homeautoswitch.lua"
|
||||||
|
sid = get_sid(loginurl, username, password);
|
||||||
|
if not sid:
|
||||||
|
Critical("Error: Login invalid or failed")
|
||||||
|
|
||||||
|
#query actual state
|
||||||
|
rain = urllib.parse.quote(ain)
|
||||||
|
url = ahaurl + '?ain=' + rain + '&sid=' + sid + '&switchcmd=gettemperature';
|
||||||
|
|
||||||
|
http_response = requests.get(url)
|
||||||
|
|
||||||
|
if http_response.status_code == 200:
|
||||||
|
# check answer
|
||||||
|
answer = http_response.content.decode().strip()
|
||||||
|
debug("Antwort: " + answer)
|
||||||
|
temperatur = float(answer) / 10
|
||||||
|
temp_str = "{0:<3.1f}".format(temperatur)
|
||||||
|
OK("Temperatur: " + temp_str + " | temp=" + temp_str)
|
||||||
|
else:
|
||||||
|
Critical("Error: Query failed.")
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user