FritzBox API mit ESP32
So werden DECT!200 und andere Smart Home Geräte über Arduino und FritzBox API mit ESP32 gesteuert
Die FritzBox bietet eine Schnittstelle, mit der man diverse Daten auslesen bzw. steuern kann. So lassen sich zum Beispiel Anruflisten und Netzwerkdaten auslesen, oder auch die AVM eigenen SmartHome Geräte steuern.
FritzBox einrichten
Zunächst muss ein Benutzer auf der FritzBox mit entsprechenden Rechten eingerichtet werden. Dazu müssen wir im Webinterface unter System/FRITZ!Box-Benutzer einen Benutzer erstellen bzw. die Rechte zuweisen. Zum Testen am besten die Haken für „Fritz!Box Einstellungen“, „Sprachnachrichten, Faxnachrichten…“ und „Smart Home“ setzen. Benutzername und Passwort für diesen Nutzer brauchen wir später im Arduino Sketch.
Zum Steuern einer FritzDect200 Steckdose benötigen wir noch dessen AIN (Aktor Identifikationsnummer). Diese finden wir im FritzBox Webinterface unter Smart Home/Geräteverwaltung, wenn wir beim entsprechenden Eintrag auf „Bearbeiten“ klicken.
Arduino
In der Arduino IDE benötigen wir die „TR-064 SOAP Library“, damit uns jegliche Protokollarbeit abgenommen wird. Die Bibliothek lässt sich über den Bibliotheksverwalter einfach finden und installieren.
Jetzt können wir mit diesem kleinen Arduino Sketch loslegen, um eine Steckdose zu schalten. Dazu die oben ermittelten FritzBox Daten und die AIN der FritzDect200 Steckdose eintragen. Der Beispielsketch schaltet die Steckdose über die Kommandos „on“ bzw. „off“ per Terminaleingabe. Wer einen Taster zum Schalten benutzten will, kann auch einen Toggle Befehl senden, dann wird automatisch zwischen an und aus umgeschaltet. Außerdem können mit dem Befehl „info“ Temperatur und Stromverbrauch ausgelesen werden.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
#include <WiFi.h> #include <WiFiMulti.h> #include <HTTPClient.h> WiFiMulti WiFiMulti; #include <tr064.h> //------------------------------------------------------------------------------------- // Put your router settings here //------------------------------------------------------------------------------------- // Wifi network name (SSID) const char* wifi_ssid = "WLAN_SSID"; // Wifi network password const char* wifi_password = "WLAN_PASSWORD"; // The username if you created an account, "admin" otherwise const char* fuser = "FritzBox_User"; // The password for the aforementioned account. const char* fpass = "FritzBox_User_Password"; // IP address of your router. This should be "192.168.179.1" for most FRITZ!Boxes const char* IP = "192.168.179.1"; // Port of the API of your router. This should be 49000 for all TR-064 devices. const int PORT = 49000; // ------------------------------------------------------------------------------------- // TR-064 connection TR064 connection(PORT, IP, fuser, fpass); // Die AIN der DECT!200 Steckdose findet sich im FritzBox Webinterface const String Steckdose1 = "12345 1234567"; void setup() { Serial.begin(115200); Serial.println("boot..."); // Connect to wifi ensureWIFIConnection(); Serial.println("WIFI connected..."); connection.init(); // Bei Problemen kann hier die Debug Ausgabe aktiviert werden //connection.debug_level = DEBUG_VERBOSE; } void loop() { if(Serial.available()) { serialEvent(); } delay(20); } void serialEvent(){ String inData; char inChar; while(Serial.available() > 0) { inChar = Serial.read(); if(inChar != '\n' && inChar != '\r') { inData += inChar; } } if(inData == "on") { SetSwitch(Steckdose1, "ON"); }else if(inData == "off") { SetSwitch(Steckdose1, "OFF"); }else if(inData == "toggle") { SetSwitch(Steckdose1, "TOGGLE"); }else if(inData == "info") { GetDeviceInfo(Steckdose1); } Serial.println(inData); } void SetSwitch(String AIN, String state) { ensureWIFIConnection(); String paramsb[][2] = {{"NewAIN", AIN},{"NewSwitchState", state}}; connection.action("urn:dslforum-org:service:X_AVM-DE_Homeauto:1", "SetSwitch", paramsb, 2); } void GetDeviceInfo(String AIN) { ensureWIFIConnection(); String paramsb[][2] = {{"NewAIN", AIN}}; String reqb[][2] = {{"NewMultimeterPower", ""}, {"NewTemperatureCelsius", ""}}; connection.action("urn:dslforum-org:service:X_AVM-DE_Homeauto:1", "GetSpecificDeviceInfos", paramsb, 1, reqb, 2); float power = reqb[0][1].toInt() / 100.0; float temp = reqb[1][1].toInt() / 10.0; Serial.print("Stromverbrauch: "); Serial.print(power, 1); Serial.println("W"); Serial.print("Temperatur: "); Serial.print(temp, 1); Serial.println("*C"); } void ensureWIFIConnection() { if((WiFiMulti.run() != WL_CONNECTED)) { WiFiMulti.addAP(wifi_ssid, wifi_password); while ((WiFiMulti.run() != WL_CONNECTED)) { delay(100); } } } |
Fazit
Das ganze ist natürlich nur ein Beispiel und soll nur einen einfachen Einblick in die Thematik darstellen. Die FritzBox API ermöglicht nahe zu alles abzufragen und einzustellen was die FritzBox zu bieten hat. Eine genaue Beschreibung über alle Funktionen bietet der Hersteller selbst hier an: https://avm.de/service/schnittstellen. Im Abschnitt zur TR-064 Schnittstelle findet sich zu jeder Kategorie eine PDF. Die Möglichkeiten der Smart Home Geräte ist in folgendem Dokument beschrieben:
https://avm.de/fileadmin/user_upload/Global/Service/Schnittstellen/x_homeauto.pdf
Mit der FritzBox API und dem ESP32 lassen sich also sehr schnell kleine Smart Home Gadgets entwickeln.
Eine eigenen Abfrage erstellen
Die größten Schwierigkeiten treten wahrscheinlich dabei auf, die nötigen Daten für eine Abfrage zusammenzustellen. Hierfür müssen wir uns in der avm Dokumentation als erstes den richtigen Service heraussuchen. Einen Überblick über alle Möglichkeiten erhält man am besten in diesem Dokument:
https://avm.de/fileadmin/user_upload/Global/Service/Schnittstellen/AVM_TR-064_first_steps.pdf
Für jeden Service gibt es dann, wie oben beschrieben, ein separates Dokument, in dem die einzelnen Funktionen beschrieben sind. Als nächstes benötigen wir die Ressource. Der Teil ist etwas verwirrend, weil diese nicht im beschreibenden Dokument steht. Im Beispiel für den Smart Home Service steht ganz oben in der Dokumentation die Service ID „urn:X_AVM-DE_Homeauto-com:serviceId:X_AVM-DE_Homeauto1“. Diese suchen wir dann in der Schnittstellenbeschreibung http://fritz.box:49000/tr64desc.xml und finden direkt darüber den benötigten Service Type „urn:dslforum-org:service:X_AVM-DE_Homeauto:1“. Hiermit starten wir den Aufbau eines Requests.
1 2 3 4 5 |
String paramsb[][2] = {{"NewAIN", AIN}}; String reqb[][2] = {{"NewMultimeterPower", ""}, {"NewTemperatureCelsius", ""}}; connection.action("urn:dslforum-org:service:X_AVM-DE_Homeauto:1", "GetSpecificDeviceInfos", paramsb, 1, reqb, 2); //connection.action(Ressource, Action, Eingabeparameter, Anzahl Eingabeparameter, Rückgabewerte, Anzahl Rückgabewerte) |
Das Ausführen eines Requests wird durch folgende Parameter beschrieben:
Ressource: Der wie oben ermittelte Service Type
Action: Der Funktionsname, der aufgerufen wird
Eingabeparameter: Werte die der Funktion übermittelt werden (Nicht alle Funktionen benötigen Eingabeparameter)
Anzahl Eingabeparameter: Die Anzahl der übergebenen Parameter. In diesem Fall ist {„NewAIN“, AIN} ein Parameter.
Rückabeparameter: Ein Aufruf kann eine ganze Menge Werte zurückliefern. Hier werden nur die Parameter eingetragen die als Rückgabe erwünscht sind. (Nicht alle Funktionen liefern Werte zurück)
Anzahl Rückgabeparameter: In diesem Beispiel sind {„NewMultimeterPower“, „“}, {„NewTemperatureCelsius“, „“} zwei Parameter.
Die Rückgabewerte werden uns automatisch in das Array was wir übergeben haben geschrieben. Das Array reqb[ ][ ] sieht beispielsweise nach dem Abruf der Daten so aus: [[„NewMultimeterPower“, „6513“], [„NewTemperatureCelsius“, „235“]]. Um an die Werte zu kommen, greifen wir wie folgt auf das zweidimensionale Array zu:
pwr = regb[0][1] // Rückgabe des ersten Parameter (6513)
temp = regb[1][1] // Rückgabe des zweiten Parameter (235)
…