Marlon Alagoda
Senior Developer (ehem.)
Hands on: Smart Home
Inspiriert von diesem “Press for Champagne” Button beim Sunday Roast im Zuge meiner Englandreise, habe ich die letzten Urlaubstage gleich genutzt um mir etwas Smart Home Equipment zu besorgen und meinen ganz eigenen Party Button zu bauen.
Nach ein paar Minuten ahnungslosen Googeln, habe ich festgestellt, dass es gleich ein paar Standards für Smart Home Anwendungen gibt. Neben einigen proprietären Technologien wie HomeKit von Apple gibt es ZigBee und Z-Wave. Beide Funknetzwerk Technologien verbindet, dass sie darauf ausgelegt sind viele, kleine Devices wie Lichtschalter, Bewegungssensoren, Türöffner usw. und Steuereinheiten („Controller“), miteinander zu verbinden und dass sie Mesh Netzwerke sind, also jeder Teilnehmer im Netzwerk die Reichweite erweitert. ZigBee hat eine weitere Verbreitung, die Anzahl der zum Netzwerk hinzufügbaren Geräte und deren Geschwindigkeit skaliert besser und die Geräte sind tendenziell kleiner und energiesparender als die von Z-Wave. Letzteres soll sich mit dem neuen Z-Wave plus Standard ändern. ZigBee hat aber den Ruf schlechte Interoperabilität zwischen Herstellern zu haben. Jedes Gerät muss einen Fingerprint, wodurch sich Hersteller, Modell und Befehlsklasse (“Command Clusters”) feststellen lassen, angeben. Ein Controller muss den Fingerprint einer Befehlsklasse zuordnen können, kennt er das Gerät nicht, kann er erst mal nicht mit ihm kommunizieren. Manche Controller verwenden einfach die vom Gerät angegeben Befehlsklasse, manche aus Sicherheitsgründen nicht. Das Z-Wave Konsortium hat es sich hingegen zur Aufgabe gemacht 100% Interoperabilität zwischen zertifizierten Geräten zu gewährleisten, was die Technologie für DIY Projekte bei denen man verschiedene Hardware von schwindeligen Herstellern zusammen funktionieren lassen will, besser geeignet macht.
Setup
Da ich keine 500 Euro für eine fertige Z-Wave Lösung ausgeben wollte, habe ich mir für 50 Euro das Razberry Daughterboard für meinen Raspberry Pi gekauft, mit dem es möglich sein soll Events von Z-Wave Geräten zu fangen und Aktionen abzusetzen. Außerdem habe ich mir The Button von Fibaro gekauft, mit dem man 7 verschiedene Signale (1, 2, 3, 4, 5 mal, 1 mal lange drücken und release) abschicken kann. Das Razberry Daughterboard kommt mit dem open source Z-Way-Server inklusive Web-UI.
Die Idee ist simpel
- Lange auf den Button drücken führt dazu, dass die Musik in der ganzen Wohnung angeht
- Kurz auf den Button drücken, beendet die Musikwiedergabe in der ganzen Wohnung
- Zwei mal auf den Button drücken → Nächstes Lied
Das Zusammenstecken vom Raspberry mit dem Daughterboard Razberry für die Z-Wave Anbindung und die Installation der dazugehörigen Open Source Software, welche unter Raspbian einwandfrei läuft, funktioniert mit der mitgelieferten Anleitung einfach und schnell.
Z-Wave Controller müssen Devices „Interviewen“, damit sie mit ihnen kommunizieren können. Dabei werden die möglichen Aktionen ausgetauscht. Das “Interviewen” von dem Button mit dem Razberry funktioniert über das Webinterface erstmal nicht so schlecht. Ich hätte erwartet, dass der Z-Way-Server dank seinem „virtual Device Konzept“ für jede mögliche Aktion ein Device erstellt. Leider erstellt der Server nur zwei und nicht sieben Devices für alle oben aufgezählten, möglichen Events. Virtuelle Devices werden im erstaunlich gut geschriebenen ZWayManual wie folgt erklärt:
“The purpose of virtual devices is to unify the appearance on a graphical user interface and to unify the communication between them.”
Kann ein Button oder anderes Z-Wave Gerät also mehr als nur eine Art von Zustandsänderung, kann dies über virtuelle Devices, in diesem Fall virtuelle Buttons abgebildet.
Dass der Fibaro Button nicht perfekt mit dem Razberry zusammen spielt wusste ich schon aus einem Forumsbeitrag, trotzdem wollte ich den prägnanten Knopf haben.
Die zwei Devices die nach dem Interview automatisch erkannt und im Webinterface vom Z-Way-Server angezeigt werden feuern beide immer wenn der Button betätigt wird. Der erste virtuelle Button feuert immer “ON”, wenn der Button gedrückt wird, egal wie of, somit ist er für meine Zwecke sinnlos.
Das zweite virtuelle Device feuert ein changed Event mit einer ID, die sich in eine der 7 möglichen Aktivitäten übersetzen lässt, das ist schon hilfreicher! Leider können die anderen Module mit diesen IDs nicht wirklich, oder nur mit großen Workarounds etwas anfangen, weshalb ich mich rangesetzt habe und selbst ein Fibaro “The Button” Modul für den Razberry geschrieben habe.
Razberry App Entwicklung
Apps für Razberry sind in Javascript oder C geschrieben und schnell entwickelt, auch hier ist das ZWayManual hilfreich. Im entsprechenden Modul Ordner müssen zumindest zwei Dateien angelegt werden, eine index.js und ein module.js. In der module.js Datei kann angegeben werden welche Felder dem Nutzer in der GUI zur Verfügung gestellt werden sollen und welchen Typen diese Felder haben. In meinem Beispiel muss der Nutzer beim aktivieren meines Moduls den entsprechenden Button auswählen, er könnte ja mehrere Buttons eingebunden (interviewed) haben. Als Datentypen des Eingabefeldes habe ich in der module.js Datei also ein Enum mit allen zur Verfügung stehenden diskreten Sensoren, was die Device Klasse des Buttons ist, gewählt.
module.js: Konfiguration für die GUI Eingabemöglichkeiten beim Aktivieren des Moduls durch den User
"targets": {
"type": "array",
"items": {
"type": "object",
"properties": {
"button": {
"type": "object",
"properties": {
"target": {
"type": "string",
"datasource": "namespaces",
"enum": "namespaces:devices_sensorDiscrete:deviceId",
"required": true
}
}
}
}
}
}
In der index.js kann man später auf die Eingaben des Nutzers zugreifen, das muss man auch, weil man nur auf die eingehenden Events von dem vom Nutzer gewählten Button und nicht auf alle möglichen Sensoren und Devices reagieren will.
Ich habe mir also für alle möglichen Events ein virtuelles Device erstellt und die virtuellen Devices bei eingehenden Events abhängig von der mitgesendeten ID feuern lassen.
Virtuelles Device erstellen
self.vDevs['pressed_once'] = self.controller.devices.create({
deviceId: 'ftb_pressed_once_' + self.id,
defaults: {
metrics: {
title: buttonName + ': pressed once'
}
},
overlay: {
deviceType: 'toggleButton',
metrics: {
icon: 'media',
level: 'on'
}
},
handler: function (cmd, args) {
this.set('metrics:level', cmd)
},
moduleId: self.id
})
Jetzt haben wir 7 virtuelle Devices, welche alle eine bestimmte Aktion von einem vom User gewählten Button repräsentieren und müssen noch dafür sorgen, dass die Devices ein Event feuern, auf das andere Module reagieren können, wenn der Button entsprechend gedrückt wird.
Event ID von Hardwarebutton in Aktion von virtuellem Device übersetzen
// Listen to hardware button events
self.controller.devices.on(button.device, 'change:metrics:level', function (event) {
// Parse ID and "convert" it to button press of virtual button
switch (parseInt(String(event.get('metrics').level).split('')[1])) {
case 0:
self.vDevs['pressed_once'].performCommand('on')
break
case 2:
self.vDevs['pressed_long'].performCommand('on')
break
// ...
}
})
Musik an
Damit dann auch wirklich Musik startet, wenn ich auf den Button drücke, habe ich über das Userinterface eine einfache IF-THEN Beziehung zwischen dem virtuellen Button “long pressed” und der Play Funktionalität vom standardmäßig installierten Sonos Modul eingestellt.
Nächster Song bitte
Das default Sonos Modul unterstützt leider nur das Ändern der Lautstärke, Play und Pause, also musste ich für die “Nächstes Lied” Funktion nochmal an den Code. In einem Fork von dem Sonos Modul habe ich einen drittes virtuelles Device hinzugefügt und die bestehende Action Method beim Betätigen des virtuellen Next-Song-Device mit “Next” aufgerufen. Nichts einfacher als das!
In der Z-Way Server UI habe ich dann meinen “pressed twice” Button mit dem eben angelegten virtuellen Device verknüpft. Für die Erweiterung habe ich einen Pull Request eingestellt, der prompt im nächsten Release gelandet ist.
Mit Sonos kann man über das UPnP AVTransport Interface kommunizieren. Ich hätte zwar gerne, dass sich per Button-Druck das aktuell Genre ändern, dazu müsste ich mich aber mit SOAP auseinander setzen und mit Seife wäscht man sich eigentlich nur die Hände, also muss das noch warten.