openHAB :: Einbinden von Funksteckdosen
Wie wir aus diesem Artikel wissen, können wir die recht günstigen Funksteckdosensets der Firma Brennenstuhl mit einem 433MHz-Funksender auch mit einem Raspberry steuern.
In dem erwähnten Artikel geben wir uns damit zufrieden, die entsprechenden Kommandos in die Konsole zu hämmern. Wäre es nicht schön, diese Funksteckdosen auch in openHAB zu integrieren? Wie das realisiert werden kann, möchte ich in diesem neuen Beitrag zeigen.
Verfügbare Artikel zu openHAB
Unser Beispielszenario ist wie folgt konfiguriert:
Wir verfügen über einen Server mit einer lauffähigen openHAB-Instanz, welche wir zuvor installierten und konfigurierten. Dieser Server ist unter der IP-Adresse „192.168.23.212“ erreichbar. Zudem befinden sich verteilt im Haushalt drei Raspberry Pi, die mit den Adressen „192.168.23.235„, „192.168.23.236“ und „192.168.23.237“ konfiguriert wurden. Wir haben zuvor sichergestellt, dass dem Server ein SSH-Login ohne Passworteingabe auf allen Raspberry gestattet wird. Grafisch kann man dieses Szenario so darstellen:
Für diesen Beitrag interessieren uns jedoch lediglich die angeschlossenen 433MHz-Funksender. Als zu schaltendes Beispielobjekt führe ich in diesem Artikel ein Paar Lautsprecher auf, die sich im Wohnzimmer befinden.
Zunächst prüfen wir, wie auch in allen anderen Artikeln der openHAB-Serie, ob die Funktionalität lokal am Raspberry gewährleistet ist. Dazu melden wir uns via SSH am Raspberry an und schalten die Lautsprecher mit dem entsprechenden Haus- sowie Gerätecode ein:
/usr/local/bin/send 11101 3 1
Ein hörbares Klick der Funksteckdose sowie die Status-LED der Lautsprecher vermitteln uns nun möglicherweise das erste Erfolgserlebnis. Als Nächstes testen wir, ob dieser Vorgang fehlerfrei remote vom openHAB-Server aus möglich ist:
/usr/bin/ssh -i /scripts/.ssh/id_rsa root@192.168.23.235 "/usr/local/bin/send 11101 3 0"
Nun sollten die Lautsprecher wieder ausgeschaltet worden sein. Da wir über drei in der Wohnung verteilte Raspberry verfügen, ist es durchaus sinnvoll, dass der entsprechende Schaltbefehl via Funk von allen Sendern aus erfolgt. Das hier vorgestellte Funksteckdosensystem verfügt leider über keinen Rückkanal, so dass wir nicht hundertprozentig wissen können, ob der Schaltvorgang erfolgreich verlief oder nicht. Möglicherweise konnte einer der Funksender den Funkaktor, also die Funksteckdose, nicht erreichen. Daher schadet es nicht, wenn der Schaltbefehl von drei Seiten „gleichzeitig“ erfolgt. Und genau das verpacken wir nun in ein kleines Bash-Script „/scripts/fsd.sh„:
#!/bin/bash /usr/bin/ssh -i /scripts/.ssh/id_rsa root@192.168.23.235 "/usr/local/bin/send $1 $2 $3" /usr/bin/ssh -i /scripts/.ssh/id_rsa root@192.168.23.236 "/usr/local/bin/send $1 $2 $3" /usr/bin/ssh -i /scripts/.ssh/id_rsa root@192.168.23.237 "/usr/local/bin/send $1 $2 $3"
Wir erlauben die Ausführung des Scripts durch
chmod +x /scripts/fsd.sh
und übertragen den Besitz an „openhab“ durch
chown openhab: /scripts/fsd.sh
Wir starten nun das Script auf dem openHAB-Server zunächst per Hand und prüfen, ob es ordnungsgemäß funktioniert:
/scripts/fsd.sh 11101 3 1
Anschließend können wir die Lautsprecher zunächst auch wieder ausschalten.
Für die Einbindung in OpenHAB verwenden wir das Addon „exec„, welches wir, wenn noch nicht vorhanden, nachträglich installieren mittels apt-Paketverwaltung:
apt-get install openhab-addon-binding-exec
Wenn alle Vorbereitung für openHAB erfolgreich abgeschlossen wurden, ist es nun an der Zeit, ein entsprechendes Item zu erstellen:
Switch BOXEN_WZ <speaker> (grp_Boxen) { exec=">[ON:/scripts/fsd.sh 11101 3 1] >[OFF:/scripts/fsd.sh 11101 3 0]" }
Die Spalten dieser Definition im Einzelnen:
- Das Item wird als Typ „Switch“ definiert
- Das Item wird mit „BOXEN_WZ“ bezeichnet
- Für die spätere Anzeige in der Sitemap wird das Symbol „speaker“ gewählt
- Das Item wird der Gruppe „grp_Boxen“ hinzugefügt
- Das Addon „exec“ wird zum Ein- und Ausschalten genutzt
Nun sind wir soweit, dass wir die Funksteckdose in die Sitemap einbinden können:
Switch item=BOXEN_WZ label="Lautsprecher" icon="speaker" mappings=[ON="An", OFF="Aus"]
Nun wird das Lautsprecherpaar auf der Weboberfläche oder in der openHAB-App so dargestellt:
Eine weitere, interessante Möglichkeit ist die Verwendung des neuen Items in einer bzw. mehreren Regeln. Beispielsweise sollen die Lautsprecher nur eingeschaltet sein, wenn auch der Fernseher läuft, an dem die Lautsprecher angeschlossen sind. Da der Fernseher mit dem lokalen Netzwerk verbunden ist, kann mittels einfacher Ping-Anfragen festgestellt werden, ob dieser in Betrieb ist oder nicht. Das dazu notwendige „Network-Health“ Addon stelle ich in einem weiteren Artikel vor.
Wir definieren also eine Regel, die unser Item „BOXEN_WZ“ einschaltet, wenn sich der Status des Fernsehers (TVC42) zu „ON“ ändert und das Item wieder ausschaltet, wenn auch der Fernseher nicht mehr erreichbar (OFF) ist:
rule "Fernseher WZ geht an" when Item TVC42 changed to ON then sendCommand(BOXEN_WZ, ON) end rule "Fernseher WZ geht aus" when Item TVC42 changed to OFF then sendCommand(BOXEN_WZ, OFF) end
Bei Gruppenschaltungen von Funksteckdosen ist ein wichtiger Punkt zu beachten, wie ich aus eigener Erfahrung feststellen musste. Grundsätzlich schaltet openHAB alle Elemente dieser Gruppe gleichzeitig. Da wir jedoch jeden Funkschaltbefehl mit allen verfügbaren Raspberries senden, werden dabei einige Mitglieder „übersprungen“. Daher ist es notwendig, zwischen jedem geschalteten Mitglied der Gruppe eine kurze Verzögerung einzubauen. Für eine morgendliche Zeitschaltung habe ich wie in folgender Regel gezeigt, zwischen jedem geschalteten Item eine Pause von zwei Sekunden eingesetzt:
rule "Morgens Tageslichter an" when Time cron "0 30 5 * * ?" then grpTier_TAGESLICHT?.members.forEach[Switch| sendCommand(Switch, ON) Thread::sleep(2000) ] end
In dieser Regel werden morgens um 05:30 alle Tageslichter meiner aquaristischen und terraristischen Bewohner (Gruppe „grpTIER_TAGESLICHT„) eingeschaltet.
Raspi und 433Mhz-Funksteckdosenschaltung, Switch auf OpenHAB - Tales from the Mac Hell
03.04.2022 @ 13:06
[…] nutzte: einmal von · Tutorials Raspberry-Pi und ein wenig weitere Inspiration von · Klenzel. Im Folgenden schreib ich vor allem über Fehler und Probleme, die ich trotzdem hatte, weil die hat […]
David
21.02.2016 @ 20:01
Hi, ich habe das selbe Problem. Gibts hier bereits eine Lösung? So wie ich das sehe (bin kein Linux Profi) dann läuft der Service bei mir mit dem Standarduser „pi“. Über den kann ich das Skript auch ganz normal aufrufen.
Daniel Wenzel
13.02.2016 @ 06:23
Hallo, ich bin grad dabei, sämtliche openHAB Artikel zu überarbeiten. Unter welchem Nutzer läuft bei dir der openHAB-Prozess? (ps aux)
Möglicherweise darf dieser Nutzer nicht auf das Script zugreifen bzw. der entsprechende SSH-Schlüssel wurde nicht ausgetauscht.
Thomas
12.02.2016 @ 10:31
Ich habe folgendes Script erstellt, ohne Probleme aufrufen kann (auch als Benutzer pi ohne sudo)
Code:
#!/bin/bash
/usr/local/bin/send $1 $2 $3
Code:
pi@raspberrypi ~ $ /opt/openhab/configurations/scripts/fsd.sh 00010 2 1
test1sending systemCode[00010] unitCode[2] command[1]
Und die Steckdose wird in diesem Fall auf 1 geschalten.
Wenn ich das ganze jetzt aber über ein Item machen will, funktioniert es einfach nicht.
Code:
Switch HIFI_WZ „TV / HIFI“ (WZ) {exec=“ON:/opt/openhab/configurations/scripts/fsd.sh 00010 2 1 ,OFF:/opt/openhab/configurations/scripts/fsd.sh 00010 2 0″}
Hat jemand vielleicht eine Idee was ich falsch mache?
Tom
09.05.2015 @ 13:18
Habe es so gemacht, wie erläutert. Leider kann ich die Steckdosen im Web-Interface nicht bedienen:
ERROR:
2015-05-09 13:08:55.422 [WARN ] [.o.u.w.i.render.SwitchRenderer] – Cannot determine item type of ’steckdose1′
org.openhab.core.items.ItemNotFoundException: Item ’steckdose1′ could not be found in the item registry
at org.openhab.core.internal.items.ItemRegistryImpl.getItem(ItemRegistryImpl.java:80) ~[na:na]
at org.openhab.ui.internal.items.ItemUIRegistryImpl.getItem(ItemUIRegistryImpl.java:531) ~[na:na]
at org.openhab.ui.webapp.internal.render.SwitchRenderer.renderWidget(SwitchRenderer.java:57) ~[org.openhab.ui.webapp_1.6.2.jar:na]
at org.openhab.ui.webapp.internal.render.PageRenderer.renderWidget(PageRenderer.java:158) [org.openhab.ui.webapp_1.6.2.jar:na]
at org.openhab.ui.webapp.internal.render.PageRenderer.processChildren(PageRenderer.java:121) [org.openhab.ui.webapp_1.6.2.jar:na]
at org.openhab.ui.webapp.internal.render.PageRenderer.processChildren(PageRenderer.java:138) [org.openhab.ui.webapp_1.6.2.jar:na]
at org.openhab.ui.webapp.internal.render.PageRenderer.processPage(PageRenderer.java:86) [org.openhab.ui.webapp_1.6.2.jar:na]
at org.openhab.ui.webapp.internal.servlet.WebAppServlet.service(WebAppServlet.java:126) [org.openhab.ui.webapp_1.6.2.jar:na]
at org.eclipse.equinox.http.servlet.internal.ServletRegistration.service(ServletRegistration.java:61) [org.eclipse.equinox.http.servlet_1.1.300.v20120522-1841.jar:na]
at org.eclipse.equinox.http.servlet.internal.ProxyServlet.processAlias(ProxyServlet.java:128) [org.eclipse.equinox.http.servlet_1.1.300.v20120522-1841.jar:na]
at org.eclipse.equinox.http.servlet.internal.ProxyServlet.service(ProxyServlet.java:60) [org.eclipse.equinox.http.servlet_1.1.300.v20120522-1841.jar:na]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:848) [javax.servlet_3.0.0.v201112011016.jar:na]
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:598) [org.eclipse.jetty.servlet_8.1.3.v20120522.jar:8.1.3.v20120522]
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:486) [org.eclipse.jetty.servlet_8.1.3.v20120522.jar:8.1.3.v20120522]
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231) [org.eclipse.jetty.server_8.1.3.v20120522.jar:8.1.3.v20120522]
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1065) [org.eclipse.jetty.server_8.1.3.v20120522.jar:8.1.3.v20120522]
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:413) [org.eclipse.jetty.servlet_8.1.3.v20120522.jar:8.1.3.v20120522]
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:192) [org.eclipse.jetty.server_8.1.3.v20120522.jar:8.1.3.v20120522]
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:999) [org.eclipse.jetty.server_8.1.3.v20120522.jar:8.1.3.v20120522]
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117) [org.eclipse.jetty.server_8.1.3.v20120522.jar:8.1.3.v20120522]
at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:250) [org.eclipse.jetty.server_8.1.3.v20120522.jar:8.1.3.v20120522]
at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:149) [org.eclipse.jetty.server_8.1.3.v20120522.jar:8.1.3.v20120522]
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:111) [org.eclipse.jetty.server_8.1.3.v20120522.jar:8.1.3.v20120522]
at org.eclipse.jetty.server.Server.handle(Server.java:350) [org.eclipse.jetty.server_8.1.3.v20120522.jar:8.1.3.v20120522]
at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:454) [org.eclipse.jetty.server_8.1.3.v20120522.jar:8.1.3.v20120522]
at org.eclipse.jetty.server.AbstractHttpConnection.headerComplete(AbstractHttpConnection.java:890) [org.eclipse.jetty.server_8.1.3.v20120522.jar:8.1.3.v20120522]
at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete(AbstractHttpConnection.java:944) [org.eclipse.jetty.server_8.1.3.v20120522.jar:8.1.3.v20120522]
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:630) [org.eclipse.jetty.http_8.1.3.v20120522.jar:8.1.3.v20120522]
at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:230) [org.eclipse.jetty.http_8.1.3.v20120522.jar:8.1.3.v20120522]
at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:77) [org.eclipse.jetty.server_8.1.3.v20120522.jar:8.1.3.v20120522]
at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:606) [org.eclipse.jetty.io_8.1.3.v20120522.jar:8.1.3.v20120522]
at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:46) [org.eclipse.jetty.io_8.1.3.v20120522.jar:8.1.3.v20120522]
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:603) [org.eclipse.jetty.util_8.1.3.v20120522.jar:8.1.3.v20120522]
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:538) [org.eclipse.jetty.util_8.1.3.v20120522.jar:8.1.3.v20120522]
at java.lang.Thread.run(Thread.java:744) [na:1.8.0]
2015-05-09 13:08:55.430 [ERROR] [o.u.i.items.ItemUIRegistryImpl] – Cannot retrieve item ’steckdose1′ for widget org.openhab.model.sitemap.Switch
2015-05-09 13:08:55.433 [ERROR] [o.u.i.items.ItemUIRegistryImpl] – Cannot retrieve item ’steckdose1′ for widget org.openhab.model.sitemap.Switch
2015-05-09 13:08:55.437 [ERROR] [o.u.i.items.ItemUIRegistryImpl] – Cannot retrieve item ’steckdose1′ for widget org.openhab.model.sitemap.Switch
2015-05-09 13:08:55.438 [ERROR] [o.u.i.items.ItemUIRegistryImpl] – Cannot retrieve item ’steckdose1′ for widget org.openhab.model.sitemap.Switch