Zugriff auf FriztBox SmartHome Components mit microPython (pico2W)
Verfasst: Montag 1. September 2025, 18:03
Man benötigt dazu eine SessionID, die nicht trivial zu bekommen ist. Hier ein Beispiel:
menencodeUTF19_LE.py:
# the Py3 code uses an edcoding which does not produce an error in microPython - but - gives a totally different and unuseful result
def enc0(char): # first character
return bytes(str(char), 'ascii')
def enc(char): # following characters
string="\x00"+char
return bytes(string, 'ascii')
def mencodeUTF16_LE(hexString: str) -> bytes:
encoded=bytes()
encoded+=enc0(hexString[0])
i=1
while i<len(hexString):
encoded+=enc(hexString)
i+=1 # why is there no i++?
encoded+=b'\x00' # termination
return encoded
def to_hex(b: bytes) -> str: # helper
ret=''.join('{:02x}'.format(x) for x in b)
return ret
fritzactors_sample.py:
# Controlling Fritz!Box smarthome components requires obtaining a sessonID according to protocol AVM TR-064.
# If done in Python3 there is a very elegant solution on Git: Tugzrida/fritzsid.py.
# Unfortunately this does not work in microPython for several reasons.
# This is a solution including a sample component access
from md5lib import md5
from mencodeUTF16_LE import * # code is below
import requests
import network
import time
# WIFI configuration
# your SSID
wlSsid = 'xxxx' # to be replaced
# your PW
wlPw = 'yyyy' # likewise
# WIFI connection
wlan = network.WLAN(network.STA_IF)
if not wlan.isconnected():
print('Connecting...')
wlan.active(True)
wlan.connect(wlSsid, wlPw)
for i in range(10):
if wlan.status() < 0 or wlan.status() >= 3:
break
print('->', wlan.status())
time.sleep(0.5)
if wlan.isconnected():
print('Connection OK')
else:
print('No connection')
print('WIFI-Status:', wlan.status())
def actors(act): # to address multiple actors/sensors
# we assume microPython sytem is in local network, otherwise see original post
response = requests.get("http://192.168.178.1/login_sid.lua")
response_content = response.content.decode('utf-8')
ia=response_content.index("nge>")
ie=response_content.index("</Cha")
challenge=response_content[ia+4:ie]
#print(challenge)
password="zzzz" # PW for user uuuu in line 51
tmp="{}-{}".format(challenge, password)
#print(tmp)
tmp2=mencodeUTF16_LE(tmp)
h = md5()
h.update(tmp2)
hash = (h.digest())
hash = to_hex(has)
username="uuuu" # FritzBox user for this specific application
respons = "{}-{}".format(challenge, hash)
response = requests.get("http://192.168.178.1/login_sid.lua?user ... {}".format(username, respons))
response_content = response.content.decode('utf-8')
ia=response_content.index("SID>")
SID=response_content[ia+4:ia+20]
#print(SID) - we've got it
if act==x: # example to get a power value from an actor with ain <ain>, e.g. a Fritz!SmartEnergy device
# for more details see AHA-HTTP-Interface document by AVM
resp=requests.get("http://192.168.178.1/webservices/homeau ... ormat(SID))
response_content = resp.content.decode('utf-8')
if resp.status_code==200: # means OK
resp1=requests.get("http://192.168.178.1/?sid={}&security:c ... SID,"dmy")) # better logout
return(float(response_content)/1000) # power in watts
else:
return -1
menencodeUTF19_LE.py:
# the Py3 code uses an edcoding which does not produce an error in microPython - but - gives a totally different and unuseful result
def enc0(char): # first character
return bytes(str(char), 'ascii')
def enc(char): # following characters
string="\x00"+char
return bytes(string, 'ascii')
def mencodeUTF16_LE(hexString: str) -> bytes:
encoded=bytes()
encoded+=enc0(hexString[0])
i=1
while i<len(hexString):
encoded+=enc(hexString)
i+=1 # why is there no i++?
encoded+=b'\x00' # termination
return encoded
def to_hex(b: bytes) -> str: # helper
ret=''.join('{:02x}'.format(x) for x in b)
return ret
fritzactors_sample.py:
# Controlling Fritz!Box smarthome components requires obtaining a sessonID according to protocol AVM TR-064.
# If done in Python3 there is a very elegant solution on Git: Tugzrida/fritzsid.py.
# Unfortunately this does not work in microPython for several reasons.
# This is a solution including a sample component access
from md5lib import md5
from mencodeUTF16_LE import * # code is below
import requests
import network
import time
# WIFI configuration
# your SSID
wlSsid = 'xxxx' # to be replaced
# your PW
wlPw = 'yyyy' # likewise
# WIFI connection
wlan = network.WLAN(network.STA_IF)
if not wlan.isconnected():
print('Connecting...')
wlan.active(True)
wlan.connect(wlSsid, wlPw)
for i in range(10):
if wlan.status() < 0 or wlan.status() >= 3:
break
print('->', wlan.status())
time.sleep(0.5)
if wlan.isconnected():
print('Connection OK')
else:
print('No connection')
print('WIFI-Status:', wlan.status())
def actors(act): # to address multiple actors/sensors
# we assume microPython sytem is in local network, otherwise see original post
response = requests.get("http://192.168.178.1/login_sid.lua")
response_content = response.content.decode('utf-8')
ia=response_content.index("nge>")
ie=response_content.index("</Cha")
challenge=response_content[ia+4:ie]
#print(challenge)
password="zzzz" # PW for user uuuu in line 51
tmp="{}-{}".format(challenge, password)
#print(tmp)
tmp2=mencodeUTF16_LE(tmp)
h = md5()
h.update(tmp2)
hash = (h.digest())
hash = to_hex(has)
username="uuuu" # FritzBox user for this specific application
respons = "{}-{}".format(challenge, hash)
response = requests.get("http://192.168.178.1/login_sid.lua?user ... {}".format(username, respons))
response_content = response.content.decode('utf-8')
ia=response_content.index("SID>")
SID=response_content[ia+4:ia+20]
#print(SID) - we've got it
if act==x: # example to get a power value from an actor with ain <ain>, e.g. a Fritz!SmartEnergy device
# for more details see AHA-HTTP-Interface document by AVM
resp=requests.get("http://192.168.178.1/webservices/homeau ... ormat(SID))
response_content = resp.content.decode('utf-8')
if resp.status_code==200: # means OK
resp1=requests.get("http://192.168.178.1/?sid={}&security:c ... SID,"dmy")) # better logout
return(float(response_content)/1000) # power in watts
else:
return -1