himpler.com himpler.com

Fritzbox, Node-RED und homee

7 Min.

Gäste-WLAN an- und ausschalten, eine Benachrichtigung über eingehende Anrufe oder eine Anwesenheitserkennung. Mit Node-RED und homee lässt sich eine FritzBox noch etwas smarter machen.

UPDATE:
Leider funktioniert das bisher verwendete Plugin node-red-contrib-fritzbox-presence nicht mit FritzOS >= Version 7. Daher wurde die Anleitung mit einer Alternative aktualisiert. Gleichzeitig wurde der Flow zur Benachrichtigung von neuen Anrufern über eine Anrufer Erkennung ergänzt.

Installation

Für diese Funktionen benötigen wir NodeJS und Node-RED. Eine detaillierte Installationsanleitung findest Du im Post Virtuelle Geräte in homee. Außerdem sollte Dein homee mindestens Version 2.15 haben.

Zusätzlich benötigen wir ein Plugin für Node-RED welches wir mit folgenden Befehlen installieren:

cd ~/.node-red
npm install node-red-contrib-fritz

Damit das neue Plugins in Node-RED zur Verfügung steht, muss Node-RED neu gestartet werden. Das FritzBox Plugin nutzt zur Kommunikation die TR064 Schnittstelle die wir zuerst aktivieren müssen.

Aktivierung der TR064 API der FritzBox
Die Aktivierung kann über ein angeschlossenes Telefon erfolgen. Damit rufen wir die Ziffernfolge #96*5* an. Zum Deaktivieren kann die Folge #96*4* verwendet werden.

Weitere Informationen zur TR064 Schnittstelle gibt es hier von AVM.

Steuerung des Gäste-WLAN

Das Ein- und Ausschalten des Gäste-WLAN über die Oberfläche der FritzBox ist umständlich und lässt nur eine eingeschränkte Automation zu. Einfacher ist ein Schalten mit Hilfe eines virtuellen Geräts in homee. Der Schaltzustand des Gäste-WLAN kann dann auch als Auslöser für Homeegramme dienen. Genauso kann das Gäste-WLAN über ein Homeegramm ein und ausgeschaltet werden.

Flow zum Schalten des Gäste WLAN

Flow zum Schalten des Gäste WLAN

Für den Flow brauchen wir ein virtuelles WeMo Gerät, eine Funktion und den Fritz!Box Node. Das virtuelle WeMo Gerät konfigurieren wir mit den Payloads on und off.

WeMo Konfiguration

WeMo Konfiguration

Die Funktion sieht dann so aus

return {
  payload: {
    NewEnable: msg.payload === 'on' ? 1 : 0
  }
};

Jetzt muss noch der Fritz Node konfiguriert werden. Mit einem Doppelklick auf den Node kommen wir in das Konfigurationsmenü und legen dort eine neue Fritz Box Konfiguration an.

Fritz Node Konfiguration

Fritz Node Konfiguration

Im Anschluss fragen wir die Services über den Button mit der Lupe ab. Je nach Modell der FritzBox kann das ein wenig dauern. Wenn nach einer Minute noch nichts im Dropdown Feld zu finden ist, einfach noch mal auf die Lupe klicken. Über die Liste wählen wir dann urn:dslforum-org:service:WLANConfiguration:3 aus.

Die gleiche Prozedur wiederholen wir beim Feld Actions. Dort wählen wir SetEnable aus der Liste.

Fritz Node Konfiguration 2

Fritz Node Konfiguration 2

Jetzt kann der Schalter wie gewohnt in homee integriert oder mit einer anderen Software genutzt werden.

Gäste-WLAN Flow zum Download

[{"id":"986380e9.875368","type":"wemo-emulator","z":"5635fba3.2a0f44","name":"Guest Wifi","friendlyName":"Gäste WLAN","serial":"2938562","port":"41257","onTopic":"guest/wifi","onPayload":"on","offTopic":"guest/wifi","offPayload":"off","x":140,"y":280,"wires":[["db14626a.1d0d78"]]},{"id":"db14626a.1d0d78","type":"function","z":"5635fba3.2a0f44","name":"","func":"return {\n    payload: {\n        NewEnable: msg.payload === 'on' ? 1 : 0\n    }\n};","outputs":1,"noerr":0,"x":290,"y":280,"wires":[["29bd9fc3.416"]]},{"id":"29bd9fc3.416","type":"fritzbox-in","z":"5635fba3.2a0f44","device":"61f053c7.62e594","name":"Gäste WLAN","service":"urn:dslforum-org:service:WLANConfiguration:3","action":"SetEnable","arguments":"{\"NewEnable\":\"value\"}","x":450,"y":280,"wires":[["97dece21.1bd53"]]},{"id":"97dece21.1bd53","type":"debug","z":"5635fba3.2a0f44","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":630,"y":280,"wires":[]},{"id":"61f053c7.62e594","type":"fritzbox-config","z":"","name":"FritzBox","host":"fritz.box","port":"49000","ssl":false}]

Benachrichtigung bei eingehenden Anrufen

Als nächstes erstellen wir einen Flow, der uns bei eingehenden Anrufen benachrichtigt und die anrufende Nummer im Telefonbuch der FritzBox nachschlägt. Wird ein Name gefunden, wird dieser zusätzlich mit ausgegeben. Die Benachrichtigung wird über Slack versandt; zusätzlich wird ein Webhook in Richtung von homee abgesandt. Natürlich sind auch andere Anbindungen, wie Telegram, Pushover oder E-Mail denkbar.

Flow zur Benachrichtigung über eingehende Anrufe via Slack und Webhook

Flow zur Benachrichtigung über eingehende Anrufe via Slack und Webhook

Der Callmonitor ist unser Ausgangspunkt. Im Konfigurationsmenü wählen wir unsere bereits erstellte FritzBox aus. Daran knüpfen wir den FritzBox-Lookup-Node. Hier ebenfalls wieder die zuvor eingerichtete FritzBox auswählen und im Feld Phonebook eine 0 erfassen. Letzteres wählt das Standardtelefonbuch.

Immer wenn ein Anruf eingeht, wird eine Nachricht erzeugt und an den nächsten Node weitergegeben. Der nächste Node sucht im Telefonbuch nach dem Anrufer und gibt diesen weiter. Neben eingehenden Anrufen werden auch nicht angenommene Anrufe gemeldet. Um nur eine Benachrichtigung bei eingehenden Anrufen und die Nachricht zu bauen, verwenden wir einen Funktions-Node.

// only incoming calls
if (msg.payload.type !== "INBOUND") return;

var response = 'Eingehender Anruf von: ';

if (msg.payload.caller_contacts.length) {
  response += msg.payload.caller_contacts[0].person.realName + ' (' + msg.payload.caller + ')';
} else {
  response += msg.payload.caller;
}

return { payload: response };

Die Funktion sorgt dafür, dass der Flow nur bei eingehenden Anrufen fortgesetzt und der Text “Eingehender Anruf von: [Name] ([Rufnummer])” bzw. “Eingehender Anruf von: [Rufnummer]” weitergegeben wird. Diese Nachricht wird an den Slack Node übermittelt.

Slack Nachricht bei eingehendem Anruf

Slack Nachricht bei eingehendem Anruf

Gleichzeitig wird ein Request Node dazu verwendet, einen Webhook in homee zu triggern.

Flow zum Download

[{"id":"32652d98.479a2a","type":"fritzbox-callmonitor","z":"2f1c2bc0.e5659c","device":"61f053c7.62e594","name":"","topic":"","x":180,"y":60,"wires":[["b7bdb240.1fd1b8"]]},{"id":"2c7d31b7.dddede","type":"slack","z":"2f1c2bc0.e5659c","name":"","channelURL":"https://hooks.slack.com/services/[...]","username":"MeinZuhause","emojiIcon":"","channel":"","x":670,"y":180,"wires":[]},{"id":"d05ebfc0.94bca8","type":"http request","z":"2f1c2bc0.e5659c","name":"","method":"GET","ret":"txt","url":"https://[homee-id].hom.ee/api/v2/webhook_trigger?webhooks_key=[webhook-key]&event=anruf","tls":"","x":590,"y":260,"wires":[["51d48672.1b2b7"]]},{"id":"b7bdb240.1fd1b8","type":"fritzbox-contact","z":"2f1c2bc0.e5659c","device":"61f053c7.62e594","name":"","topic":"","phonebook":"0","ccode":"DE","x":330,"y":120,"wires":[["78d007d6.44b8b"]]},{"id":"78d007d6.44b8b","type":"function","z":"2f1c2bc0.e5659c","name":"parse response","func":"// only incoming calls\nif (msg.payload.type !== \"INBOUND\") return;\n\nvar response = 'Eingehender Anruf von: ';\n\nif (msg.payload.caller_contacts.length) {\n    response += msg.payload.caller_contacts[0].person.realName + ' (' + msg.payload.caller + ')';\n} else {\n    response += msg.payload.caller;\n}\n\nreturn { payload: response };","outputs":1,"noerr":0,"x":460,"y":180,"wires":[["2c7d31b7.dddede","d05ebfc0.94bca8"]]},{"id":"51d48672.1b2b7","type":"debug","z":"2f1c2bc0.e5659c","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":790,"y":260,"wires":[]},{"id":"61f053c7.62e594","type":"fritzbox-config","z":"","name":"FritzBox","host":"fritz.box","port":"49000","ssl":false}]

Anwesenheitserkennung für beliebig viele Personen

Last but not least wollen wir uns noch eine automatische Anwesenheitserkennung über die Anwesenheit des Smartphones bauen. Dazu fragen wir die an der FritzBox angemeldeten Geräte in einem definierten Intervall ab. Über einen Abgleich der eindeutigen MAC-Adresse der Geräte, kann der Anwesenheitsstatus ermittelt werden.

Flow zur Anwesenheitserkennung mit beliebig vielen Geräten

Flow zur Anwesenheitserkennung mit beliebig vielen Geräten

Den FritzBox-Node konfigurieren wir mit dem Service urn:dslforum-org:service:Hosts:1 und als Action wählen wir X_AVM-DE_GetHostListPath. Der Node meldet uns bei der Ausführung einen Pfad samt Authentifizierungsschlüssel zurück, den wir für einen weiteren Request in Richtung FritzBox benötigen.

Parameter zur Abfrage der FritzBox Host Liste mit Node-RED

Parameter zur Abfrage der FritzBox Host Liste mit Node-RED

In der Konfiguration des Request Nodes geben wir die URL http://fritz.box:49000@{{{payload.NewX_AVM-DE_HostListPath}}} wie im nächsten Screenshot gezeigt an. Bitte verwendet bei der URL unbedingt je drei geschweifte Klammern, sonst funktioniert die Übergabe der Variable nicht.

Request Node zur Abfrage angemeldeten Geräte der FritzBox mit Node-RED

Request Node zur Abfrage angemeldeten Geräte der FritzBox mit Node-RED

Die FritzBox antwortet dann mit einer Geräteliste im XML-Format, die unter anderem die Mac- und IP-Adressen sowie den Online-Status der angemeldeten Geräte enthält. Praktischerweise bringt Node-RED von Haus aus einen Node mit, der XML in JSON umwandeln kann.

Nach der Umwandlung mit Hilfe des XML Nodes enthält der Payload unseres Flows nun einen Array mit den Geräten, den wir in einer Funktion weiter verarbeiten können.

const devices = msg.payload.List.Item;
const macs = ['A1:B2:C3:D4:B5:F4', 'A1:B2:D7:49:AC:34'];

let state = false;

for (let i=0; i<devices.length; i++) {
  if (macs.indexOf(devices[i].MACAddress[0]) > -1 && devices[i].Active[0] === "1") {
    state = true;
  }
}

if (state === context.get('oldState')) return;

context.set('oldState', state);

return state ? [msg, null] : [null, msg];

Die Funktion durchsucht den Array nach den festgelegten Mac-Adressen und prüft gleichzeitig den Online-Status des Gerätes. Dieser wird durch das Attribut Active als String ("0" oder "1") ausgewiesen. Sobald ein Gerät als Anwesend erkannt wurde, wird der Status auf true gesetzt.

Um nur echte Statusänderungen weiterzuleiten, greifen wir auf eine Variable oldState zu, die wir im Context des Nodes speichern und von dort wieder abrufen. Weicht der neue state vom oldState ab, wird eine Nachricht versendet. Mehr zum Speichern von Werten findet man in der offiziellen Node-RED Dokumentation.

Um einen Node einzusparen, bietet der Funktions-Node zwei Ausgänge. Einen für den Status Anwesend, einen für den Status Abwesend. Dabei wird der erste (obere) Ausgang für die Meldung der Anwesenheit und der zweite (untere) Ausgang für die Meldung der Abwesenheit verwendet.

Die Konfiguration des Request Nodes mit 2 Ausgängen

Die Konfiguration des Request Nodes mit 2 Ausgängen

Jetzt muss der Wert noch an homee übermittelt werden. Dazu gibt es zwei Möglichkeiten. Variante 1 ist das Auslösen eines Webhooks. Als Alternative kann auch mein Node-RED Plugin für homee genutzt werden. Ich werde hier nur die erste Variante beschreiben.

Wir erstellen zunächst zwei Homeegramme. Eins für den Status Anwesend, das zweite für den Status Abwesend. Als Auslöser verwenden wir jeweils einen Webhook und als Aktion verändern wir den Modus in Zuhause bzw. Abwesend. Damit der Modus Urlaub nicht durch den Status Abwesend verändert wird, legen wir im zweiten Homeegramm eine zusätzliche Bedingung an.

Homeegramm zum Setzen des Status Abwesend

Homeegramm zum Setzen des Status Abwesend

Für das Auslösen des Webhooks brauchen wir dann jeweils einen HTTP Request Node, den wir wie im Bild konfigurieren. Im Feld URL fügen wir unseren Webhook aus homee ein.

Konfiguration des Request Nodes zum triggern eines Webhooks in homee

Konfiguration des Request Nodes zum triggern eines Webhooks in homee

Nach dem Deployen des Flows wird nun alle 20 Sekunden der Anwesenheitsstatus überprüft und automatisch an homee übermittelt.

Flow für die Anwesenheitserkennung in Node-RED zum Download

[{"id":"8547a62b.261318","type":"function","z":"2f1c2bc0.e5659c","name":"parse response","func":"const devices = msg.payload.List.Item;\nconst macs = ['A1:B2:C3:D4:B5:F4', 'A1:B2:D7:49:AC:34'];\n\nlet state = false;\n\nfor (let i=0; i<devices.length; i++) {\n    if (macs.indexOf(devices[i].MACAddress[0]) > -1 && devices[i].Active[0] === \"1\") {\n        state = true;\n    }\n}\n\nif (state === context.get('oldState')) return;\n\ncontext.set('oldState', state);\n\nreturn state ? [msg, null] : [null, msg];","outputs":2,"noerr":0,"x":440,"y":600,"wires":[["12b83e74.f3068a"],["fbbc4496.707ed8"]]},{"id":"96c4ff22.8fcf2","type":"xml","z":"2f1c2bc0.e5659c","name":"","property":"payload","attr":"","chr":"","x":350,"y":540,"wires":[["8547a62b.261318"]]},{"id":"12b83e74.f3068a","type":"http request","z":"2f1c2bc0.e5659c","name":"Anwesend","method":"GET","ret":"txt","url":"http://[homee-id]/api/v2/webhook_trigger?webhooks_key=[webhook-key]&event=zuhause","tls":"","x":633,"y":580,"wires":[["556d3d5d.9f2a1c"]]},{"id":"fbbc4496.707ed8","type":"http request","z":"2f1c2bc0.e5659c","name":"Abwesend","method":"GET","ret":"txt","url":"http://[homee-id]/api/v2/webhook_trigger?webhooks_key=[webhook-key]&event=Abwesend","tls":"","x":633,"y":620,"wires":[["556d3d5d.9f2a1c"]]},{"id":"9d3ded91.a8985","type":"http request","z":"2f1c2bc0.e5659c","name":"","method":"GET","ret":"txt","url":"http://fritz.box:49000@{{{payload.NewX_AVM-DE_HostListPath}}}","tls":"","x":270,"y":480,"wires":[["96c4ff22.8fcf2"]]},{"id":"556d3d5d.9f2a1c","type":"debug","z":"2f1c2bc0.e5659c","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":810,"y":600,"wires":[]},{"id":"2cb8d0b3.406b88","type":"fritzbox-in","z":"2f1c2bc0.e5659c","device":"61f053c7.62e594","name":"","service":"urn:dslforum-org:service:Hosts:1","action":"X_AVM-DE_GetHostListPath","arguments":"{}","x":190,"y":420,"wires":[["9d3ded91.a8985"]]},{"id":"e3c594a3.28927","type":"inject","z":"2f1c2bc0.e5659c","name":"every 20s","topic":"","payload":"","payloadType":"date","repeat":"20","crontab":"","once":true,"onceDelay":0.1,"x":130,"y":360,"wires":[["2cb8d0b3.406b88"]]},{"id":"61f053c7.62e594","type":"fritzbox-config","z":"","name":"FritzBox","host":"fritz.box","port":"49000","ssl":false}]

Das könnte dir auch gefallen