Angefangen hat alles mit einer "smarten" Steckdose.

Dann habe ich im Internet den FHEM-Server entdeckt...

Angefangen hat alles mit einer "smarten" Steckdose.

Dann habe ich im Internet den FHEM-Server entdeckt...

Allgemeines

 

Allgemeines:

Was ist FHEM?

"FHEM ist ein in perl geschriebener, GPL lizensierter Server für die Heimautomatisierung."

http://fhem.de/fhem_DE.html

Um es kurz zu machen: FHEM ist großartig ! Der Server läuft auf verschiedensten Geräten:

auf Windows, Linux, Raspberry Pi und anderen Kleinstrechnern - sogar auf NAS-Platten.

FHEM schafft das, was die Industrie mal wieder nicht hinbekommt: es vereint unendlich

viele Protokolle in einem System. Der Panasonic-TV kann mit dem Homematic-Rolladenaktor

agieren (wenn TV an, dann Rolladen herunterfahren),

die Philips-Hue-Lampe mit der Sonos-Box, der Logitech-Harmony-Hub mit dem Enigma-Receiver.

Und so weiter und so weiter...

Es ist ein klein wenig Hirnschmalz gefordert, bevor man irgendetwas zum Laufen bekommt,

man muß aber durchaus keine Atome spalten können, um Automatisierungen zu realisieren.

FHEM ist sehr gut dokumentiert und im FHEM-Forum trifft man auf nette User, die einen gerne unterstützen.

http://forum.fhem.de/

Ich kenne mich weder mit Perl noch mit JAVA aus und habe mir alles in oben genannten Forum angelesen.

Hier mein bisheriger "Output":

Fhem läuft bei mir auf einem Intel NUC i5 mit Linux Mint..

Eine sehr gute Beschreibung wie man FHEM auf einem Gerät installiert und wie man z.B. Verbindung zu Homematic-Komponenten schafft findet sich hier:

http://www.meintechblog.de/2013/05/fhem-server-auf-dem-raspberry-pi-in-einer-stunde-einrichten/

Mit dieser Beschreibung habe ich angefangen.

Mit der standard-FHEM-Oberfläche kann man eigentlich schon alles steuern.

Es geht allerdings noch schöner, denn es gibt viele unterschiedliche Frontends für fhem, Da sollte für jeden Geschmack und jede Anwendung etwas dabei sein. Es kommt halt drauf an, was man steuern möchte und wo man die Steuerung visualisieren möchte (kleines Display (Handy,Tablet) oder großes (PC, TV). Ich habe mich für  das frontend "Floorplan" entschieden.

Den Floorplan finde ich am flexibelsten – da es sich ja im wesentlichen um eine „html-Seite“ handelt kann man hier in relativ kurzer Zeit viele Dinge realisieren.
Ausserdem: es muß sich bei einer floorplan-Seite ja nicht unbedingt um einen Gebäude-Grundriss handeln. Alles ist möglich - von der Listendarstellung bis zur 3D-Kugel.
Ich habe mich für das Design „darkfloorplanstyle.css“ entschieden.
Die 3D-Zeichnungen habe ich mit dem Programm "SweetHome3D" erstellt.
Die Bedienung erfolgt über unsere Tablets und PCs. In der Küche (zentraler Raum) und an der Haustür habe ich jeweils ein Tablet an
die Wand gespaxt:

Android, Dolphin-Browser im Fullscreen-Modus (Achtung: "Dolphin-Jetpack" muß abgeschaltet sein, sonst verschluckt der browser einige dummys)

( wundert Euch nicht über die schiefe Wand - das gehört so - wir wohnen in einer uralten Reetdachkate, hier ist nichts gerade  ;D )

und in der Küche:

Komponenten

 

Ich habe folgende Komponenten im Einsatz:

Mein FHEM läuft mittlerweile auf einem Intel NUC i5, das Aufrufen der Floorplans ist dadurch superfix.

Zusätzlich habe ich im Einsatz:

  • div. Homematic-Komponenten über HM-LAN-Adapter:
    Schalter, Taster, Jalousie-Aktoren,Thermostaten, Funk-Tasterschnittstellen,Funk-Fernbedienungen
  • Fritzbox 6840LTE mit 10x FritzDect200
  • Philips-Hue Bridge, dazu 3x Lightstrip und 3x Hue Bulb
  • 1x VU+ Duo2 Enigma-Sat-Receiver
  • 2x Harmony-Hub zur IR-Anbindung diverser Geräte ohne LAN-Schnittstelle
  • 2x Philips-TV
  • 7x PI2 mit piCorePlayer als Squeezebox-Client mit Logitech Squeezebox Server auf dem NUC
  • 1x E-Litro Net Heizöl-Level Erfassung
  • 1x HM-Sys-sRP-Pl Selektiver Funkrepeater


Folgendes habe ich (bisher) mit fhem realisiert:

Steuerung (fast) aller Lampen, Rollos, Pumpen, Ventile, Torantrieb
Steuerung von Philips-Hue Kompontenten
Steuerung von Philips-TVs
Steuerung der Dreambox
Steuerung von Harmony Hubs
Squeezebox Multiroom
Sprachbenachrichtigung bei eingehenden emails über Squeezebox "talk"
PCs aufwecken per WOL
Anwesenheitserkennung (ping auf unsere Handys) → pushmail → Begrüssung per Sprachausgabe
Müllabfuhr-Kalender (über Google Kalender, im Floorplan werden Symbole für Mülltonne, Gelber Sack oder
Papiertonne eingeblendet wenn die Abfuhr dran ist)
http://www.fhemwiki.de/wiki/Google-Kalender_zur_Steuerung_von_Dummies
Pushmail über Debian-Sendmail zur Fernbedienung von Android-Geräten (mit Tasker)
Messung des Heizöl-Standes zuerst per Ultraschall-Sensor, jetzt per Einperl-Sonde

Ausserdem kann ich sämtliche Befehle (auch TV-Programme umschalten, usw.)
per Spracheingabe steuern und bekomme auch ein Sprachfeedback:
„Computer, schalte die Aussenbeleuchtung ein“ → „Ich habe die Aussenbeleuchtung eingeschaltet“
http://forum.fhem.de/index.php/topic,13455.0.html

Floorplans

 

Meine Floorplans:

Erdgeschoss

Im Erdgeschoss-Floorplan kann ich alle relevanten Lampen und Rollos schalten, die farbigen „Blumen“ zeigen den
Schaltzustand unserer „Hue Devices“ an. (readingsProxy)
Die eigentliche Steuerung der Farben der Hue-Lampen und Lightstrips findet aus Platzgründen im separaten
Floorplan „Philips Hue“ statt.

Das Wetter ist das Yahoo-Wetter mit folgenden Anpassungen:

für die horizontale Darstellung: WeatherAsHtmlH
http://forum.fhem.de/index.php?topic=25262.0
und um die Beschriftung im dunklen Floorplan besser sichtbar zu machen habe ich diese Zeile
in die darkfloorplanstyle.css eingefügt:

table.weather { color: #ffffff; font-size: 14px;}


Auch die Steuerung der Heizungs-Thermostaten habe ich – ebenfalls aus
Platzgründen in einen separaten Floorplan geschoben. Hier habe ich zusätzlich
die entsprechenden Plots eingefügt. Die kleinen Thermostaten im Erdgeschoss-Floorplan
sind weblinks, diese leiten direkt auf den „Heizungs-Floorplan“ weiter.

Ein Klick/Touch auf die PC-Symbole weckt den entsprechenden PC per WOL, das TV-Symbol
verlinkt zum "Multimedia-Floorplan, das Lautsprechersymbol zum "Multiroom-Audio"-Floorplan.

Das Tag/Nacht-Symbol ist ein "Makro"-Dummy für Licht, TV, usw.

 

In der Küche:
An den on/off-Button unseres Kaffeeautomatens habe ich 2 Drähte angelötet. Ein Homematic-Schalter schaltet eine Kippstufe (Conrad-Bausatz) und die betätigt bei ein/aus kurz diesen Taster.
Das „Eierbechersymbol“ löst einen 5 Minuten Timer aus – danach gibt es eine „sendmail“ mit dem Betreff „Die Eier sind fertig!“ auf alle Tablets – die dann klingeln. Gibt immer perfekte Frühstückseier...

Obergeschoss:

Das Obergeschoss u.a. hat einen Wecker (sendmail auf's Tablet – das macht dann Lärm)
und einen TV-Ausschalttimer (Harmony Hub)

Aussenanlage und Bewässerung

 

Aussenanlage:

Wir haben eine kleine „Hobby-Tierhaltung“ (Esel, Schafe, Hühner).
Die Stallbeleuchtung ist natürlich integriert, ausserdem die Wasserversorgung der
Ställe über ein Gardena-Ventil und einen Homematic-Schalter:

Das Gardena-Ventil benötigt 24V AC - daher der Ringkerntrafo.
Hinter dem Ventil ist eine Schaltschrankheizung montiert, diese wird bei Minus-Graden von einer
Conrad-Thermostat-Steckdose aktiviert damit das Ventil im Winter nicht einfriert.

Zusätzlich lassen sich die Aussenbeleuchtung, die Lampion-Ketten der Terrassenbeleuchtung und diverse Pumpen
(wir haben einen Bachlauf, einen Teich mit Wasserspeier und einen kleinen Wasserfall gebaut) steuern.

Gartentor-Steuerung

 

Torsteuerung

Wir haben einen Motorantrieb an unser Einfahrtstor gebaut. Auch diesen habe ich in unsere
Hausautomation integriert. Ich habe einen HM-LC-SW1-FM direkt in das Gehäuse der Torelektronik montiert. 
Bedient wird das ganze  mit  HM-RC-4-2 Handsendern.
Da wir leider genau 2m vor dem Tor keine Verbindung mehr zum HMLAN-Adapter haben
(man müsste aus dem Auto aussteigen, um das Tor zu öffnen...), habe ich den den HM-LC-SW1-FM direkt
mit einer der Tasten unserer Handsender gepeert:

set Handsender1_4 peerChan 0 Torantrieb single


Jetzt muß die Funkverbindung also nur noch bis zum Aktor reichen.
Weil der Torantrieb einen Tastimpuls erfordert, habe ich diesen peer „getimed“:

set Torantrieb regSet shOnTime 3 Handsender1_4


Der Aktor schaltet jetzt für 3 Sekunden an und dann wieder aus. Der Tasttkontakt für das Tor muß potentialfrei sein,
ich habe also zusätzlich ein 230V-Relais hinter den Aktor gehängt.

Wie schon erwähnt: wir haben eine kleine Herde von „Rasen-Mäh-ern“ haben, die auch direkt um das Haus den Rasen kurzhalten.
Da ist es sehr wichtig, das Öffnen und Schließen des Tores zu überwachen. Auch um die Blumenbeete des Nachbarn zu schonen  :)

Zu diesem Zweck habe ich einen Homematic Funk-Tür/Fensterkontakt HM-SEC-SC-2 in ein wasserdichtes Gehäuse (eine alte dünnwandige Schraubenschachtel, in Torfarbe lackiert) montiert und den passenden Magneten an den Torflügel geschraubt.
Der Status bei geschlossenem Tor ist also „closed“ , wenn der Reedkontakt öffnet gibt es ein „open“.

So kann FHEM schonmal erkennen, ob das Tor auf oder zu ist. Ich überwache das Tor mit einer Kamera.
Um die Kamera im Floorplan anzuzeigen, wenn das Tor geöffnet ist, habe ich mir folgende Lösung einfallen lassen:
ich habe mir einen zweiten „Aussenanlagen“-Floorplan gebaut, der exakt dem
normalen entspricht, aber zusätzlich einen Iframe mit der URL der passenden Kamera enthält.

Mit einen DOIF überwache ich den Status des HM-LC-SW1-FM.

define gateopenACT DOIF ([Torkontakt] eq "open") (set gateopen on, set Dum_pageswap_D /fhem/floorplan/fp_AN_gateopen) DOELSEIF ([Torkontakt] eq "closed") (set gateopen off, set Dum_pageswap_D /fhem/floorplan/fp_AN 


Bei „open“ wird  per pageswap auf den Floorplan mit dem Kamerabild  umgeschaltet.
http://www.fhemwiki.de/wiki/Browsersteuerung,_Seiten_per_JS_autom._aufrufen

Außerdem wird ein dummy auf „on“ gesetzt, der für seinen „on“-Zustand ein blinkendes Warn-Gif (devStateIcon für „on“) vor das Tor im Floorplan setzt.
Wird das Tor wieder geschlossen, wird dieser dummy auf „off“ gesetzt – das devStateIcon für „off“ ist ein transparenter Pixel - das icon verschwindet also. Dann wird per pageswap wieder auf den „normalen“ Floorplan zurückgeschaltet.

Für den Floorplan gibt es dann noch einen zusätzlichen dummy, der den Toraktor per "on-for-timer" schaltet:

define TorACT dummy
attr TorACT setList on off
attr TorACT room Aussenanlage
define TorACTon notify TorACT set Torantrieb on-for-timer 3


Und so sieht die Anzeige im Floorplan bei geöffnetem Tor aus:

Kameraüberwachung

 

Kameras:

Unsere Kameras habe ich im Floorplan „Kameras“ als iframe untergebracht. Es handelt sich um
den jpg-Link unseres Kamerarekorders, das Bild wird ständig „refresht“, ist also ein
quasi-Bewegtbild. Da das ursprüngliche Bild des Kamera-Recorders zu klein ist,
habe ich es mit folgendem Befehl skaliert:

attr cam1 htmlattr width="350" height="300" frameborder="0" marginheight="0" 
marginwidth="0" style="zoom: 1.5;;-moz-transform: scale(1.5);;-moz-transform-origin: 0 0;;-o-transform: scale(1.5);;-o-transform-origin: 0 0;;-webkit-transform: scale(1.5);;webkit-transform-origin: 0 0;;"

 

Zusätzlich zur Dropdown-Kameraauswahl habe ich mir eine html-Seite gebaut, die die jpg-links jeder unserer Kameras darstellt. Ein Klick auf eines
der kleinen Bilder stellt das Bild im großen frame dar. Bei dieser Ansicht funktioniert der refresh natürlich nicht so flüssig wie im Einzelbild. Die Seite wird alle 4 Sek. neu geladen.  Ich habe diese html-Seite in das "docs"-Verzeichnis des fhem-Servers kopiert - das fungiert nämlich als mini-html-Server. Keine Ahnung ob man das soll oder darf - es funktioniert jedenfalls. Die "Multi-Kamera"-html-Seite habe ich wieder als iframe eingebunden:

Philips Hue

 

Philips_hue:

Der Hue-Floorplan steuert alle Hue-Lampen und Lightstrips im Haus an.
Den Hintergrund der Slider für den dunklen Floorplan musste ich anpassen,
indem ich i.d. darkfloorplanstyle.css folgende Zeile hinzugefügt habe:

.colorpicker_hue .slider { background: url(/../jscolor/hue_background.svg); }


Die Buttons darunter lösen eine Debian Sendmail-Aus. Auf unseren Android-Geräten wird der Eingang der Mail anhand der
Betreffzeile per Tasker erkannt und die entsprechende App wird geöffnet. Das „Philips“-Symbol beispielsweise öffnet die App, die das Ambilight unseres Philips-TV mit dem Hue synct – da wird dann der ganze Raum zum Fernsehbild.  :D
Ein Highlight ist auch der „Disco“ Button. Der öffnet in selbiger Weise die App „Hue Disco“ und synct die Hue-Lampen zur Musik.
Die pushmail hatte ich zunächst mit „Pushover“ realisiert.
Ich habe aber festgestellt, das die Reaktion über debian-sendmail schneller ist.
Mit sendmail dauert es ca. 3 Sekunden, bis sich die gewünschte App öffnet.

Heizungssteuerung

 

Heizung:

Der Heizungs-Floorplan vereint die Steuerung aller Thermostaten und zeigt die Plots der entsprechenden
Temperaturverläufe an. Da die Beschriftung der Plots im dunklen Floorplan nicht zu sehen war, habe ich die
svg_style.css angepasst wie hier beschrieben:
http://forum.fhem.de/index.php/topic,20882.msg144114.html#msg144114

Zusätzlich wird im Floorplan Heizung der Heizölstand im Tank angezeigt:

Heizölstand messen per Ultraschall


Messung des Heizöl-Standes per Ultraschall

Da unser Heizöltank bisher nur einen höchst ungenauen analogen Füllstandstandsanzeiger (so ein Schätzeisen mit Schwimmer) hatte,
habe ich nach einer Lösung der Ölstandsanzeige mit fhem gesucht.
Im Netz bin ich auf die Lösung von Bracew mit einem Ultraschallsensor gestoßen, der den Abstand zur Flüssigkeitsoberfläche misst.

Der Ultraschallsensor (DYP-ME007Y) ist so ein Teil wie es auch für die Rückfahrwarner bei Autos benutzt wird.
Das Modul kostet aktuell 15,99€ beim großen Internethändler mit „A“. Meiner kam direkt aus China, das hat ca. 2 Wochen gedauert.

Der Sensor wird an die GPIO eines RasPis angelötet – hier gibt es eine Anleitung und das passende Script zur Auswertung der Messdaten:

http://www.gtkdb.de/index_36_2272.html

Die Beschreibung ist für einen anderen Sensor, der oben erwähnte hat aber die gleichen Anschlüsse.
Bracew hat das ganze für fhem aufbereitet:

http://www.forum-raspberrypi.de/Thread-haussteuerung-heizoel-tankstand-oder-verbrauchs-fernablesung-mit-raspi-geloest-beitrag-21?pid=115200#pid115200


Per cronjob wird in festgelegten Intervallen die Messung gestartet, in eine Log-Datei kopiert und diese Log-Datei wird per
SFTP (von einem weiteren cronjob) an das log-Verzeichnes des fhem-Pis geschoben.
Aus den Messdaten wird dann ein Plot erstellt. Die Tankgröße und der Montageabstand kann im Meßscript angepasst werden –
da unser Tank nur 2000 Liter fasst, habe ich das auch getan.

Der "HeizPi" muß nicht im Tank-Raum sitzen, das Kabel am Sensor ist ziemlich lang:

Ich bin während der Umsetzung/Installation auf einige Schwierigkeiten/Fehlermeldungen, usw. gestossen – hier die Lösungen:
1) folgende Erweiterungen für script-Ausführung und SFTP fehlten im Standard-Raspbian meines Mess-Pis und mussten von Hand nachinstalliert werden:
expect

sudo apt-get install expect

und der tcl-interpreter

sudo apt-get install tcl8.4


2) Der Zugriff auf die GPIO muß als root erfolgen. Mit sudo crontab -e sollte ja eigentlich die cronjob-Tabelle von root  erstellt werden
(so habe ich das zumindest verstanden), ich musste für den Mess-Cronjob jedoch noch extra ein „sudo“ vorstellen:

10 0,6,12,18 * * * sudo /home/HeizPi/ultrasonic.py >> /home/HeizPi/Heizoel.log

(Beispiel für 4xtägl. Messung)

3) Der cronjob für die SFTP-Übertragung sollte eine Minute später als die Messung erfolgen, da diese ein paar Sekunden dauert.
Ist nicht so wichtig, da die log-Datei ja in jedem Fall geschrieben wird und bei der nächsten Übertragung dann mitgesendet wird.
Gibt halt nur keine zeitnahme Messung. Bracew misst übrigens 4x täglich, ich messe bisher stündlich – einfach, um zu sehen ob alles klappt.

Ich habe den Sensor – wie Bracew – in das Entlüftungsrohr meines Tanks montiert.
Da der Mindest-Messabstand des Sensors lt. Datenblatt 30cm beträgt, ist so eine korrekte Messung auch bei vollem Tank gewährleistet.

 

Heizölstand messen per Einperl-Sensor

Messung des Heizöl-Standes per Einperl-Sensor

Der Ultraschall-Sensor im Tank hatte für mich irgendwie die ganze Zeit ein "Geschmäckle" (wegen Strom in der Nähe des Brennstoffes). Ich habe mir jetzt ein E-Litro-Net bestellt. Das Ding arbeitet mit einem  Einperl-Sensor. Über einen Plastikschlauch wird ein klein wenig Luft in der Tank gepustet. Der hydrostatische Druck über der Einperlöffnung wird mit dem barometrischen Aussenluftdruck verglichen. Aus der Differenz ergibt sich dann die Höhe der Flüssigkeitssäule - also der Ölstand.  Es befindet sich also lediglich ein Plastikschlauch im Tank  - die Elektronik ist weit davon entfernt.

Der E-Litro Net hat eine html-Oberfläche. EInen Demo-Link gibt es auf der Herstellerseite. Mit dem Zusatz

/xml

 

gibt das Teil zusätzlich eine xml-Datei aus. Mit dem FHEM-Modul httpmod lese ich aus dieser Datei den Wert "tankLevel" aus

define OelTank httpmod http://IP_meines_E-Litro/xml 14400
attr OelTank reading01Name Level
attr OelTank reading01Regex (?s)tankLevel>([\d]+)
attr OelTank stateFormat Level
define FileLog_OelTank FileLog ./log/OelTank-%Y-%m.log OelTank.*

 

Die Zahl hinter der URL ist der Abfrage-Intervall in Sekunden.

Für das ganze habe ich mir dann noch einen Plot für den Floorplan gebaut:

Zusätzlich zur Messwerterfassung "Level"  habe ich mir noch einen httpmod-Dummy für den Wert "tankPercent" in der xml-Datei des E-Litro gebaut.

define OelStatusdummy httpmod http://IP_meines_E-litro/xml 14400
attr OelStatusdummy reading01Name tankPercent
attr OelStatusdummy reading01Regex (?s)tankPercent>([\d]+)
attr OelStatusdummy stateFormat tankPercent


Der Dummy soll per icon den Level des Ölstandes mit levelabhängigem devStateIcon grob anzeigen.
Das habe ich mir beim Rolladen abgeguckt (siehe Icon für Rolladen Status):
Beschreibung im FHEM-Wiki

Für den Level habe ich das FHEM-WLAN-Icon mit Gimp umgebaut, level5.png zeigt 5 volle Striche, level1.png nur einen und level0.png ein Warndreieck für "Heizöl nachbestellen":

attr OelStatusdummy devStateIcon 9\d.*:level5.png 8\d.*:level5.png 7\d.*:level4.png 6\d.*:level4.png 5\d.*:level3.png 4\d.*:level3.png 3\d.*:level2.png 2\d.*:level1.png 1\d.*:level0.png 0\d.*:level0.png

 

100% wird nicht vorkommen, da der Grenzwertschater bei 95% auslöst. Also kann die 1\d.* nur einmal vorkommen.

Im Floorplan sieht das dann so aus:

Somit habe ich jetzt eine 100% sichere Messwerterfassung ohne elektrische Sensorik in der Nähe des Tanks.

Wettervorhersage

Wetter

Im Floorplan Wetter wird ein Satellitenbild, ein Regenradar sowie nochmal das Yahoo-Wetter (diesmal vertikal)
angezeigt. http://forum.fhem.de/index.php/topic,33610.0.html

Multimedia

 

Multimedia:

Der Floorplan „Multimedia“ steuert unsere Dreambox. Diese ist zentral im Haus über einen HDMI-Verteiler eingespeist und kann
direkt über das Enigma-Interface angesprochen werden.
Zusätzlich werden über die entsprechenden dummys unter „TV Wohnzimmer“, „Hifi Wohnzimmer“ 
und „TV Schlafzimmer“ zwei Harmony-Hubs angesprochen. Damit sind dann auch Makros möglich (TV, Dreambox und Hifi gleichzeitig an/aus)

Ich hatte die Philips-TVs zuerst über das Philips Smart TV Remote für JointSpace
angesteuert.
http://forum.fhem.de/index.php?topic=16189.0

Das hat auch sehr gut funktioniert – das Problem dabei ist allerdings , dass  die Philips-TVs
den Modus „schnelle Inbetriebnahme“ erfordern (ansonsten schlafen die TVs komplett und sind über LAN nicht ansprechbar).
Leider kann man diesen Modus nicht permanent aktivieren sondern nur einen „Zeitrahmen“ angeben. Diese "Zeitrahmen sind max.
2h lang und es gibt 3 Stück davon - ergibt also maximal 6h „Aufweckbarkeit“ durch fhem...
Ich mache die Steuerung mittlerweile über Harmony-Hubs, das funktioniert super und ohne diese Einschränkung.

Ich habe allerdings zusätzlich das Modul PHTV aktiviert.
http://fhem.de/commandref.html#PHTV

Ich frage das Reading "presence" des TV im Wohnzimmer damit ab. Weil: es passiert schon mal, dass man im Schlafzimmer die falsche Taste drückt
(ist ja alles auf einem Floorplan) und versehntlich den "falschen TV" einschaltet.
Ein kleiner Statusdummy auf dem Floorplan zeigt dann an, ob der TV im Wohnzimmer läuft - wenn nicht, ist das icon unsichtbar:

define WZTVpresent dummy
attr WZTVpresent setList on off
attr WZTVpresent devStateIcon on:set_on.png off:transparent.png
define WZTVpresentACT DOIF ([PhilipsTV:presence] eq "present") (set WZTVpresent on) DOELSEIF ([PhilipsTV:presence] eq "absent") (set WZTVpresent off)

Der Modus "schnelle Inbetriebnahme" muß am TV dafür abgeschaltet sein, sonst ändert sich das Reading erst, wenn der TV in den Tiefschlaf fällt.

In einem iframe habe ich dann noch das Dreambox-Webinterface eingefügt – da kann man die Programme direkt klicken und sieht auch das
vollständige EPG.

Bei Klick/Touch auf das Fernbedienungs-Symbol gelangt man zusätzlich auf den Floorplan „Remote“.
Dort sind die wichtigsten Sender als dummy mit den "Picons" der Dreambox dargestellt und wiederum klick/touchbar.

Einkaufsliste

 

Einkaufsliste

Wir nutzen schon seit einiger Zeit die App "denkst-du-daran" auf unseren Androiden. Das ist eine cloudbasierte Einkaufsliste die sich auf allen Geräten
synchronisiert. Wir können also am Handy ablesen, was gerade fehlt. Da dieser Dienst auch ein frontend für den browser besitzt,
habe ich einen Floorplan drumrum gebaut (iframe). Wenn in der Küche das Olivenöl zur Neige geht, kann man also ganz einfach
einfach einen Eintrag (z.B. am wandhängenden Tablet) hinzufügen und derjenige, der gerade bei Aldi vorm Regal steht bekommt die Änderung sofort mit  :)

Multiroom-Audio mit Squeezebox

 

Multiroom-Audio mit Squeezebox

Das Lautsprechersymbol oder der Menüpunkt "Multiroom" leitet weiter zum Floorplan "Multiroom".

Mit dem quelloffenen Logitech Sqeezebox Server ist es möglich, synchrones Audio auf mehrere Audio-Clients

zu verteilen. Bei mir laufen sowohl der Logitech-Server als auch die Clients jeweils auf einem Raspberry PI.

Ich habe mittlerweile 7 Pis als Client laufen und entweder an eine PC-Aktivbox gespaxt oder an eine vorhandene Hifi-Anlage
angeschlossen:

Und über der Badewanne:

Wie bei einem Profi-Multiroom-System ist übrigens bei der Logitech Geschichte echtes synchrones Audio möglich.

Ein weiterer Vorteil für mich ist der Einsatz von piCore-Playern auf meinen Pis – diese laden Ihr komplettes
„Mini-Squeezebox-Client-Linux“ nach dem booten ins RAM – es wird also nichts auf der SD geschrieben und es kann
sogar im Betrieb der Stecker gezogen werden ohne die SD-Karte zu crashen.

Aber der Reihe nach – so habe ich das umgesetzt:

1) Installation des Logitech Squeezebox-Servers auf einem PI 2  (mit Raspbian)
nach dieser Anleitung:

http://allthingspi.webspace.virginmedia.com/lms.php

Der Squeezebox-Server kann nach der Installation vollständig über sein webinterface
(IP_des_Squeezebox_Servers:9000) konfiguriert werden.
Ich habe meine Musik auf einem NAS, das muß natürlich auf dem PI gemounted werden.
Im webinterface unter „Einstellungen“ habe ich ein playlisten-Verzeichnis definiert.
Für meine Radiosender habe ich einfach eine .m3u-Datei erstellt, die die Stream-URL des Senders enthält.
Diese Datei habe ich per ftp auf den Squeezebox-Server geschoben.
Die Playlisten für die Musik von meiner NAS-Platte können sehr komfortabel im webinterface des LMS erstellt und gespeichert werden.

2) Installation der PiCore-Player auf den Client-Pis:

https://sites.google.com/site/picoreplayer/home

Bei der Installation hatte ich 2 Probleme:

a) Der piCorePlayer soll sich auch per eigenem webinterface konfigurieren lassen. Bei mir wurden
Änderungen nach einem reboot jedoch nicht übernommen. Ist evt. Ein Linux-Rechteproblem -
egal – es gibt eine Datei auf der Boot-Partition der erstellten SD-Karte, die heisst newconfig.cfg.
In diese Datei kann man alles eintragen: Player-Name, WLAN ja/nein, SSID, WLAN pw usw.

b) Bei Playern die über LAN angebunden sind, wird als standard die MAC-Adresse 00:00:00:00:00:00 eingetragen.
Der Logitech Server kommt mit 2 gleichen Mac-Adressen aber nicht klar, also muß diese unbedingt geändert werden.
Ich habe einfach die letzte Stelle geändert also xx.xx.xx.01, xx.xx.xx.02 usw.
Die Änderung kann man ebenfalls in der .cfg-Datei vornehmen.

3) Ich habe mir die Module SB_SERVER und SB_PLAYER für fhem heruntergeladen

...und den Server per „define“ eingebunden wie hier beschrieben:

http://forum.fhem.de/index.php?topic=17667.0

Per autocreate wurden sofort alle piCorePlayer erkannt. Diese habe ich dann umbenannt.
Weil: der Name im FHEM muß mit dem Namen im Squeezebox-Server identisch sein

4) Ich habe mir einen floorplan gebastelt:

Ich habe die SB_PLAYER eingebunden.
Per "attr Mein_SB_PLAYER_Kueche webcmd playlists:volume" bekomme jetzt ich den Lautstärke-Slider
und ein dropdown-Menü für alle Playlisten des Squeezbox-Servers.

Ich hatte das Problem, dass  das devStateIcon des Players im Floorplan sich nur bei jedem 2. Klick oder bei browser refresh
aktualisiert hat.

http://forum.fhem.de/index.php/topic,30139.msg287151.html#msg287151


Das Atrribut "donotnotify" des Players muß auf "false" gesetzt werden, dann geht es.
(Diese Einstellung ist auch für das ordnungsgemäße Aktualiseren der readings "currentTitle" und "currentArtist" notwendig - siehe weiter unten)
Um damit nicht zuviele events zu erzeugen, habe ich folgendes Attribut gesetzt (Danke kvo1! ):

attr Mein_SB_Player event-on-change-reading currentTitle,currentArtist,state


Ich habe mir einen zusätzlichen dummy gebaut, weil ich zusätzlich noch die Stromversorgung meiner
Aktiv-Lautsprecher an- und abschalten möchte:   *** siehe Hinweis "Update 2"

define JNSKuechePower dummy
attr JNSKuechePower room SB_PLAYER
attr JNSKuechePower setList on off
attr JNSKuechePower devStateIcon off:mroom_kueche.off.png on:mroom_kueche.on.png
define JNSKuechePowerAn notify JNSKuechePower:on
set Kueche on;set JogiNetAudio5Power on;set Kueche play
define JNSKuechePowerAUS notify JNSKuechePower:off
set Kueche off


Ich lasse für den im floorplan eingebundenen SB-Player (hier heisst der „Kueche“) also nur „commands only“ anzeigen, dann
werden die webcmds „volume und playlists“ angezeigt, den dummy setze ich direkt darüber.

Zusätzlich lasse ich mir den gerade gespielten Titel/Interpreten
per readings-group anzeigen:

define KuecheText readingsgroup Kueche:currentTitle,currentArtist
attr KuecheText room SB_PLAYER
attr KuecheText noheading 1
attr KuecheText nonames 1
attr KuecheText notime 1
attr KuecheText style style="color:lightblue;font-size:15px"
attr KuecheText visibility hidden


Um diese Readings nur bei aktivem Player einzuschalten, habe ich ein weiteres DOIF erstellt:

define KuecheTextVis DOIF ([Kueche] eq "on") (set KuecheText visibility show) DOELSEIF ([Kueche] eq "off") (set KuecheText visibility hide)
attr KuecheTextVis room SB_PLAYER


Jetzt zum syncen der Einzelnen Player:
Ich möchte die Möglichkeit haben, jeden Player mit jedem anderen Player zu syncen.
Also habe ich mir für jeden Sync einen dummy gebaut.
Am Player „Kueche“ beispielsweise hängt also für jedes meiner anderen Geräte ein dummy:

define JNSsyncKuecheAussen dummy
attr JNSsynxKuecheAussen room SB_PLAYER
attr JNSsyncKuecheAussen setList on off
attr JNSSyncKuecheAussen devStateIcon on:aussen_ticked.png off:aussen_unticked.png


ein notify für „An“ synct den Player mit dem gewünschten Gerät und schaltet den entsprechenden
Verstärker (per Homematic-Schalter) mit ein:

define JNSsyncKuecheAussenAN notify JNSsyncKuecheAussen:on set JNSAussenPower on;set Kueche sync Aussen;set Kueche play


das „Aus“-Notify entfernt den Player aus der Sync-Gruppe:

define JNSsyncKuecheAussenAUS notify JNSsyncKuecheAussen:off set JNSAussenPower off;set Aussen unsync


So einen dummy habe ich jetzt für alle devices angelegt, für die Küche also:

Zitat
define JNSsyncKuecheWohnzimmer dummy,...
define JNSsyncKuecheBad dummy...
blabla...


Ergibt bei mittlerweile 7 Playern die sich jeweils mit den anderen 6 Playern syncen können sollen 42 dummys.
Wird für einen Player ein weiterer dummy geklickt, hängt sich der jeweilige Player einfach an die sync-Gruppe dran.

(in diesem Beispiel sind Bad und Wohnzimmer mit dem Player im Arbeitszimmer gesynct)

Für das Anlegen der vielen dummys Ist ein bischen Fleißarbeit erforderlich. Theoretisch kann man den sync auch in ein webcmd legen.
Ich fand es aber so wesentlich übersichtlicher.

So sieht es im floorplan aus (im Beispielbild läuft im Arbeitszimmer "Radio Latina", das Bad und das Wohnzimmer sind dazugesynct.
Parallel läuft im Schlafzimmer "Alsterradio")

Es ist also auch möglich, in Zimmer  A Sender/playlist X „gesynct“ zu hören, während im Zimmer B Sender/Playlist Y spielt.
Ist schon sehr komfortabel und - wie gesagt - auf meinen Pis absolut synchron.
Wenn ich zusätzlich eine andere Hardware (z.B. Tablet mit Player-App)
als Player laufen lassen möchten, ergibt sich evt. aus der unterschiedlichen Hardware ein Zeitversatz. Diesen kann man auf
der web-Oberfläche des LMS unter Einstellungen/Player anpassen.

Die Buttons play,pause,<<,>> habe ich über das Modul "remotecontrol" / layout "itunes" eingebunden - notify auf die SB_Player.

Zu guter letzt habe ich mir noch einen dummy „alle Zonen aus“ angelegt – damit wird auf Knopfdruck alles auf Null gesetzt.

Ich habe dann mal gemessen (da ich LTE habe bekomme ich den Verbrauch von Vodafone angezeigt).
Über eine Stunde verbraucht ein Internetradiosender bei mir zwischen 60 und 80MB.
Und zwar UNABHÄNGIG davon, ober der Stream nur auf einem SB-Player oder auf 5 SB-Playern gleichzeitig läuft.
Der Server greift also immer nur einen Stream aus dem Internet ab.

Stream des Sounds vom lokalen PC (z.B. Youtube, usw.):

Zum Stream des lokalen Desktop-Sounds:

Ich habe lange mit dem wavein-plugin experimentiert - leider ohne Ergebnis. Das kann daran liegen, dass ich das ganze "Pulse-Audio"-Geschehen
auf meinem Linux-PC nicht verstanden haben.

Egal - ich bin im Netz auf eine simple Lösung per VLC gestossen:

http://confoundedtech.blogspot.de/2014/10/pc-audio-music-to-squeezebox-without.html

Die Beschreibung ist für Linux, sollte sich aber auch auf Windows übertragen lassen (Firewall-Ports freigeben funktioniert natürlich dann über die entsprechenden Windows-Einstellungen).

Per

cvlc pulse://alsa_output.pci-0000_00_1b.0.analog-stereo.monitor :sout='#transcode{vcodec=none,acodec=mp3,ab=320,channels=2,samplerate=44100}:http{dst=:8081/pc-stream.mp3}' :no-sout-rtp-sap :no-sout-standard-sap


starte ich den Stream auf meinem lokalen PC.

 Auf dem Squeezebox-Server kann ich jetzt eine URL öffnen:

IP_MEINES-PCS:8081/pc-stream.mp3- es wird dann alles wiedergegeben, was mein lokaler PC auch abspielt.

Diese URL kann natürlich auch als Favorit oder playlist-Datei eingebunden werden.

Latenz: ca. 1 Sekunde - also bei Youtube-Videos nicht so ganz "lippensynchron" aber brauchbar f.d. Partymodus  :)

 

Einbindung einer Durchsage-Option per email für das Squeezebox-Audiosystem

Es kommt des öfteren vor, dass einer von uns bei der Gartenarbeit oder beim Ausmisten der Ställe keinTelefon dabei hat.
"Hast Du denn das Telefon nicht gehört? ..."

Da ich - natürlich  ;D - Stall und Terrasse mittlerweile mit  Squeezebox-Pis bestückt habe,
habe ich überlegt, eine email an fhem zu schicken und diese dann über die Squeezeboxen vorlesen zu lassen.
Hier meine Lösung mit der "talk"-Funktion des Squeezebox-Moduls:

1) Ich habe mir eine Durchsage-emailadresse angelegt.
Die ist natürlich streng geheim – wer die hat, der spricht schließlich mit unserem Haus...
Ich hoffe, diese Adresse landet niemals in einem Spamverteiler...   ;D

2) Ich habe mit dieser Anleitung den imap-Empfang unter fhem eingerichtet:
http://blog.jenconsulting.de/?p=152

3) ich habe eine mp3-Sounddatei (gong.mp3) auf den Squeezebox-Server geladen

4) Ich habe mir ein notify gebaut, das auf den Posteingang einer mail reagiert:

define Durchsage notify FhemMail set JNSKuechePower on;set JNSsyncKuecheAussen2 on;set JNSsyncKuecheBad on;set JNSsyncKuecheArbeitszimmer on;set JNSsyncKuecheWohnzimmer on;set JNSsyncKuecheSchlafzimmer on;set JNSsyncKuecheAussen on;sleep 5;{fhem("set Kueche talk Achtung Es folgt eine Durchsage |/home/pi/gong.mp3| ".ReadingsVal("FhemMail","Subject",""))};sleep 25;set alloff on;sleep 5;set Dum_pageswap_D /fhem/floorplan/Message;{fhem("set Dream1 showText ".ReadingsVal("FhemMail","Subject",""))};set alloff on

Dieses notify erledigt folgendes:

a) es schaltet den Player in der Küche an
b) es schaltet meine Sync-dummys an.
(siehe Beschreibung http://forum.fhem.de/index.php/topic,33088.msg288020.html#msg288020)
Alle Player werden also mit der Küche gesynct und diese wiederum schalten dann Ihren Verstärker, usw. an.

c) es wird ein Gong und danach ein „Achtung, es folgt eine Durchsage“ abgespielt - danach wird das Reading der Betreffzeile der eingehenden email vorgelesen.
(Wie gesagt nur die Betreffzeile - hier muß die Nachricht rein - der Inhalt der mail ist irrelevant)

d) Mein alloff dummy schaltet alle player ab. Wer irgendwo Musik gehört hat, muß wieder einschalten – Pech gehabt.
Außerdem unterstreicht das ja die Wichtigkeit der Durchsage  :D
Aber im Ernst: um selektiv an- und auszuschalten müßte ich im Vorwege prüfen, welcher Player gerade läuft – das kommt dann später...

e) per pageswap-dummy werden alle auf den Tablets oder PCs aufgerufenen Floorplans auf den Floorplan „Message“ umgeleitet
Beschreibung – siehe hier:

http://www.fhemwiki.de/wiki/Browsersteuerung,_Seiten_per_JS_autom._aufrufen

f) Zusätzlich wird der Inhalt des email-Readings i.d. laufende TV-Programm unserer Dreambox eingeblendet

Spätestens jetzt sollte jeder die Nachricht erhalten haben  ;D

5) für den floorplan „Message“ habe ich eine readingsGroup angelegt,
die die letzte Nachricht mit Datum und Uhrzeit anzeigt:

define mail_message readingsGroup FhemMail:Subject
attr mail_message room SB_PLAYER
attr mail_message style style="color:lightblue;;text-align:center;;font-size:25px"
attr mail_message timestampstyle style="color:magenta;;text-align:center;;font-size:15px"
attr mail_message cellStyle style="font-weight:bold;;font-size:16px
attr mail_message noheading 1
attr mail_message nonames 1


Und so sieht es dann auf allen Displays aus:

Anzeige der 35 zuletzt gespielten Titel unserer Squeezebox-Player:

Oft hören wir einen Titel im Radio, den wir später gerne im Internet als mp3 käuflich erwerben möchten.
Bis dato mussten wir dann immer die Playlist-Recherche auf der Internetseite des jeweiligen Senders aufrufen.
Das ist jetzt Geschichte - mein "Musiktitel-Floorplan" sammelt Titel- und Interpreten-Readings.
Das geht ganz easy mit einer "readingsHistory":

define Musiktitel readingsHistory SB_Player1:currentTitle,currentArtist SB_player2:currentTitel,currentArtist SB_Player3:currentTitel,currentArtist
attr Musiktitel style style="color:lightblue;;text-align:left;;font-size:15px"
attr Musiktitel rows 35


Und so sieht es dann im floorplan aus:

 

Da kann man dann schnell mal nachschauen. Ein direkt generierter Link zur Suche im Amazon-Shop wäre natürlich genial - das liesse sich bestimmt
über die Such-URL+Reading lösen  ;D

Multiroom-Audio mit Kodi

 

Multiroom-Audio mit Kodi

Der Vollständigkeit halber sei hier noch eine weitere Multiroom-Audiovariante erwähnt: Ich hatte mir - vor der Squeezebox-Varaiante - eine Multiroom-Audioversion mit Kodi/XBMC-Clients gebaut. Auch diese lassen sich mit FHEM perfekt steuern, die Audio-Wiedergabe ist jedoch nicht synchron. Über einen mdp-Server hatte ich mir dazu noch eine Möglichkeit der "Stream-Bündelung" einfallen lassen. Hier die Beschreibung der damiligen Version:

Die OpenElec/Kodi-Geschichte steuere ich "headless" mit dem Modul "xbmc".
Das Booten erledigt ein Homematic-Schalter (weil der PI kein WOL kann), die Aktivbox wird gleich mit aktiviert.
Zusätzlich habe ich die "remote" des xbmc-Moduls eingebunden für Laut/Leise/Mute/Stop.
Die von uns meist gehörten Radiostreams habe ich als Favoriten-Dummies angelegt. Per "set MeinAudio1 open stream-URL"
kann ich den passenden Stream öffnen. Und das geht für jeden Raum - auch separat:

 

Der weblink "Playlists" führt zum jeweiligen Floorplan "Playlists". Links unten sind vordefinierte kodi-Listen (80er, 90er, blabla).
Touch/Klick genügt. Die Listen editiere ich am PC und schiebe die per Filezilla auf die Rasbpis.
Ausserdem ist die "Chorus" Oberfläche von kodi als iframe in den Floorplan integriert. Für benutzerdefinierte Playlisten,
weitere webradios, usw.:

Für die Radiosender meiner „Multiroom“-Lösung habe ich mir folgende Erweiterung ausgedacht:
Es ist – wie ich ja schon beschrieben habe – möglich, in jedem Raum auf einem OpenElec-PI einen anderen Radiosender
zu hören. Ein Floorplan-dummy öffnet dabei über das XBMC-Modul  den jeweiligen Stream.

Da wir hier auf dem Land über LTE ins Internet gehen, nagt dass natürlich am Traffic (30GB ist das Limit) wenn alle Räume
den gleichen Sender hören (denn dann wird ja für jeden Raum ein Stream gestartet).

So ein Radiosender frisst ja nicht sooo viel, aber wir hören halt auch sehr viel Radio und es laufen ja auch noch weitere
Dienste, die am Trafficlimit zehren. Die Lösung, die mir dazu eingefallen ist, ist evt. etwas aufwändig, funktioniert aber prächtig.

Allerdings: Der Code (was hat sich der Künstler dabei gedacht?) ist wohlmöglich optimierungsfähig, kürzbar und effizienter zu gestalten.
Ich bin halt weder Programmierer noch fhem-Profi. Wer sowas in ein Perl-Script auslagern kann o.ä. - ich bin für Input
dankbar & aufgeschlossen. Hier jedenfalls meine McGyver-Lösung:

Ich habe mir zunächst auf einem freien RasbpPi 2 einen mpd-Server installiert
http://forum.fhem.de/index.php/topic,35428.0.html
 und mir für jeden „Favouriten-Radiosender“ eine Playlist angelegt – also eine m3u-Datei, die lediglich die
URL des jeweiligen Senders beinhaltet.

Ich zähle dann einfach die Zahl der aktiven Dummys mit einem DOIF.
Ich habe insges. 5 Räume, in denen ein RasbPi mit OpenElec läuft.
Wenn in mehr als einem Raum der gleiche Sender läuft, dann wird per fhem die Stream-URL vom
eigentlichen Stream auf die Netzwerkadresse des mpd-Servers umgeschaltet und der mpd-Server wird veranlasst,
die Playlist des jeweiligen Senders abzuspielen.
http://forum.fhem.de/index.php?topic=18517.0

Zum Schluß wird ein „Statusdummy“  im Floorplan gesetzt. Blinkt der dummy grün, ist es ein Einzelstream, blinkt der
dummy rot ist es ein Stream des mpd-Servers.
Beispiel: hier laufen auf den PIs der Räume "Multiroom Aussen" und "Multiroom Bad" der gleiche Sender (Streams sind zusammen-
geschaltet) und im "Multiroom Schlafzimmer" läuft ein anderer Sender:

Das würde natürlich mit allen playlisten – nicht nur mit Radiosendern laufen.

Funktionieren tut das Ganze so (am Beispiel „Alsterradio“):

Zuerst definiere ich für jeden Sender einen Dummy für den Radiostream
(Auswahl normaler Stream oder mpd-Server-Zugriff):

define  streamurl_alsterradio dummy
attr  streamurl_alsterradio room xbmc
attr  streamurl_alsterradio setList http://live96.106acht.de http://192.168.0.70:8000
set streamurl_alsterradio http://live96.106acht.de


zusätzlich gibt es einen „Statusdummy“ für jede Betriebsart und für jeden OpenElec-PI (JNA1-5):

define JNA1wait dummy
attr JNA1wait setList on off active server achtung
attr JNA1wait devStateIcon on:wait.png off:transparent.png active:green_blink.gif server:red_blink.gif achtung:achtung.gif


Beim Einschalten eines RasbPis wird dieser dummy auf „wait“ gesetzt
(dann erscheint ein „bitte warten“),  danach auf „off“, das ist ein transparenter Pixel:

Wird ein Einzelstream abgerufen (active), blinkt ein grünes Licht (animiertes gif)
und im Serverbetrieb (also mehr als ein Einzelstream des gewünschten Senders)
blinkt ein rotes gif (Status: „server“) - siehe oben.

Der Status „achtung“ erscheint, sobald mehr als 2 Serverstreams laufen – da ich nur eine mpd-Instanz
laufen habe, geht das ja nicht (siehe weiter unten)

Bei klick oder touch auf den jeweiligen floorplan-dummy wird der stream gestartet und
wie bei Omas Dampfradio „springen die anderen Radiotasten heraus“, sobald man eine drückt:

define alsterradioJNA1 dummy
attr alsterradioJNA1 room xbmc
attr alsterradioJNA1 setList on off
define alsterradioJNA1An notify alsterradioJNA1:on {fhem('set JogiNetAudio1 open '.Value('streamurl_alsterradio'));;fhem('set radiolatinaJNA1,skyrockJNA1,ouifmJNA1,radio538JNA1,ndr2JNA1,ndr1shJNA1,rshJNA1 off')}
define alsterradioJNA1Aus notify alsterradioJNA1:off set JNA1wait off


Ein DOIF guckt, wieviele Alsterradio-dummys gerade betätigt sind, setzt die Stream-URL entsprechend und selektiert
die playlist des mpd. So ein DOIF braucht es für jeden meiner 8 Favouriten.
(Es hat sich als am praktikabelsten erwiesen, den Text mit copy & paste in eine Textverarbeitung zu kopieren.
Ich benutze LibreOffice. Über „finden & ersetzen“ tauscht man dann einfach den Sendernamen aus und braucht nur noch
die Stream URL händisch zu ändern):

define multi_alsterradio DOIF (([alsterradioJNA1] eq "on" and [alsterradioJNA2] eq "off" and [alsterradioJNA3] eq "off" and [alsterradioJNA4] eq "off" and [alsterradioJNA5] eq "off") or ([alsterradioJNA1] eq "off" and [alsterradioJNA2] eq "on" and [alsterradioJNA3] eq "off" and [alsterradioJNA4] eq "off" and [alsterradioJNA5] eq "off") or ([alsterradioJNA1] eq "off" and [alsterradioJNA2] eq "off" and [alsterradioJNA3] eq "on" and [alsterradioJNA4] eq "off" and [alsterradioJNA5] eq "off") or ([alsterradioJNA1] eq "off" and [alsterradioJNA2] eq "off" and [alsterradioJNA3] eq "off" and [alsterradioJNA4] eq "on" and [alsterradioJNA5] eq "off") or ([alsterradioJNA1] eq "off" and [alsterradioJNA2] eq "off" and [alsterradioJNA3] eq "off" and [alsterradioJNA4] eq "off" and [alsterradioJNA5] eq "on") or ([alsterradioJNA1] eq "off" and [alsterradioJNA2] eq "off" and [alsterradioJNA3] eq "off" and [alsterradioJNA4] eq "off" and [alsterradioJNA5] eq "off")) (set JogiNetMPD stop, set streamurl_alsterradio http://live96.106acht.de) DOELSE (set JogiNetMPD playlist alsterradio.m3u, set streamurl_alsterradio http://192.168.0.70:8000)


Zusätzlich wird geguckt ob mpd-Server-Betrieb oder nicht:

define server_alsterradio dummy
attr server_alsterradio room xbmc
attr server_alsterradio setList on off
define serveract_alsterradio DOIF ([streamurl_alsterradio:state] eq "http://192.168.0.70:8000") (set server_alsterradio on) DOELSEIF ([streamurl_alsterradio:state] eq "http://live96.106acht.de") (set server_alsterradio off)

attr serveract_alsterradio do always


Wenn sich der Streamstatus ändert (also mpd-Server oder nicht) wird „Staus-dummy“ gesetzt und der Stream neu gestartet:

define state_alsterradioJNA1wait DOIF (([alsterradioJNA1:state] eq "on" and [server_alsterradio:state] eq "on"))(set JNA1wait server,{fhem('set JogiNetAudio1, open '.Value('streamurl_alsterradio'))} ) DOELSEIF (([alsterradioJNA1:state] eq "on" and [server_alsterradio:state] eq "off"))(set JNA1wait active,{fhem('set JogiNetAudio1 open '.Value('streamurl_alsterradio'))} )
attr  state_alsterradioJNA1wait  do always


Wenn – wie oben erwähnt mehr als 2 Streams aus der einen mpd-Instanz abgerufen werden sollen,
muss das ganze zurückgesetzt werden. Überwacht wird das mit einem weiteren DOIF:

define streamcount dummy
attr streamcount setList zuviele_streams streams_ok
attr streamcount room xbmc
define multi_serverzugriff DOIF (([server_latina] eq "on" and [server_skyrock] eq "off" and [server_radio538] eq "off" and [server_ouifm] eq "off" and [server_ndr2] eq "off" and [server_ndr1sh] eq "off" and [server_rsh] eq "off" and [server_alsterradio] eq "off") or ([server_latina] eq "off" and [server_skyrock] eq "on" and [server_radio538] eq "off" and [server_ouifm] eq "off" and [server_ndr2] eq "off" and [server_ndr1sh] eq "off" and [server_rsh] eq "off" and [server_alsterradio] eq "off") or ([server_latina] eq "off" and [server_skyrock] eq "off" and [server_radio538] eq "off" and [server_ouifm] eq "off" and [server_ndr2] eq "off" and [server_ndr1sh] eq "off" and [server_rsh] eq "off" and [server_alsterradio] eq "off") or ([server_latina] eq "off" and [server_skyrock] eq "off" and [server_radio538] eq "off" and [server_ouifm] eq "on" and [server_ndr2] eq "off" and [server_ndr1sh] eq "off" and [server_rsh] eq "off" and [server_alsterradio] eq "off") or ([server_latina] eq "off" and [server_skyrock] eq "off" and [server_radio538] eq "off" and [server_ouifm] eq "off" and [server_ndr2] eq "on" and [server_ndr1sh] eq "off" and [server_rsh] eq "off" and [server_alsterradio] eq "off") or ([server_latina] eq "off" and [server_skyrock] eq "off" and [server_radio538] eq "off" and [server_ouifm] eq "off" and [server_ndr2] eq "off" and [server_ndr1sh] eq "on" and [server_rsh] eq "off" and [server_alsterradio] eq "off") or ([server_latina] eq "off" and [server_skyrock] eq "off" and [server_radio538] eq "off" and [server_quifm] eq "off" and [server_ndr2] eq "off" and [server_ndr1sh] eq "off" and [server_rsh] eq "on" and [server_alsterradio] eq "off") or ([server_latina] eq "off" and [server_skyrock] eq "off" and [server_radio538] eq "off" and [server_ouifm] eq "off" and [server_ndr2] eq "off" and [server_ndr1sh] eq "off" and [server_rsh] eq "off" and [server_alsterradio] eq "on") or ([server_latina] eq "off" and [server_skyrock] eq "off" and [server_radio538] eq "off" and [server_ouifm] eq "off" and [server_ndr2] eq "off" and [server_ndr1sh] eq "off" and [server_rsh] eq "off" and [server_alsterradio] eq "off")) (set streamcount streams_ok) DOELSE (set streamcount zuviele_streams)
attr multi_serverzugriff do always
define streamcount_act DOIF ([streamcount:state] eq "zuviele_streams") (set stream_reset on)

 

(hier laufen 2x Alsterradio, die Stream-URL wurde umgeschaltet auf die lokale IP des mpd-Servers und weil das nur
ein Sender versucht, ist der Status streamcount auf "streams_ok)

„stream_reset“ schaltet erstmal mit dem Holzhammer alle „Radiotasten“ für alle Räume aus, setzt dann den Serverstatus der
Streams auf „off“ und den  Statusdummy auf „achtung“ (es kommt die Anzeige „Server überlastet, bitte neu wählen“).

 

Nach einer kleinen Pause wird zuletzt noch der Status-dummy wieder auf „off“ gesetzt:

define stream_reset dummy
attr stream_reset setList on off
attr stream_reset room xbmc
define stream_resetAN notify stream_reset:on set radiolatinaJNA1 off;;set skyrockJNA1 off;;set radio538JNA1 off;;set ouifmJNA1 off;;set ndr2JNA1 off;;set NDR1shJNA1 off;;set rshJNA1 off;;set alsterradioJNA1 off;;set radiolatinaJNA2 off;;set skyrockJNA2 off;;set radio538JNA2 off;;set ouifmJNA2 off;;set ndr2JNA2 off;;set NDR1shJNA2 off;;set rshJNA2 off;;set alsterradioJNA2 off;;set radiolatinaJNA3 off;;set skyrockJNA3 off;;set radio538JNA3 off;;set ouifmJNA3 off;;set ndr2JNA3 off;;set NDR1shJNA3 off;;set rshJNA3 off;;set alsterradioJNA3 off;;set radiolatinaJNA4 off;;set skyrockJNA4 off;;set radio538JNA4 off;;set ouifmJNA4 off;;set ndr2JNA4 off;;set NDR1shJNA4 off;;set rshJNA4 off;;set alsterradioJNA4 off;;set radiolatinaJNA5 off;;set skyrockJNA5 off;;set radio538JNA5 off;;set ouifmJNA5 off;;set ndr2JNA5 off;;set NDR1shJNA5 off;;set rshJNA5 off;;set alsterradioJNA5 off;;set server_latina off;;set server_skyrock off;;set server_radio538 off;;set server_ouifm off;;set server_ndr2 off;;set server_ndr1sh off;;set server_rsh off;;set server_alsterradio off;;set streamcount streams_ok;;set JNA1wait achtung;;set JNA2wait achtung;;set JNA3wait achtung;;set JNA4wait achtung;;set JNA5wait achtung;;sleep 15;;set JNA1wait off;;set JNA2wait off;;set JNA3wait off;;set JNA4wait off;;set JNA5wait off


Jetzt kann man die Sender wieder ganz normal wählen und die DOIFs selektieren wieder die gewünschte Betriebsart.

Abfall-Kalender mit Google

Einbindung des Google-Kalenders in FHEM

Wenn die Mülltonne, die Papiertonne oder der gelbe Sack an die Strasse muss, tragen wir diesen Termin in den Google Kalender ein.

Über das FHEM-Modul Calendar lassen sich diese Termine prima auslesen.

FHEM Wiki Calendar

Einen Tag bevor die Tonne abgeholt wird, zeigt unser Floorplan ein entsprechendes Symbol.

 

Zusätzlich bekommen wir jeder eine email geschickt mit dem Text "der gelbe Sack muss raus!" oder "die Papiertonne muß raus".

So habe ich das Ganze umgesetzt.

Zunächst muß natürlich ein Google-Kalender vorhanden sein. Die Kalender ID findet sich bei den Einstellungen des Google-Kalenders unter "PrivatAdresse".

So wird das Calendar-Device in FHEM angelegt:

define AbfallGoogleCalender Calendar ical url https://www.google.com/calendar/ical/meine_GoogleKalender_URL.ics 43200

 

Die "43200" steht für den Abfrage-Intervall in Sekunden, der Kalender wird also alle 12 Stunden abgefragt.

Dann habe ich mir Dummies für den Floorplan angelegt:

FHEM Wiki Google-Kalender zur Steuerung von Dummies

define gelber_Sack dummy attr gelber_Sack room Kalender attr gelber_Sack setList ja nein attr gelber_Sack webCmd ja:nein
attr gelber_Sack devStateIcon ja:gelber_sack.ja.png nein:transparent.png

Das devStateIcon ist ein transparenter Pixel bei "nein" und ein entsprechendes Symbol bei "ja". Für die "schwarze Tonne" und die Papiertonne habe ich mir dann ebenfalls dummies angelegt:

mit

update all https://raw.githubusercontent.com/uniqueck/fhem-abfall/master/controls_fhemabfall.txt

 

habe ich mir dann das inoffizielle Hilfmodul "Abfall" installiert. FHEM Wiki ABFALL

Dann wird ein Device "myABFALL" erstellt:

define myABFALL AbfallGoogleCalender

wobei "AbfallGoogleCalender" der Names des definierten Google-Kalenders im Modul "Calender" ist.

Zur Datumsanzeige wird eine Hilfsfunktion in die 99_myUtils eingefügt:

#
# Hilfsfunktion für Kalenderauswertungen
#
sub datumHeuteMorgen($){
my $compareDate = shift;
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$year += 1900; $mon += 1;
my $heute = sprintf('%02d.%02d.%04d', $mday, $mon, $year);
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time+86400);
$year += 1900; $mon += 1;
my $morgen = sprintf('%02d.%02d.%04d', $mday, $mon, $year);
return "heute" if $compareDate eq $heute;
return "morgen" if $compareDate eq $morgen;
return $compareDate;
}

sub
myUtils_refresh($)
{
my ($name) = @_;

FW_directNotify("#FHEMWEB:$name", "location.reload(true);","" );
}




Dann werden die User-Readings definiert:

attr myABFALL ftui_datum {ReadingsVal("myABFALL","now_text","") eq "" ? datumHeuteMorgen(ReadingsVal("myABFALL","next_datum","")) : "heute"

und zum Schluß werden noch entsprechende "DOIFS" generiert:

set DgelberSack DOIF ([myABFALL] =~ "gelber") (set gelber_sack ja,{ DebianMail(This email address is being protected from spambots. You need JavaScript enabled to view it.','Muchelndorf Smarthome: Der Gelbe Sack muss raus!','Muchelndorf Smarthome: Der gelbe Sack muss raus!');;} DOELSE (set gelber_sack nein)
attr DgelberSack do always

 

Somit haben wir einen Tag vor dem eigentlichen Kalendereintrag das Floorplan-icon gesetzt und per Debian-Mail eine email verschickt.

 

Erhöhung der Funkreichweite

Erhöhung der Funkreichweite von Homematic-Komponenten

Der Herbst kommt, die Tage werden wieder kürzer. Wir müssen nach der Arbeit unsere Tiere versorgen und wenn wir abends den Paddock unserer Esel abäppeln, ist es im Normalfall bereits dunkel. Unser Paddock liegt auf dem Nachbargrundstück und es gibt dort eine Aussenbeleuchtung. Leider liegt diese weit ausserhalb der Reichweite unseres Homematic HM-LAN Adapters. Ich habe etwas im Internet gesucht, es gibt einen selektiven Funkrepeater für Homematic-Komponenten - den HM-Sys-SRP-Pl Funk-Zwischenstecker.

Das Gerät scheint nicht mehr produziert zu werden, ich habe leider nur einen Bausatz gefunden. Eine halbe Stunde Lötarbeit war also vonnöten - glücklicherweise waren alle SMD-Teile bereits bestückt. 

Auf "halber Strecke" zur Verteilerdose der Lichtanlage des Nachbarhauses steht unser Gartenpavillion. Von hier bis zum HM-LAN-Adapter sind es ca. 15m mit zwei Wänden dazwischen. Hier habe ich den Repeater in einem wetterfesten Gehäuse montiert. Vom Pavillion bis zum "Aussenlichtverteiler" des Nachbarhauses sind dann nochmal ca. 18m Funkstrecke zu überbrücken.

Das Nachbarhaus hatte vorher schon einen Funklichtschalter der Marke "Jung" - diesen habe ich einfach durch einen Homematic HM-LC-SW1-FM Funkschaltaktor ersetzt. Die Fernbedienungen der Nachbarn musste ich natürlich austauschen. Leider wird die aktuelle Version der Homematic Fernbedienung HM-RC-4-3 nicht von der veralteten Firmware meines HMLAN-Adpaters unterstützt, eine direkte Anmeldung im FHEM ist daher fehlgeschlagen ( es wird ein unbekanntes Gerät erkannt). Ich hätte natürlich ein Firmware-Update machen können, habe aber keinen Windows-PC im Haus...

Ich habe also die 3 Fernbedienungen für die Nachbarn direkt mit dem HM-LC-SW1-FM gepeert. Hierzu muss an jeweils beiden Komponten das Anlern-Prozedere ausgeführt werden. Wichtig: die direkte Verbindung ist nur möglich, wenn der HM-LC-SW1-FM noch nicht im FHEM (bzw. am HM-LAN-Adapter) angemeldet ist.

Nachdem die Fernbedienungen sich direkt mit dem Aktor verstanden haben, habe ich den HW-LC-SW1-FM dann mit dem üblichen Prozedere im FHEM angemeldet: 

set HMLAN1 hmPairForSec 900

 

und umbenannt

 

ren CUL_HM_HM_LC_SW1_FM_xxxxxx NachbarLicht

 

Das Anlernen muß natürlich in Reichweite des HM-LAN passieren und nicht in Nachbars Garage.

Jetzt der Repeater:

Auch dieser kann genau wie der Funkaktor automatisch mit set HMLAN1 hmPairForSec 900 angelernt und dann anschliessend umbenannt werden.

Der Repeater ist selektiv, d.h. man kann bis zu 16 Kanäle am Repeater betreiben, wobei jeder Aktor oder Sensor einen Kanal bekommt:

 

set <REPEATER> setRepeat <Channel> <Sensor/Aktor> <IO> no

http://www.fhemwiki.de/wiki/HM-Sys-sRP-Pl_Funk-Zwischenstecker_Repeater

Das FHEM-wiki empfiehlt den Einsatz einer VCCU, da ich nur einen einzigen Aktor schalten möchte, habe ich diesen Schritt übersprungen. Bisher hatte ich keine Probleme , aber hier die Anleitung zu erstellen einer solchen:

http://www.fhemwiki.de/wiki/Virtueller_Controller_VCCU

Ohne VCCU sieht meine Einbindung des HM-LC-SW1-FM in den Repeater (Kanal 1) dann  also so aus:

set Mein_Repeater_1 setRepeat 1 NachbarLicht HMLAN1 no 

Den Aktor für das Nachbargrundstück kann ich jetzt problemlos über das FHEM erreichen, mit unseren

eigenen, vorhandenen Handsendern koppeln und auch im Floorplan einbinden.

Mit Repeater überbrücke ich problemlos eine Funkstrecke von ca. 33m Luftlinie mit 3 Wänden dazwischen.

 

Nie wieder Arbeit im dunkeln !

Email mit FHEM versenden

Email versenden mit FHEM

Mein FHEM kann Emails versenden - z.B. zur Erinnerung, wenn die Mülltonne an die Strasse gestellt werden muß. Diese Email kann z.B. auch auf dem Handy ausgewertet werden. Hierfür benutze ich die Anroid- pp "Tasker". Der Tasker kann z..B. die Betreffzeile einer email auswerten und daraufhin eine App starten.

Auf meinem NUC-FHEM-Server läuft ein Linux Mint, gleiche Anleitung gilt für Ubuntu, Raspbian, usw.

Siehe auch: FHEM Wiki Email senden

Auf dem FHEM-Serversystem muß zunächst einmal "sendemail" installiert werden:

sudo apt-get update 
sudo apt-get install sendemail libio-socket-ssl-perl libnet-ssleay-perl perl

 

Achtung: Bei älteren Distributionen wird das "sendemail" evt. mit großem "E", also "sendEmail" geschrieben.

In die 99_myUtils.pm habe ich folgendes eingetragen:

######## DebianMail Mail versenden ############ 
sub
DebianMail
{
my $rcpt = shift;
my $subject = shift;
my $text = shift;
my $attach = shift;
my $ret = "";
my $sender = "absender\@meinedomain.de";
my $konto = "absender\@meinedomain.de";
my $passwrd = "mein_passwort";
my $provider = "smtp.mein_provider.de";
Log 1, "sendemail RCP: $rcpt";
Log 1, "sendemail Subject: $subject";
Log 1, "sendemail Text: $text";
Log 1, "sendemail Anhang: $attach";

$ret .= qx(sendemail -f '$sender' -t '$rcpt' -u '$subject' -m '$text' -a $attach -s '$provider' -xu '$konto' -xp '$passwrd' -o tls=auto -o message-charset=utf-8);
$ret =~ s,[\r\n]*,,g; # remove CR from return-string
Log 1, "sendemail returned: $ret";
}

 

Der Aufruf erfolgt im FHEM so:

{ DebianMail('meine_email@meine_domain.de','Betreff','Email_Text');;}

 

Offline-Sprachsteuerung mit MOVI und Arduino

Offline-Spracherkennung mit Arduino-MOVI Shield und Steuerung von FHEM

 

Für den Arduino gibt es eine „offline Spracherkennung“ - das MOVI-Shield von Audeme.

Hiermit habe ich mir eine „cloudfreie“ Offline-Alexa für FHEM gebastelt.

 

Hier ein kleines Video der "pre-alpha"mit einem Pi2, die wohnt noch in einem Eierkarton:

 

 

Und hier der erste Versuch der Integration in ein Gehäuse (aka "alte Lautsprecherbox") - meine "Gehäuseversion 1":

 

 

Die Zutaten:

 

Ein Raspberry Pi (am besten die Version 3, weil da das WLAN gleich mit „an Bord“ ist), ein Arduino

(ich habe mich für den MEGA 2560 R3 entschieden) und natürlich das MOVI-Shield.

 

Die Vorbereitung:

 

Zunächst muss das Betriebssystem des Raspberry Pi auf eine SD-Karte. Am einfachsten geht das mit Noobs: herunterladen, das ZIP-Archiv entpacken und den Inhalt einfach auf eine leere SD-Karte schieben. Wenn diese dann in den PI gesteckt wird, kann der damit booten und man wird durch die Installation des Betriebssystems geführt. WLAN, IP-Adressen festlegen, usw. geht mittlerweile auch bei Raspbian ohne „Konsole“ direkt aus der grafischen Oberfläche heraus.

 

Das MOVI-Shield wird auf den Arduino gesteckt und es muß noch ein Jumper entsprechend der eingesetzten Arduino-Version gesetzt werden. Wie das Jumper-Setting ist und welche Arduino-Boards und Klone kompatibel sind, entnehmt Ihr am besten der Anleitung des Herstellers:

 

https://www.audeme.com/downloads.html

Da die SD-Karte des MOVI-Boards Hardware-spezifische und proprietäre Programmteile enthält, empfiehlt der Hersteller die zu klonen. Bei Ausfall der SD-Karte ohne existierendes Backup müsste der MOVI ansonsten zum Hersteller eingeschickt werden.

 

Wenn die SD-Karte des MOVI schonmal im Rechner steckt: auf die „Update“-Partition werden das ebenfalls herunterladbare Firmeware-Update sowie – falls gewünscht – das Deutsche Sprachpaket geladen. Auch hierzu: siehe Anleitung des Herstellers.

 

Der Ardunio muß eine kräftige Stromversorgung bekommen, ansonsten bootet der MOVI nicht. Ein 5V-USB-Netzteil ist nicht ausreichend!

 

Der Arduino wird über USB mit dem PI verbunden.

 

Die Verkabelung (inkl. Realtime-Clock, dazu weiter unten mehr) ist im Bild gut zu erkennen. Es handelt sich hierbei um meine "Gehäuseversion IV":

 

 

Die "Technik" kann hinter einem Schrank oder auf einem Regal verschwinden, nur der Lautsprecher und das 360°-Mikro (das ist der kleine "Hut" auf dem Lautsprecher) sind sichtbar. Ein winziges "Frontend" sozusagen:

 

 

 

Zurück zur Software:

 

um schnell meinen Arduino-Sketch auf alle Pis zu bekommen, habe ich die aktuelle Arduino IDE auf den Pi geladen. Die IDE in den Repositories des Pi ist leider stark veraltet. Ihr müsst Euch also die aktuelle IDE für ARM herunterladen:

 

https://www.arduino.cc/en/Main/Software

 

Im Verzeichnis, wo Ihr die zip-Datei entpackt habt, gibt es jetzt ein Installationsscript.

Um die IDE zu installieren, muß man dieses Script ausführen:

 

sudo ./install.sh

 

Um die "headless" Pis mit den daran angeschlossenen Arduinos zu bedienen, habe den RDP-Server XRDP installiert.

 

Achtung: vorher muß der RealVNC-Server runter - die beiden beissen sich:

 

sudo apt-get purge realvnc-vnc-server
sudo apt-get update
sudo apt-get install xrdp

 

Zuletzt muß im aktuellen Raspbian noch ssh aktiviert werden. Dass kann man über die GUI erledigen:

 

Einstellungen --> Raspberry-Pi-Konfiguration --> Schnittstellen

 

Mit "passwd" dann im Terminal noch ein eigenes Passwort setzen. Es wird nach dem bisherigen Passwort gefragt, das ist per default "raspberry".

 

Jetzt kann man mit einem RDP-Client (unter Linux benutze ich Remmina) auf das Desktop des PIs und auf die Arduino-IDE zugreifen.

 

Achtung: es wird - anders als bei klassischer Fernwartung - für die RDP-Sitzung ein eigenes Desktop aufgemacht.

 

Das MOVI-Shield braucht jetzt noch die Libraries (Download beim Hersteller), diese werden in der Arduino IDE direkt als zip-Datei unter Sketch –> Bibliothek einbinden geladen.

Mit der MOVI-Bibliothek werden gleich einige Beispiel-Sketche installiert. Ich empfehle den „LightSwitch“ (Beispiele → Movi(tm)VoiceDialogShield → beginner → LightSwitch). Diesen habe ich geladen und nach und nach ausgebaut.

 

Es gibt für den MOVI ein Deutsches Sprachpaket, man muß aber sehr viel "phonetisch umschreiben" und die Erkennung ist nicht so präzise wie auf Englisch. Zudem kann der Synthesizer keine Umlaute aussprechen und sowohl bei der Erkennung als auch bei der Aussprache von z.B. "Küche" hatte ich arge Schweirigkeiten. Nach langen Versuchen habe ich mich für Englisch entschieden - hier klappt die Erkennung deutlich besser. Ich habe bei mir die weibliche Stimme eingestellt. Das Callsign ist frei wählbar - mein MOVI hört auf "Moneypenny".

 

Das "Einlernen" neuer Sätze denkbar einfach. Über die Arduino-IDE im MOVI-Sketch einfach eintragen und hochladen:

 

Für die Erkennung:

 

recognizer.addSentence("Aussenlicht an"); // Add German sentence 8

 

und für das Sprach-Feedback:

 

if (res==8) { // Sentence 8
recognizer.say("Die Aussenbeleuchtung ist jetzt eingeschaltet!"); // Respond a sentence in German
}

 

Anbindung an FHEM:

 

Auf dem frisch Installierten PI muß ein FHEM installiert werden.

 

Die Vorbereitung:

 

sudo apt-get update && sudo apt-get -y upgrade && sudo reboot

 

sudo apt-get -f install && sudo apt-get -y install perl-base libdevice-serialport-perl libwww-perl libio-socket-ssl-perl libcgi-pm-perl libjson-perl sqlite3 libdbd-sqlite3-perl libtext-diff-perl libtimedate-perl libmail-imapclient-perl libgd-graph-perl libtext-csv-perl libxml-simple-perl liblist-moreutils-perl ttf-liberation libimage-librsvg-perl libgd-text-perl libsocket6-perl libio-socket-inet6-perl libmime-base64-perl libimage-info-perl libusb-1.0-0-dev libnet-server-perl

 

Die Installation:

 

sudo wget http://fhem.de/fhem-5.8.deb && sudo dpkg -i fhem-5.8.deb

 

Folgende Schritte sind auf dem Client-Pi notwendig:

 

Den Arduino habe ich als „JeeLink“-Device im FHEM angelegt.

 

define myArduino1 JeeLink /dev/ttyACM0@9600
attr myArduino1 event-on-change-reading .*

 

Der Client wird dann im Haupt-FHEM als FHEM2FHEM-Device angelegt.

 

Im „Haupt“-FHEM:

 

Wie hier beschrieben: https://forum.fhem.de/index.php/topic,25399.msg183910.html#msg183910

 

wird im Linux -Terminal meines (Haupt)FHEM-Servers eine "named pipe“ gesetzt:

 

mkfifo /tmp/jdummy

 

Dann wird ein JeeLink dummy angelegt:

 

define myArduino1 JeeLink /tmp/jdummy@directio
attr myArduino1 event-on-change-reading .*

 

Achtung: es muß tatsächlich „directio“ heissen – ohne „n“

 

Jetzt kommt das FHEM2FHEM device:

 

define remotepi1 FHEM2FHEM IP_meines_Client_PI:7072 LOG:.*

 

Bei Aktivität des Movi werden jetzt folgende Readings im JeeLink dummy "myArduino1" erzeugt:

(Im Beispiel sage ich „Homeoffice on“, der MOVI-Sketch für den ARDUINO muß natürlich geladen sein):

 

UNKNOWNCODE MOVIEvent[140] ACTIVELISTEN 2018-02-10 19:40:46
UNKNOWNCODE MOVIEvent[141] END ACTIVELISTEN 2018-02-10 19:40:50
UNKNOWNCODE MOVIEvent[150] SPEAKING 2018-02-10 19:40:52
UNKNOWNCODE MOVIEvent[151] END SPEAKING 2018-02-10 19:40:59
UNKNOWNCODE MOVIEvent[200] CALLSIGN DETECTED 2018-02-10 19:40:46
UNKNOWNCODE MOVIEvent[201] HOMEOFFICE ON 2018-02-10 19:40:51
UNKNOWNCODE MOVIEvent[202] #7 2018-02-10 19:40:52

 

Das MOVI-Shield vergibt die Satznummern nach der Reihenfolge im Sketch. Der erste Satz heisst "#0", der Zweite "#1", usw.

 

Mit

 

attr myArduino1 stateFormat { ReadingsVal("myArduino1","UNKNOWNCODE MOVIEvent[202]",0);; }

 

setze ich den Status des JeeLink dummies auf diese Satznummer, im Beispiel die "#7"

Ein DOIF kann jetzt auf diese Satznummer reagieren:

define ARD1 DOIF ([myArduino1:"#7"]) (set Arbeitszimmer1 on,set Arbeitszimmer2 on) DOELSEIF ([myArduino1:"#8"]) (set Arbeitszimmer1 off,set Arbeitszimmer2 off)
attr ARD1 do always

 

Die Anbindung weiterer Pis mit Arduino+Movishield für die Spracherkennung in weiteren (Ziel: in allen!) Räumen ist sehr einfach:

Wie oben beschrieben könnt Ihr Euch weitere Pi/MOVI-Kombinationen zusammenbauen.

Zur Vereinfachung habe ich mir eine SD-Karte mit einer fertigen Installation geklont. So brauche ich diese nur in weitere Pis zu stecken und die IP zu ändern, der Rest passiert dann wie beschrieben per RDP.

 

Auf dem "Haupt-FHEM" muß dann nur ein weiteres FHEM2FHEM-Device für jeden zusätzlichen MOVI-Pi angelegt werden:

 

define remotepi2 FHEM2FHEM IP_meines_2tenPI:7072 LOG:.*
define remotepi3 FHEM2FHEM IP_meines_3ten_PI:7072 LOG:.*
...
...

 

Da alle Pis die gleichen Readings erzeugen, triggern alle für den MOVI angelegten DOIFS auf alle Pis.

Den Arduino-Sketch und die Libraries schiebe ich per Filezilla auf die Pis und binde sie dann per Arduino IDE ein. So kann ich schnell etwas ändern und diese Änderung allen Client-MOVIs mitteilen.

 

Wichtige Tipps:

 

1) Wenn das FHEM auf dem Client-Pi an der USB-Schnittstelle „lauscht“ ist diese blockiert.

 

Es gibt in der Arduino-IDE dann eine Fehlermeldung beim Upload eines neuen oder geänderten Sketches. Abhilfe: im FHEM des Clients muß das JeeLink-Device kurzfristig auf eine andere Schnittstelle. IM FHEM-web auf das Device klicken und bei „DEF“ z.B. /dev/ACM0@9600 in /dev/ACM1@9600 ändern. Der state wechselt dann auf „disconnected“ und dann funktioniert der Sketch-Upload.

 

2) Wenn irgendetwas im Sketch geändert wurde und/oder die Schnittstelle wie in Punkt 1 beschrieben kurzzeitig geändert wurde, dann braucht das FHEM2FHEM -Device im Haupt-FHEM ein „set remotepi1 reopen“. Wenn man mehrere Cleints geändert hat, ist es natürlich mühsam, das bei jedem einzelnen auszuführen. Also habe ich mir einen „pi-reopen“ dummy gebaut. Ein DOIF triggert auf diesen dummy führt den Befehl dann auf allen FHEM2FHEM-Pis aus:

 

define pi_reopen dummy
attr pi_reopen setList on off
define pi_reopen_act DOIF ([pi_reopen:"on"]) (set remotepi1 reopen,set remotepi2 reopen,...,set pi_reopen off)
attr pi_reopen_act do always

 

3) Der MOVI verfügt über ein "LowLevel Interface". Damit kann man z.B.die Systemmeldungen ("there is a lot of noise in the room") abstellen oder den Mikrofon-Threshold für die optimale Erkennung einstellen. Der Hersteller hat dafür einen eigenen Sketch bereitgestellt. Wenn man diesen Sketch hochlädt, kann man das LowLevel-Interface über den Seriellen Monitor der Arduino IDE bedienen. Es geht aber auch viel einfacher: man kann einfach über das Terminal des Pis darauf zugreifen:

echo "SYSTEMMESSAGES OFF" > /dev/ttyACM0

 

oder über die FHEM-Kommandozeile:

{system("echo SYSTEMMESSAGES OFF > /dev/ttyACM0")}

 

Die Systemrückmeldungen werden im Event Monitor von FHEM angezeigt. "HELP" gibt eine Liste der möglichen Befehle aus.Für diese Variante muß der PI nichtmal "disconnected" werden (wie in Punkt 1 beschrieben)

 

Uhrzeit und Datum ansagen lassen:

 

Für ganz kleines Geld gibt es eine "Real-Time-Clock" für den Arduino.

Hier gibt es einen Beitrag, der die Installation beschreibt:

 

https://www.instructables.com/id/Voice-Controlled-Clock-With-Arduino-no-WiFi-No-PC/

 

Ich habe die dazugehörige library hier heruntergeladen: https://github.com/adafruit/RTClib

 

und per

 

#include "RTClib.h"

 

in den Arduino Sketch eingebunden. Die Zeilen des Uhrzeit-Sketches habe ich in meinem Sketch integriert.

Um die Uhr zu stellen, muß der PI die richtige Zeit wissen:

 

sudo dpkg-reconfigure tzdata

 

Im Sketch muss für das Stellen der Uhrzeit kurzfristig die Auskommentierung einer Zeile entfernt werden.

Damit stellt sich die Uhr und wenn das einmal geschehen ist, kann die Zeile wieder auskommentiert werden:

 

// Comment out the first time to set the time and date on the RTC module. After this,
// it will remember it via it non-volatile memory. 
// rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

 

Ich kann den MOVI jetzt also nach Uhrzeit und Datum fragen, einen Timer für die Frühstückseier setzen, usw.

Hier ein Demo-Video meiner zweiten Moneypenny-Version - diesmal mit Pi3 inkl. Lautsprecher und Mikro im Gehäuse

eines alten Kabelmodems - das war meine "Gehäuseversion III":

 

 

 

 

Steuerung meiner Multiroom-Lautsprecher (FHEM/Squeezebox):

 

Mit der MOVI-Library werden verschiedene Beispiel-Sketche angeboten, u.a. der "NestedDialog".

(In der Arduino IDE zu finden unter "Beispiele-->MOVI(tm)Voice Dialog Shield--> intermediate--> NestedDialog").

 

Hiermit kann ich z.B. folgenden Dialog erreichen:

 

Ich: "Moneypenny, spiele Musik!"

Moneypenny: "welchen Spieler möchtest Du?"

Ich:"Badezimmer!"

Moneypenny: "Welche Playliste oder welchen Sender soll ich spielen?"

Ich: "Latina!"

Moneypenny: "Ich spiele jetzt Radio Latina auf dem ausgewählten Player!"

 

 

Ich habe also das Beispiel "NestedDialog" zusätzlich in meinen Sketch eingebaut.

Wie weiter oben beschrieben, triggern meine DOIFs im Haupt-FHEM ja auf die eindeutigen Satznummern,

die kommen beim "NestedDialog" nicht vor.

Also habe ich hier eine Umleitung gebaut: die Player-DOIFs reagieren auf eine Variable:

"#8" für Musik, zweite Stelle für den Player, dritte Stelle für die Playlist.

 

Also: Event "#821" = Musik, Player 2, Playlist 1.

 

Mit

 

Serial.println

 

im MOVI-Sketch übergebe ich das "Reading" an das Haupt-FHEM.

 

Anders ausgedrückt:

 

Moneypenny: "welchen Spieler möchtest Du?"

Ich:"Badezimmer!" --> Variable Player wird gesetzt

Moneypenny: "Welche Playliste oder welchen Sender soll ich spielen?"

Ich: "Latina!" --> Variable Playlist wird gesetzt

Moneypenny: "Ich spiele jetzt Radio Latina auf dem ausgewählten Player!"

 

Im Arduino-Sketch sieht das im Wesentlichen so aus:

 

// choose Player
if (context==BOOT) { // MOVI just started
if (res==20) 
recognizer.ask(F("What Player do you choose?"));
context=PLAYER;
sbp=0;
}

if (context==PLAYER) {
if (res==45) { // player living room
recognizer.say(F("player living room choosen"));
recognizer.ask(F("What Playlist or Station do you choose?"));
context=PLAYLIST;
sbp=1;
}
if (res==46) { // player kitchen
recognizer.say(F("player kitchen choosen"));
recognizer.ask(F("What Playlist or Station do you choose?"));
context=PLAYLIST;
sbp=2;
}
if (res==47) { // player bathroom
recognizer.say(F("player bathroom choosen"));
recognizer.ask(F("What Playlist or Station do you choose?"));
context=PLAYLIST;
sbp=3;
}
if (res==48) { // player outside
recognizer.say(F("player outside choosen"));
recognizer.ask(F("What Playlist or Station do you choose?"));
context=PLAYLIST;
sbp=4;
}

if (context==PLAYLIST) {
if (res==50) { // NDR2
recognizer.say(F("I am now playing ND R2 on the selected player"));
context=BOOT;
playlst=1;
String Au1=String (sbp,DEC);
String Au2=String (playlst,DEC);
String Au4=Au3+Au1+Au2;
Serial.println(Au4);
}

if (res==51) { // LATINA
recognizer.say(F("I am now playing LATINA on the selected player"));
context=BOOT;
playlst=2;
String Au1=String (sbp,DEC);
String Au2=String (playlst,DEC);
String Au4=Au3+Au1+Au2;
Serial.println(Au4);
}

if (res==52) { // Barbaras Liste
recognizer.say(F("I am now playing Barbaras Playlist on the selected player"));
context=BOOT;
>playlst=3;
String Au1=String (sbp,DEC);
String Au2=String (playlst,DEC);
String Au4=Au3+Au1+Au2;
Serial.println(Au4);
}

f (res==53) { // Jochens Liste
recognizer.say(F("I am now playing Jochens playlist on the selected player"));
context=BOOT;
playlst=4;
String Au1=String (sbp,DEC);
String Au2=String (playlst,DEC);
String Au4=Au3+Au1+Au2;
Serial.println(Au4);
}

 

Und so sieht das passende DOIF im Haupt-FHEM aus:

 

define play22 DOIF[ ([myArduino1:state] =~ "#822") (set JNSKuechePower on,set Kueche on,set Kueche playlist play latina)
attr play22 do always

 

Natürlich sind weitere Befehle wie Sync. und Lautstärke möglich, soweit bin ich aber noch nicht.

 

 

 

Ansage des Wetters:

 

Der MOVI kann in zwei Richtungen kommunizieren. Ich kann über:

 

{system("echo SAY test > /dev/ttyACM0")}

 

vom FHEM des jewiligen MOVI-Pis einen Text (hier "test") vorlesen lassen.

Da auch eine "offline-Alexa" über das Wetter informieren können muß, habe ich folgendes gemacht:

 

Achtung: das passiert alles im FHEM des/der Movi-Pi(s), nicht im Haupt-FHEM

 

Ich habe ein "Weather" - device angelegt: https://wiki.fhem.de/wiki/Weather

 

define MeinWetter Weather 676378 3600 de

 

Da Moneypenny noch Englisch spricht, habe ich das "de" weggelassen. Euren Städtecode bekommt ihr wie im Wiki beschrieben.

 

Dann:

 

define forecast dummy

 

Diesen dummy kann ich schonmal mit den Readings aus dem Weather-Device plus etwas Zwischentext befüllen:

 

{ fhem("set forecast " ."The weather in ".(ReadingsVal("MeinWetter","city",0)." today is ". ReadingsVal("MeinWetter","condition",0)).". The temperature currently is ". ReadingsVal("MeinWetter","temp_c",0)." degrees celsius. The forecast for tomorrow will be ".ReadingsVal("MeinWetter","fc2_condition",0)." and a maximum temperature of ".ReadingsVal("MeinWetter","fc2_high_c",0)." degrees celsius. ") }

 

Merkwürdigerweise konnte ich nicht direkt in einem DOIF auf ein "MOVI-Event" reagieren, die "system"-Ausgabe gibt den Wert "-1" zurück und damit macht das DOIF (oder ich?) einen Fehler. Egal, über den Umweg dummy+notify geht es:

 

define wetterdummy dummy
attr wetterdummy setList on off
define wspeech_on notify wetterdummy:on {my $wetter = ReadingsVal("forecast","state",0);;system("echo SAY $wetter > /dev/ttyACM0")}

 

Im Arduino Sketch passiert bei Anfrage nach dem Wetter folgendes:

 

If (res==54) { // Sentence 53
digitalWrite(led, HIGH); // Turn on LED
Serial.println("wetter"); // Ausgabe wetterdummy on
Serial.println("..."); // Ausgabe wetterdummy off
digitalWrite(led, LOW); //Turn off LED

 

Im FHEM reagiert ein DOIF darauf:

 

define forecast_act DOIF ([myArduino1:&RAWMSG] =~ "wetter") (set wetterdummy on) DOELSEIF ([myArduino1:&RAWMSG] =~ "...") (set wetterdummy off)
attr forecast_act do always

 

Und damit das Wetter immer schön aktuell bleibt, wird der dummy "forecast" bei Aktualiserung des Devices "MeinWetter" neu befüllt:

 

define wetteraktuell notify MeinWetter.* { fhem("set forecast " ."The weather in ".(ReadingsVal("MeinWetter","city",0)." today is ". ReadingsVal("MeinWetter","condition",0)).". The temperature currently is ". ReadingsVal("MeinWetter","temp_c",0)." degrees celsius. The forecast for tomorrow will be ".ReadingsVal("MeinWetter","fc2_condition",0)." and a maximum temperature of ".ReadingsVal("MeinWetter","fc2_high_c",0)." degrees celsius. ") }

 

 

Gestensteuerung mit dem APDS-9960 Sensor

Gestensteuerung mit dem APDS-9960 Sensor

Im Internet bin ich auf ganz einfache Möglichkeit der Gestenerkennung gestossen:

https://www.youtube.com/watch?v=d8txEBNaTw0

Den Sensor "APDS-9960" gibt es für kleines Geld zu kaufen. Er wird an einen Arduino angeschlossen.

Achtung: VCC muss an den 3,3V-Anschluss, nicht an 5V !

Hier gibt es den Anschlussplan und bei GitHub die Arduino-Libraries inklusive Beispiel Sketch.

Im Beispiel-Sketch reagiert der Sensor auf Hand rauf/runter,links/rechts und weit/nah.

Ich habe das Ganze in FHEM eingebunden wie im Abschnitt "Offline-Sprachsteuerung mit MOVI und Arduino" beschrieben.

Also Arduino-->Pseudo-Jeelink-Device im FHEM auf Raspberry PI --> FHEM2FHEM

Im FHEM-Eventmonitor tauchen jetzt die Handbewegungen auf:

UNKNOWNCODE" gefolgt von "UP","DOWN","LEFT","RIGHT","NEAR" oder "FAR" - je nach Handbewegung.

 



Darauf kann ein DOIF triggern:

define LightstripsAus DOIF ([myArduino1:state] eq "UNKNOWNCODE DOWN")(set HUEDevice6 off)

 

Zum Test habe ich mal eine Stehlampe auf "Hand links/rechts" und einen Lightstrip auf "Hand hoch/runter" gelegt.

Hier ein kleines Video dazu: 

 

Ein weiteres Anwendungsbeispiel für die Gestenerkennung: die Steuerung meiner Squeezebox-Player

Ich habe im setup-Teil des Gesten-Sketches zwei Variablen cud und clr (soll heissen: counter up/down bzw. counter links/rechts)
sowie zwei Strings "UD" und "LR" (für up-down und left-right) angelegt:

int cud = 0;
int clr = 0;
String S1 = "UD";
String S2 = "LR";

 

Dann im loop-Teil:


// Handgeste hoch-runter

case DIR_UP:
cud = cud+1;
if (cud >5) {
cud=5;
}
Serial.println(S1+cud);
break;
case DIR_DOWN:
cud =cud-1;
if (cud <0) {
cud=0;
}
Serial.println(S1+cud);
break;

// Handgeste links-rechts

case DIR_LEFT:
clr = clr-1;
if (clr <0) {
clr=5;
}
Serial.println(S2+clr);
break;
case DIR_RIGHT:
clr = clr+1;
if (clr >5) {
clr=0;
}
Serial.println(S2+clr);
break;

 

Die Handbewegungen hoch runter werden also in der Variable "cud" hoch bzw. runtergezählt. Im Beispiel ist bei "5" nach oben und "0" nach unten Schluss.


Bei Handbewegung links/rechts wird in "clr" gezählt, bei "<0" springt die Variable auf "5" und bei ">5" wieder auf "0"

Der Arduinio gibt bei Hand rauf/runter also String S1+cud aus, also z.B. "UNKNOWNCODE UD4".
Bei Hand links/trechts entsprechend String S2+clr, also z.B. "UNKNOWNCODE LR3".

Jetzt kommen die DOIFs im FHEM:

Hand links/rechts "winkt "die Sender oder playlisten meines players "Arbeitszimmer" durch:

define Senderwahl0 DOIF ([myArduino1:state] eq "UNKNOWNCODE LR0") (set Arbeitszimmer playlist play latina)
define Senderwahl1 DOIF ([myArduino1:state] eq "UNKNOWNCODE LR1") (set Arbeitszimmer playlist play Radio538)
define Senderwahl2 DOIF ([myArduino1:state] eq "UNKNOWNCODE LR2") (set Arbeitszimmer playlist play NDR2)
...

und die rauf/runter-Handbewegung steuert die Lautstärke:

define Lautstaerke0 DOIF ([myArduino1:state] eq "UNKNOWNCODE UD0") (set Arbeitszimmer volume 10)
define Lautstaerke1 DOIF ([myArduino1:state] eq "UNKNOWNCODE UD1") (set Arbeitszimmer volume 20)
define Lautstaerke2 DOIF ([myArduino1:state] eq "UNKNOWNCODE UD2") (set Arbeitszimmer volume 30)

 

Das An-und Ausschalten des players übernimmt die Funktion "FAR". Auf die Auswertung von "NEAR" habe ich verzichtet, dann muss man sich keine Mühe geben, die Entfernung zum Sensor abzuschätzen.

Ich habe sozusagen ein "Toggle" auf "FAR" gesetzt. Will heissen:
Hand Richtung Sensor und wieder weg: Player an
Hand Richtung Sensor und wieder weg: Player aus

Und so geht's:

wieder habe ich im setup-Teil eine Variable gesetzt:

int onoff =0;

 

Und dann im loop ("NEAR" ist wie gesagt auskommentiert und somit deaktiviert):

// case DIR_NEAR:
// Serial.println("NEAR");
// break;
   
case DIR_FAR:
onoff=onoff+1;
if (onoff >1) {
onoff=0;
Serial.println("PLR_OFF");
}
else if (onoff =1) {
Serial.println("PLR_ON");
}
break;

 

Das passende FHEM-DOIF reagiert dann wie oben beschrieben auf "UNKNOWNCODE PLR_ON" bzw. "PLR_OFF".

Damit kann die Gestensteuerung eines Squeezebox-Players "stand-alone" erfolgen - das funktioniert prima!

Ich habe mir ein 20x4 Display und ein passendes Gehäuse bestellt,
damit kann dann der Sendername und die Lautstärke angezeigt werden.
Dank WLAN kann dieses Squeezebox-Bedienteil überall im Haus aufgestellt werden.

Das ganze könnte z.B. auch den TV steuern. Oder Hue-Farben "durchwinken"...