<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>http://wiki.fhem.de/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Rince</id>
	<title>FHEMWiki - Benutzerbeiträge [de]</title>
	<link rel="self" type="application/atom+xml" href="http://wiki.fhem.de/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Rince"/>
	<link rel="alternate" type="text/html" href="http://wiki.fhem.de/wiki/Spezial:Beitr%C3%A4ge/Rince"/>
	<updated>2026-04-05T21:58:05Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.43.6</generator>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Mi_vacuum&amp;diff=27523</id>
		<title>Mi vacuum</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Mi_vacuum&amp;diff=27523"/>
		<updated>2018-07-23T13:43:10Z</updated>

		<summary type="html">&lt;p&gt;Rince: Vorgehensweise Token Auslesen erneuert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
=Mi Vacuum=&lt;br /&gt;
Wie der preiswerte Staubsaugerroboter auch auf FHEM hört...&lt;br /&gt;
&lt;br /&gt;
==Für wen ist die Anleitung gedacht?==&lt;br /&gt;
Ich gehe davon aus, dass ihr ein funktionierendes FHEM auf einem Linux Rechner (Debian) betreibt.&lt;br /&gt;
&lt;br /&gt;
Weiterhin denke ich, dass euer Hauptarbeitsrechner unter Windows läuft.&lt;br /&gt;
&lt;br /&gt;
Als Smartphone OS Android (wer Apple hat, kann gerne die Token-Auslese-Geschichte hier beschreiben).&lt;br /&gt;
&lt;br /&gt;
Um das Teil auch von Alexa aus ein und aus zu schalten, sollte auch die Installation von Alexa in FHEM fertig sein.&lt;br /&gt;
&lt;br /&gt;
==Die Einrichtung des Moduls==&lt;br /&gt;
Das ist insofern spannend, als das Modul nicht offiziell in FHEM eingecheckt ist. Man muss also das Modul runterladen, auf den FHEM Rechner bringen etc...&lt;br /&gt;
&lt;br /&gt;
===Vorarbeiten (Linux)===&lt;br /&gt;
Zunächst fangen wir mal auf unserem FHEM Rechner an. Mit Putty verbinden wir uns per SSH mit dem FHEM Computer.&lt;br /&gt;
&lt;br /&gt;
Folgende Befehle können benötigt werden (Debian):&lt;br /&gt;
* &amp;lt;code&amp;gt;sudo apt-get install libjson-perl&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;sudo apt-get install libdigest-md5-perl&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;sudo apt-get install libcrypt-cbc-perl&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;sudo cpan Crypt::Rijndael_PP&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;sudo apt-get install libcrypt-ecb-perl&amp;lt;/code&amp;gt; (nur nötig, wenn ihr einen verschlüsselten Token mit 96 Zeichen habt)&lt;br /&gt;
* &amp;lt;code&amp;gt;sudo cpan Crypt::Cipher::AES&amp;lt;/code&amp;gt; (nur nötig, wenn Crypt::Rijndael_PP aus irgendwelchen Gründen nicht funktioniert)&lt;br /&gt;
Wenn bei dem ein oder anderen Modul die Meldung kommt, dass es schon installiert ist, einfach mit dem nächsten Befehl weiter machen. Das CPAN Teil würde ich am Schluss machen, das braucht ziemlich lang zum installieren.&lt;br /&gt;
&lt;br /&gt;
===Vorarbeiten am Smartphone (Token, Android)===&lt;br /&gt;
Das Problem ist folgendes:&lt;br /&gt;
&lt;br /&gt;
Wenn der Roboter mit dem WLAN verbunden wird, generiert er einen Token. Das ist ein Schlüssel, ohne den er sich nicht steuern lässt. Damit FHEM drauf zugreifen kann, benötigt man diesen Token.&lt;br /&gt;
&lt;br /&gt;
Mit den neueren Versionen der MiHome App klappt das Auslesen der Tokens leider nicht mehr.&lt;br /&gt;
&lt;br /&gt;
Ich gehe davon aus, dass der Staubsauger mit der original MiHome App eingebunden ist und funktioniert. (Ich habe bei der Einrichtung des Servers =&amp;gt; &amp;quot;other&amp;quot; gewählt. Offenbar wollen neuere Staubsauger sich mit &amp;quot;China Mainland&amp;quot; nicht mehr verbinden. Tut hier an dieser Stelle zwar nichts zur Sache, aber vielleicht hilft es dem ein oder anderen. Wenn man die Region gewechselt hat, muss man auch den Staubsauger neu einbinden)&lt;br /&gt;
&lt;br /&gt;
* MiHome löschen&lt;br /&gt;
* alte MiHome suchen (APKMirror z.B., Version 5.0.19 hat bei mir funktioniert, unsichere Quellen müssen erlaubt sein)&lt;br /&gt;
* runtergeladene MiHome App öffnen und anmelden (sollte ganz normal den Sauger finden)&lt;br /&gt;
* USB-Debugging am Handy einschalten (Entwickleroptionen...)&lt;br /&gt;
* Handy mit USB Kabel und PC verbinden&lt;br /&gt;
* [https://github.com/ultrara1n/MiToolkit/releases MiToolkit] 1.6 runterladen und öffnen&lt;br /&gt;
* [https://github.com/ultrara1n/MiToolkit/releases MiToolkit] erzeugt nun am Handy ein Backup&lt;br /&gt;
* anschließend zeigt es den Token direkt am PC an&lt;br /&gt;
&lt;br /&gt;
===Installation des inoffiziellen Moduls===&lt;br /&gt;
Der folgende Teil ist für völlige Noobs. Wenn ihr einen eleganteren Weg kennt, her damit.&lt;br /&gt;
&lt;br /&gt;
Zunächst bitte das Modul aus dem Forum herunterladen.&lt;br /&gt;
[https://forum.fhem.de/index.php/topic,73052.0.htmlm Hier] befindet sich der Thread. Markus M. hat sich die Mühe gemacht, ein Modul zu schreiben. Solange es nicht offiziell eingecheckt ist, muss man es händisch installieren. Das kann man wie folgt machen:&lt;br /&gt;
* das Modul zunächst auf seinem Windows PC speichern&lt;br /&gt;
&lt;br /&gt;
Wie kommt das Modul nun auf den eigenen RasPi?&lt;br /&gt;
&lt;br /&gt;
Ich nutze dafür einen kleinen HTTP Server auf meinem Windows Rechner: [http://miniweb.sourceforge.net/ MiniWeb]&lt;br /&gt;
&lt;br /&gt;
Dieses Tool runterladen und irgendwohin entpacken. Zum starten habe ich eine kleine Batchdatei geschrieben:&lt;br /&gt;
&amp;lt;pre&amp;gt;D:\Software\MiniWebServer\miniweb\miniweb.exe -p 80&amp;lt;/pre&amp;gt;&lt;br /&gt;
Die sorgt nur dafür, dass der Server auf Port 80 läuft.&lt;br /&gt;
&lt;br /&gt;
Im entpackten Verzeichnis ist ein Unterverzeichnis mit dem Namen &amp;quot;htdocs&amp;quot;. Dahin kopieren wir das soeben runtergeladene Modul aus dem Forum-Thread.&lt;br /&gt;
&lt;br /&gt;
Langsam sollte das cpan Tool auf unserer SSH Verbindung durchgelaufen sein.&lt;br /&gt;
&lt;br /&gt;
Nun wechseln wir (auf dem Linux Rechner) in das FHEM Verzeichnis (cd /opt/fhem/FHEM).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;wget http://IP-Adresse_EUres_Windows_Rechners/72_XiaomiDevice.pm&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
bringt die Datei in euer FHEM Verzeichnis.&lt;br /&gt;
&lt;br /&gt;
Jetzt noch die Rechte anpassen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo chown fhem:dialout /opt/fhem/FHEM/72_XiaomiDevice.pm&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Fertig.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Jetzt können wir auf die FHEM Oberfläche wechseln.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;reload 72_XiaomiDevice.pm&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
und unser runtergeladenes Modul steht in FHEM zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
==Einrichten des Moduls==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Mi_Vacuum XiaomiDevice 192.168.222.77 55387753545937326a33396943557999&lt;br /&gt;
&lt;br /&gt;
attr Mi_Vacuum subType VacuumCleaner&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Und schon (=etwa nach 10 Sekunden) sollte euer Roboter in FHEM mit ganz vielen Readings auftauchen.&lt;br /&gt;
&lt;br /&gt;
==Anwendung: Sprachsteuerung mit Alexa (einfach, ein und aus)==&lt;br /&gt;
Wie bindet man das jetzt schnell in Alexa ein?&lt;br /&gt;
&lt;br /&gt;
Wir legen uns in FHEM einen Dummy an. Dieser wird ein Switch (on off). Dazu noch ein DOIF oder ein notify, welches diesen Switch überwacht. Je nach Status des Dummys schalten wir den Roboter.&lt;br /&gt;
&lt;br /&gt;
Ein List meines Dummys:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 Internals: &lt;br /&gt;
   CFGFN &lt;br /&gt;
   NAME       Mi_Vacuum_Staubsauger &lt;br /&gt;
   NR         719473 &lt;br /&gt;
   STATE      on &lt;br /&gt;
   TYPE       dummy &lt;br /&gt;
   Readings: &lt;br /&gt;
     2017-09-18 21:10:12   state           on &lt;br /&gt;
 Attributes: &lt;br /&gt;
   alexaName  Mi_Vacuum_Staubsauger &lt;br /&gt;
   genericDeviceType switch &lt;br /&gt;
   room       alexa &lt;br /&gt;
   setList    on off &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mein DOIF:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define di_Mi_Vacuum DOIF ([Mi_Vacuum_Staubsauger:&amp;quot;on&amp;quot;]) (set Mi_Vacuum start) DOELSE (set Mi_Vacuum charge)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Attribut do always nicht vergessen!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Den Dummy setzen wir in den Raum, der unsere Alexa Geräte beinhaltet. Nun den Alexa FHEM Service neu starten. Anschließend sollte eine Suche nach neuen Geräten in Alexa unseren Dummy finden. Für diesen legen wir in Alexa einen neuen Raum an, z.B. Staubsauger.&lt;br /&gt;
&lt;br /&gt;
Fertig.&lt;br /&gt;
&lt;br /&gt;
Ein &amp;quot;Alexa schaltet den Staubsauger ein&amp;quot; lässt unseren Mi-Vacuum loslegen. &amp;quot;Alexa schalte den Staubsauger aus&amp;quot; schickt ihn wieder zurück zu seiner Station.&lt;br /&gt;
&lt;br /&gt;
==Quellen==&lt;br /&gt;
* {{Link2Forum|Topic=73052|LinkText=Forums-Thread}}&lt;br /&gt;
* {{Link2Forum|Topic=76940|LinkText=Diskussionsthread}}&lt;br /&gt;
* [http://miniweb.sourceforge.net/ MiniWeb], kleiner WebServer für Windows&lt;br /&gt;
* [https://xiaomi.flole.de/ Flole], alternative App für Android, die das Token nach GoogleDrive exportiert&lt;br /&gt;
* [http://www.roboter-forum.com/forumdisplay.php?130-Xiaomi Roboter-Forum] deutschsprachiges Forum, welches sich mit dem Mi Vacuum beschäftigt (auch vor dem Kauf des Roboters lohnt sich ein Besuch dort)&lt;br /&gt;
* [https://paypal.me/mm0 PayPal]-Link, um Markus M. Dankeschön zu sagen&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Mi_vacuum&amp;diff=22660</id>
		<title>Mi vacuum</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Mi_vacuum&amp;diff=22660"/>
		<updated>2017-09-21T16:52:56Z</updated>

		<summary type="html">&lt;p&gt;Rince: Rechte nur auf Modul beschränkt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
=Mi Vacuum=&lt;br /&gt;
Wie der preiswerte Staubsaugerroboter auch auf FHEM hört...&lt;br /&gt;
&lt;br /&gt;
==Für wen ist die Anleitung gedacht?==&lt;br /&gt;
Ich gehe davon aus, dass ihr ein funktionierendes FHEM auf einem Linux Rechner (Debian) betreibt.&lt;br /&gt;
&lt;br /&gt;
Weiterhin denke ich, dass euer Hauptarbeitsrechner unter Windows läuft.&lt;br /&gt;
&lt;br /&gt;
Als Smartphone OS Android (wer Apple hat, kann gerne die Token-Auslese-Geschichte hier beschreiben).&lt;br /&gt;
&lt;br /&gt;
Um das Teil auch von Alexa aus ein und aus zu schalten, sollte auch die Installation von Alexa in FHEM fertig sein.&lt;br /&gt;
&lt;br /&gt;
==Die Einrichtung des Moduls==&lt;br /&gt;
Das ist insofern spannend, als das Modul nicht offiziell in FHEM eingecheckt ist. Man muss also das Modul runterladen, auf den FHEM Rechner bringen etc...&lt;br /&gt;
&lt;br /&gt;
===Vorarbeiten (Linux)===&lt;br /&gt;
Zunächst fangen wir mal auf unserem FHEM Rechner an. Mit Putty verbinden wir uns per SSH mit dem FHEM Computer.&lt;br /&gt;
&lt;br /&gt;
Folgende Befehle können benötigt werden (Debian):&lt;br /&gt;
* &amp;lt;code&amp;gt;sudo apt-get install libjson-perl&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;sudo apt-get install libdigest-md5-perl&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;sudo apt-get install libcrypt-cbc-perl&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;sudo cpan Crypt::Rijndael_PP&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;sudo apt-get install libcrypt-ecb-perl&amp;lt;/code&amp;gt; (nur nötig, wenn ihr einen verschlüsselten Token mit 96 Zeichen habt)&lt;br /&gt;
* &amp;lt;code&amp;gt;sudo cpan Crypt::Cipher::AES&amp;lt;/code&amp;gt; (nur nötig, wenn Crypt::Rijndael_PP aus irgendwelchen Gründen nicht funktioniert)&lt;br /&gt;
Wenn bei dem ein oder anderen Modul die Meldung kommt, dass es schon installiert ist, einfach mit dem nächsten Befehl weiter machen. Das CPAN Teil würde ich am Schluss machen, das braucht ziemlich lang zum installieren.&lt;br /&gt;
&lt;br /&gt;
===Vorarbeiten am Smartphone (Token, Android)===&lt;br /&gt;
Das Problem ist folgendes:&lt;br /&gt;
&lt;br /&gt;
Wenn der Roboter mit dem WLAN verbunden wird, generiert er einen Token. Das ist ein Schlüssel, ohne den er sich nicht steuern lässt. Damit FHEM drauf zugreifen kann, benötigt man diesen Token.&lt;br /&gt;
&lt;br /&gt;
Für Android gibt es eine [https://xiaomi.flole.de/ alternative App] (Flole) um den Roboter zu steuern. Die originale Steuerung der Mi-Home App wird dadurch nicht beeinträchtigt! Also keine Angst, die coolen Karten bleiben erhalten.&lt;br /&gt;
&lt;br /&gt;
*Ich kann nur beschreiben, wie es bei mir funktioniert hat. Wenn es wer einfacher oder anders hinbekommen hat, ergänzt bitte den Wiki Eintrag*&lt;br /&gt;
Zunächst muss die Flole-App installiert werden. Zur Installation muss die Installation von unbekannten Quellen in den Sicherheitseinstellungen von Android erlaubt werden. Bitte nicht vergessen, die Enstellung nach der Installation der App wieder zu korrigieren.&lt;br /&gt;
&lt;br /&gt;
Ich hatte die Mi-Home App schon installiert:&lt;br /&gt;
* Mi-Vacuum aus der Mi-Home App löschen&lt;br /&gt;
* WLAN zurückgesetzt (die beiden Buttons lange gedrückt halten)&lt;br /&gt;
* den Roboter per Reset Taster zurückgesetzt&lt;br /&gt;
=&amp;gt; dennoch hat die App den Roboter nicht gefunden&lt;br /&gt;
&lt;br /&gt;
Lösung:&lt;br /&gt;
* der Mi Vacuum spannt sein eigenes WLAN Netz auf (damit verbinden)&lt;br /&gt;
* Tipp: ist man aus der App mal rausgeflogen (Verbindung gescheitert), muss man die App wirklich unter Android abschießen, bevor sie wieder funktioniert&lt;br /&gt;
* jetzt die Verbindung mit der Flole App herstellen&lt;br /&gt;
* WLAN am Android wieder auf den eigenen AP zurück stellen&lt;br /&gt;
* die IP Adresse des Roboters rausfinden (z.B. FritzBox fragen)&lt;br /&gt;
* in der Flole App die IP Adresse des Mi Vacuum eintragen&lt;br /&gt;
* Die Settings nach Google Drive exportieren (sollte wenige Sekunden dauern. Wenn das Fenster grau bleibt, hat man vermutlich die IP Adresse noch nicht eingetragen ;) )&lt;br /&gt;
* Anschließend kann man den Mi Vacuum wider mit Mi-Home suchen und verbinden&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Jetzt kann man aus Google Drive die Datei &amp;quot;FloleXiaomiRemote.settings&amp;quot; runterladen und im Editor der eigenen Wahl öffnen. Ich nehme dafür gerne Notepad++&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In meiner steht z.B.:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[{&amp;quot;c&amp;quot;:&amp;quot;192.168.222.77&amp;quot;,&amp;quot;d&amp;quot;:64647999,&amp;quot;e&amp;quot;:&amp;quot;55387753545937326a33396943557999&amp;quot;,&amp;quot;f&amp;quot;:&amp;quot;Mi Vacuum&amp;quot;,&amp;quot;g&amp;quot;:0}]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zahlenkolonne &amp;quot;55387753545937326a33396943557999&amp;quot; ist der Token. Den behalten wir mal im Auge, bzw. der Zwischenablage.&lt;br /&gt;
&lt;br /&gt;
===Installation des inoffiziellen Moduls===&lt;br /&gt;
Der folgende Teil ist für völlige Noobs. Wenn ihr einen eleganteren Weg kennt, her damit.&lt;br /&gt;
&lt;br /&gt;
Zunächst bitte das Modul aus dem Forum herunterladen.&lt;br /&gt;
[https://forum.fhem.de/index.php/topic,73052.0.htmlm Hier] befindet sich der Thread. Markus M. hat sich die Mühe gemacht, ein Modul zu schreiben. Solange es nicht offiziell eingecheckt ist, muss man es händisch installieren. Das kann man wie folgt machen:&lt;br /&gt;
* das Modul zunächst auf seinem Windows PC speichern&lt;br /&gt;
&lt;br /&gt;
Wie kommt das Modul nun auf den eigenen RasPi?&lt;br /&gt;
&lt;br /&gt;
Ich nutze dafür einen kleinen HTTP Server auf meinem Windows Rechner: [http://miniweb.sourceforge.net/ MiniWeb]&lt;br /&gt;
&lt;br /&gt;
Dieses Tool runterladen und irgendwohin entpacken. Zum starten habe ich eine kleine Batchdatei geschrieben:&lt;br /&gt;
&amp;lt;pre&amp;gt;D:\Software\MiniWebServer\miniweb\miniweb.exe -p 80&amp;lt;/pre&amp;gt;&lt;br /&gt;
Die sorgt nur dafür, dass der Server auf Port 80 läuft.&lt;br /&gt;
&lt;br /&gt;
Im entpackten Verzeichnis ist ein Unterverzeichnis mit dem Namen &amp;quot;htdocs&amp;quot;. Dahin kopieren wir das soeben runtergeladene Modul aus dem Forum-Thread.&lt;br /&gt;
&lt;br /&gt;
Langsam sollte das cpan Tool auf unserer SSH Verbindung durchgelaufen sein.&lt;br /&gt;
&lt;br /&gt;
Nun wechseln wir (auf dem Linux Rechner) in das FHEM Verzeichnis (cd /opt/fhem/FHEM).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;wget http://IP-Adresse_EUres_Windows_Rechners/72_XiaomiDevice.pm&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
bringt die Datei in euer FHEM Verzeichnis.&lt;br /&gt;
&lt;br /&gt;
Jetzt noch die Rechte anpassen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo chown fhem:dialout /opt/fhem/FHEM/72_XiaomiDevice.pm&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Fertig.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Jetzt können wir auf die FHEM Oberfläche wechseln.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;reload 72_XiaomiDevice.pm&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
und unser runtergeladenes Modul steht in FHEM zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
==Einrichten des Moduls==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Mi_Vacuum XiaomiDevice 192.168.222.77 55387753545937326a33396943557999&lt;br /&gt;
&lt;br /&gt;
attr Mi_Vacuum subType VacuumCleaner&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Und schon (=etwa nach 10 Sekunden) sollte euer Roboter in FHEM mit ganz vielen Readings auftauchen.&lt;br /&gt;
&lt;br /&gt;
==Anwendung: Sprachsteuerung mit Alexa (einfach, ein und aus)==&lt;br /&gt;
Wie bindet man das jetzt schnell in Alexa ein?&lt;br /&gt;
&lt;br /&gt;
Wir legen uns in FHEM einen Dummy an. Dieser wird ein Switch (on off). Dazu noch ein DOIF oder ein notify, welches diesen Switch überwacht. Je nach Status des Dummys schalten wir den Roboter.&lt;br /&gt;
&lt;br /&gt;
Ein List meines Dummys:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 Internals: &lt;br /&gt;
   CFGFN &lt;br /&gt;
   NAME       Mi_Vacuum_Staubsauger &lt;br /&gt;
   NR         719473 &lt;br /&gt;
   STATE      on &lt;br /&gt;
   TYPE       dummy &lt;br /&gt;
   Readings: &lt;br /&gt;
     2017-09-18 21:10:12   state           on &lt;br /&gt;
 Attributes: &lt;br /&gt;
   alexaName  Mi_Vacuum_Staubsauger &lt;br /&gt;
   genericDeviceType switch &lt;br /&gt;
   room       alexa &lt;br /&gt;
   setList    on off &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mein DOIF:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define di_Mi_Vacuum DOIF ([Mi_Vacuum_Staubsauger:&amp;quot;on&amp;quot;]) (set Mi_Vacuum start) DOELSE (set Mi_Vacuum charge)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Attribut do always nicht vergessen!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Den Dummy setzen wir in den Raum, der unsere Alexa Geräte beinhaltet. Nun den Alexa FHEM Service neu starten. Anschließend sollte eine Suche nach neuen Geräten in Alexa unseren Dummy finden. Für diesen legen wir in Alexa einen neuen Raum an, z.B. Staubsauger.&lt;br /&gt;
&lt;br /&gt;
Fertig.&lt;br /&gt;
&lt;br /&gt;
Ein &amp;quot;Alexa schaltet den Staubsauger ein&amp;quot; lässt unseren Mi-Vacuum loslegen. &amp;quot;Alexa schalte den Staubsauger aus&amp;quot; schickt ihn wieder zurück zu seiner Station.&lt;br /&gt;
&lt;br /&gt;
==Quellen==&lt;br /&gt;
* {{Link2Forum|Topic=73052|LinkText=Forums-Thread}}&lt;br /&gt;
* {{Link2Forum|Topic=76940|LinkText=Diskussionsthread}}&lt;br /&gt;
* [http://miniweb.sourceforge.net/ MiniWeb], kleiner WebServer für Windows&lt;br /&gt;
* [https://xiaomi.flole.de/ Flole], alternative App für Android, die das Token nach GoogleDrive exportiert&lt;br /&gt;
* [http://www.roboter-forum.com/forumdisplay.php?130-Xiaomi Roboter-Forum] deutschsprachiges Forum, welches sich mit dem Mi Vacuum beschäftigt (auch vor dem Kauf des Roboters lohnt sich ein Besuch dort)&lt;br /&gt;
* [https://paypal.me/mm0 PayPal]-Link, um Markus M. Dankeschön zu sagen&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Mi_vacuum&amp;diff=22646</id>
		<title>Mi vacuum</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Mi_vacuum&amp;diff=22646"/>
		<updated>2017-09-21T04:28:33Z</updated>

		<summary type="html">&lt;p&gt;Rince: Link zum Diskussionsthread im Forum ergänzt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
=Mi Vacuum=&lt;br /&gt;
Wie der preiswerte Staubsaugerroboter auch auf FHEM hört...&lt;br /&gt;
&lt;br /&gt;
==Für wen ist die Anleitung gedacht?==&lt;br /&gt;
Ich gehe davon aus, dass ihr ein funktionierendes FHEM auf einem Linux Rechner (Debian) betreibt.&lt;br /&gt;
&lt;br /&gt;
Weiterhin denke ich, dass euer Hauptarbeitsrechner unter Windows läuft.&lt;br /&gt;
&lt;br /&gt;
Als Smartphone OS Android (wer Apple hat, kann gerne die Token-Auslese-Geschichte hier beschreiben).&lt;br /&gt;
&lt;br /&gt;
Um das Teil auch von Alexa aus ein und aus zu schalten, sollte auch die Installation von Alexa in FHEM fertig sein.&lt;br /&gt;
&lt;br /&gt;
==Die Einrichtung des Moduls==&lt;br /&gt;
Das ist insofern spannend, als das Modul nicht offiziell in FHEM eingecheckt ist. Man muss also das Modul runterladen, auf den FHEM Rechner bringen etc...&lt;br /&gt;
&lt;br /&gt;
===Vorarbeiten (Linux)===&lt;br /&gt;
Zunächst fangen wir mal auf unserem FHEM Rechner an. Mit Putty verbinden wir uns per SSH mit dem FHEM Computer.&lt;br /&gt;
&lt;br /&gt;
Folgende Befehle können benötigt werden (Debian):&lt;br /&gt;
* &amp;lt;code&amp;gt;sudo apt-get install libjson-perl&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;sudo apt-get install libdigest-md5-perl&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;sudo apt-get install libcrypt-cbc-perl&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;sudo cpan Crypt::Rijndael_PP&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;sudo apt-get install libcrypt-ecb-perl&amp;lt;/code&amp;gt; (nur nötig, wenn ihr einen verschlüsselten Token mit 96 Zeichen habt)&lt;br /&gt;
* &amp;lt;code&amp;gt;sudo cpan Crypt::Cipher::AES&amp;lt;/code&amp;gt; (nur nötig, wenn Crypt::Rijndael_PP aus irgendwelchen Gründen nicht funktioniert)&lt;br /&gt;
Wenn bei dem ein oder anderen Modul die Meldung kommt, dass es schon installiert ist, einfach mit dem nächsten Befehl weiter machen. Das CPAN Teil würde ich am Schluss machen, das braucht ziemlich lang zum installieren.&lt;br /&gt;
&lt;br /&gt;
===Vorarbeiten am Smartphone (Token, Android)===&lt;br /&gt;
Das Problem ist folgendes:&lt;br /&gt;
&lt;br /&gt;
Wenn der Roboter mit dem WLAN verbunden wird, generiert er einen Token. Das ist ein Schlüssel, ohne den er sich nicht steuern lässt. Damit FHEM drauf zugreifen kann, benötigt man diesen Token.&lt;br /&gt;
&lt;br /&gt;
Für Android gibt es eine [https://xiaomi.flole.de/ alternative App] (Flole) um den Roboter zu steuern. Die originale Steuerung der Mi-Home App wird dadurch nicht beeinträchtigt! Also keine Angst, die coolen Karten bleiben erhalten.&lt;br /&gt;
&lt;br /&gt;
*Ich kann nur beschreiben, wie es bei mir funktioniert hat. Wenn es wer einfacher oder anders hinbekommen hat, ergänzt bitte den Wiki Eintrag*&lt;br /&gt;
Zunächst muss die Flole-App installiert werden. Zur Installation muss die Installation von unbekannten Quellen in den Sicherheitseinstellungen von Android erlaubt werden. Bitte nicht vergessen, die Enstellung nach der Installation der App wieder zu korrigieren.&lt;br /&gt;
&lt;br /&gt;
Ich hatte die Mi-Home App schon installiert:&lt;br /&gt;
* Mi-Vacuum aus der Mi-Home App löschen&lt;br /&gt;
* WLAN zurückgesetzt (die beiden Buttons lange gedrückt halten)&lt;br /&gt;
* den Roboter per Reset Taster zurückgesetzt&lt;br /&gt;
=&amp;gt; dennoch hat die App den Roboter nicht gefunden&lt;br /&gt;
&lt;br /&gt;
Lösung:&lt;br /&gt;
* der Mi Vacuum spannt sein eigenes WLAN Netz auf (damit verbinden)&lt;br /&gt;
* Tipp: ist man aus der App mal rausgeflogen (Verbindung gescheitert), muss man die App wirklich unter Android abschießen, bevor sie wieder funktioniert&lt;br /&gt;
* jetzt die Verbindung mit der Flole App herstellen&lt;br /&gt;
* WLAN am Android wieder auf den eigenen AP zurück stellen&lt;br /&gt;
* die IP Adresse des Roboters rausfinden (z.B. FritzBox fragen)&lt;br /&gt;
* in der Flole App die IP Adresse des Mi Vacuum eintragen&lt;br /&gt;
* Die Settings nach Google Drive exportieren (sollte wenige Sekunden dauern. Wenn das Fenster grau bleibt, hat man vermutlich die IP Adresse noch nicht eingetragen ;) )&lt;br /&gt;
* Anschließend kann man den Mi Vacuum wider mit Mi-Home suchen und verbinden&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Jetzt kann man aus Google Drive die Datei &amp;quot;FloleXiaomiRemote.settings&amp;quot; runterladen und im Editor der eigenen Wahl öffnen. Ich nehme dafür gerne Notepad++&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In meiner steht z.B.:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[{&amp;quot;c&amp;quot;:&amp;quot;192.168.222.77&amp;quot;,&amp;quot;d&amp;quot;:64647999,&amp;quot;e&amp;quot;:&amp;quot;55387753545937326a33396943557999&amp;quot;,&amp;quot;f&amp;quot;:&amp;quot;Mi Vacuum&amp;quot;,&amp;quot;g&amp;quot;:0}]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zahlenkolonne &amp;quot;55387753545937326a33396943557999&amp;quot; ist der Token. Den behalten wir mal im Auge, bzw. der Zwischenablage.&lt;br /&gt;
&lt;br /&gt;
===Installation des inoffiziellen Moduls===&lt;br /&gt;
Der folgende Teil ist für völlige Noobs. Wenn ihr einen eleganteren Weg kennt, her damit.&lt;br /&gt;
&lt;br /&gt;
Zunächst bitte das Modul aus dem Forum herunterladen.&lt;br /&gt;
[https://forum.fhem.de/index.php/topic,73052.0.htmlm Hier] befindet sich der Thread. Markus M. hat sich die Mühe gemacht, ein Modul zu schreiben. Solange es nicht offiziell eingecheckt ist, muss man es händisch installieren. Das kann man wie folgt machen:&lt;br /&gt;
* das Modul zunächst auf seinem Windows PC speichern&lt;br /&gt;
&lt;br /&gt;
Wie kommt das Modul nun auf den eigenen RasPi?&lt;br /&gt;
&lt;br /&gt;
Ich nutze dafür einen kleinen HTTP Server auf meinem Windows Rechner: [http://miniweb.sourceforge.net/ MiniWeb]&lt;br /&gt;
&lt;br /&gt;
Dieses Tool runterladen und irgendwohin entpacken. Zum starten habe ich eine kleine Batchdatei geschrieben:&lt;br /&gt;
&amp;lt;pre&amp;gt;D:\Software\MiniWebServer\miniweb\miniweb.exe -p 80&amp;lt;/pre&amp;gt;&lt;br /&gt;
Die sorgt nur dafür, dass der Server auf Port 80 läuft.&lt;br /&gt;
&lt;br /&gt;
Im entpackten Verzeichnis ist ein Unterverzeichnis mit dem Namen &amp;quot;htdocs&amp;quot;. Dahin kopieren wir das soeben runtergeladene Modul aus dem Forum-Thread.&lt;br /&gt;
&lt;br /&gt;
Langsam sollte das cpan Tool auf unserer SSH Verbindung durchgelaufen sein.&lt;br /&gt;
&lt;br /&gt;
Nun wechseln wir (auf dem Linux Rechner) in das FHEM Verzeichnis (cd /opt/fhem/FHEM).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;wget http://IP-Adresse_EUres_Windows_Rechners/72_XiaomiDevice.pm&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
bringt die Datei in euer FHEM Verzeichnis.&lt;br /&gt;
&lt;br /&gt;
Jetzt noch die Rechte anpassen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo chown -R fhem:dialout /opt/fhem&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Fertig.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Jetzt können wir auf die FHEM Oberfläche wechseln.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;reload 72_XiaomiDevice.pm&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
und unser runtergeladenes Modul steht in FHEM zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
==Einrichten des Moduls==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Mi_Vacuum XiaomiDevice 192.168.222.77 55387753545937326a33396943557999&lt;br /&gt;
&lt;br /&gt;
attr Mi_Vacuum subType VacuumCleaner&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Und schon (=etwa nach 10 Sekunden) sollte euer Roboter in FHEM mit ganz vielen Readings auftauchen.&lt;br /&gt;
&lt;br /&gt;
==Anwendung: Sprachsteuerung mit Alexa (einfach, ein und aus)==&lt;br /&gt;
Wie bindet man das jetzt schnell in Alexa ein?&lt;br /&gt;
&lt;br /&gt;
Wir legen uns in FHEM einen Dummy an. Dieser wird ein Switch (on off). Dazu noch ein DOIF oder ein notify, welches diesen Switch überwacht. Je nach Status des Dummys schalten wir den Roboter.&lt;br /&gt;
&lt;br /&gt;
Ein List meines Dummys:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 Internals: &lt;br /&gt;
   CFGFN &lt;br /&gt;
   NAME       Mi_Vacuum_Staubsauger &lt;br /&gt;
   NR         719473 &lt;br /&gt;
   STATE      on &lt;br /&gt;
   TYPE       dummy &lt;br /&gt;
   Readings: &lt;br /&gt;
     2017-09-18 21:10:12   state           on &lt;br /&gt;
 Attributes: &lt;br /&gt;
   alexaName  Mi_Vacuum_Staubsauger &lt;br /&gt;
   genericDeviceType switch &lt;br /&gt;
   room       alexa &lt;br /&gt;
   setList    on off &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mein DOIF:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define di_Mi_Vacuum DOIF ([Mi_Vacuum_Staubsauger:&amp;quot;on&amp;quot;]) (set Mi_Vacuum start) DOELSE (set Mi_Vacuum charge)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Attribut do always nicht vergessen!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Den Dummy setzen wir in den Raum, der unsere Alexa Geräte beinhaltet. Nun den Alexa FHEM Service neu starten. Anschließend sollte eine Suche nach neuen Geräten in Alexa unseren Dummy finden. Für diesen legen wir in Alexa einen neuen Raum an, z.B. Staubsauger.&lt;br /&gt;
&lt;br /&gt;
Fertig.&lt;br /&gt;
&lt;br /&gt;
Ein &amp;quot;Alexa schaltet den Staubsauger ein&amp;quot; lässt unseren Mi-Vacuum loslegen. &amp;quot;Alexa schalte den Staubsauger aus&amp;quot; schickt ihn wieder zurück zu seiner Station.&lt;br /&gt;
&lt;br /&gt;
==Quellen==&lt;br /&gt;
* {{Link2Forum|Topic=73052|LinkText=Forums-Thread}}&lt;br /&gt;
* {{Link2Forum|Topic=76940|LinkText=Diskussionsthread}}&lt;br /&gt;
* [http://miniweb.sourceforge.net/ MiniWeb], kleiner WebServer für Windows&lt;br /&gt;
* [https://xiaomi.flole.de/ Flole], alternative App für Android, die das Token nach GoogleDrive exportiert&lt;br /&gt;
* [http://www.roboter-forum.com/forumdisplay.php?130-Xiaomi Roboter-Forum] deutschsprachiges Forum, welches sich mit dem Mi Vacuum beschäftigt (auch vor dem Kauf des Roboters lohnt sich ein Besuch dort)&lt;br /&gt;
* [https://paypal.me/mm0 PayPal]-Link, um Markus M. Dankeschön zu sagen&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Mi_vacuum&amp;diff=22627</id>
		<title>Mi vacuum</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Mi_vacuum&amp;diff=22627"/>
		<updated>2017-09-20T20:47:28Z</updated>

		<summary type="html">&lt;p&gt;Rince: /* Anwendung: Sprachsteuerung mit Alexa (einfach, ein und aus) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
=Mi Vacuum=&lt;br /&gt;
Wie der preiswerte Staubsaugerroboter auch auf FHEM hört...&lt;br /&gt;
&lt;br /&gt;
==Für wen ist die Anleitung gedacht?==&lt;br /&gt;
Ich gehe davon aus, dass ihr ein funktionierendes FHEM auf einem Linux Rechner (Debian) betreibt.&lt;br /&gt;
&lt;br /&gt;
Weiterhin denke ich, dass euer Hauptarbeitsrechner unter Windows läuft.&lt;br /&gt;
&lt;br /&gt;
Als Smartphone OS Android (wer Apple hat, kann gerne die Token-Auslese-Geschichte hier beschreiben).&lt;br /&gt;
&lt;br /&gt;
Um das Teil auch von Alexa aus ein und aus zu schalten, sollte auch die Installation von Alexa in FHEM fertig sein.&lt;br /&gt;
&lt;br /&gt;
==Die Einrichtung des Moduls==&lt;br /&gt;
Das ist insofern spannend, als das Modul nicht offiziell in FHEM eingecheckt ist. Man muss also das Modul runterladen, auf den FHEM Rechner bringen etc...&lt;br /&gt;
&lt;br /&gt;
===Vorarbeiten (Linux)===&lt;br /&gt;
Zunächst fangen wir mal auf unserem FHEM Rechner an. Mit Putty verbinden wir uns per SSH mit dem FHEM Computer.&lt;br /&gt;
&lt;br /&gt;
Folgende Befehle können benötigt werden (Debian):&lt;br /&gt;
* sudo apt-get install libjson-perl&lt;br /&gt;
* sudo apt-get install libdigest-md5-perl&lt;br /&gt;
* sudo apt-get install libcrypt-cbc-perl&lt;br /&gt;
* sudo apt-get install libcrypt-ecb-perl&lt;br /&gt;
* sudo cpan Crypt::Cipher::AES&lt;br /&gt;
Wenn bei dem ein oder anderen Modul die Meldung kommt, dass es schon installiert ist, einfach mit dem nächsten Befehl weiter machen. Das CPAN Teil würde ich am Schluss machen, das braucht ziemlich lang zum installieren.&lt;br /&gt;
&lt;br /&gt;
===Vorarbeiten am Smartphone (Token, Android)===&lt;br /&gt;
Das Problem ist folgendes:&lt;br /&gt;
&lt;br /&gt;
Wenn der Roboter mit dem WLAN verbunden wird, generiert er einen Token. Das ist ein Schlüssel, ohne den er sich nicht steuern lässt. Damit FHEM drauf zugreifen kann, benötigt man diesen Token.&lt;br /&gt;
&lt;br /&gt;
Für Android gibt es eine [https://xiaomi.flole.de/ alternative App] (Flole) um den Roboter zu steuern. Die originale Steuerung der Mi-Home App wird dadurch nicht beeinträchtigt! Also keine Angst, die coolen Karten bleiben erhalten.&lt;br /&gt;
&lt;br /&gt;
*Ich kann nur beschreiben, wie es bei mir funktioniert hat. Wenn es wer einfacher oder anders hinbekommen hat, ergänzt bitte den Wiki Eintrag*&lt;br /&gt;
Zunächst muss die Flole-App installiert werden. Zur Installation muss die Installation von unbekannten Quellen in den Sicherheitseinstellungen von Android erlaubt werden. Bitte nicht vergessen, die Enstellung nach der Installation der App wieder zu korrigieren.&lt;br /&gt;
&lt;br /&gt;
Ich hatte die Mi-Home App schon installiert:&lt;br /&gt;
* Mi-Vacuum aus der Mi-Home App löschen&lt;br /&gt;
* WLAN zurückgesetzt (die beiden Buttons lange gedrückt halten)&lt;br /&gt;
* den Roboter per Reset Taster zurückgesetzt&lt;br /&gt;
=&amp;gt; dennoch hat die App den Roboter nicht gefunden&lt;br /&gt;
&lt;br /&gt;
Lösung:&lt;br /&gt;
* der Mi Vacuum spannt sein eigenes WLAN Netz auf (damit verbinden)&lt;br /&gt;
* Tipp: ist man aus der App mal rausgeflogen (Verbindung gescheitert), muss man die App wirklich unter Android abschießen, bevor sie wieder funktioniert&lt;br /&gt;
* jetzt die Verbindung mit der Flole App herstellen&lt;br /&gt;
* WLAN am Android wieder auf den eigenen AP zurück stellen&lt;br /&gt;
* die IP Adresse des Roboters rausfinden (z.B. FritzBox fragen)&lt;br /&gt;
* in der Flole App die IP Adresse des Mi Vacuum eintragen&lt;br /&gt;
* Die Settings nach Google Drive exportieren (sollte wenige Sekunden dauern. Wenn das Fenster grau bleibt, hat man vermutlich die IP Adresse noch nicht eingetragen ;) )&lt;br /&gt;
* Anschließend kann man den Mi Vacuum wider mit Mi-Home suchen und verbinden&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Jetzt kann man aus Google Drive die Datei &amp;quot;FloleXiaomiRemote.settings&amp;quot; runterladen und im Editor der eigenen Wahl öffnen. Ich nehme dafür gerne Notepad++&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In meiner steht z.B.:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[{&amp;quot;c&amp;quot;:&amp;quot;192.168.222.77&amp;quot;,&amp;quot;d&amp;quot;:64647999,&amp;quot;e&amp;quot;:&amp;quot;55387753545937326a33396943557999&amp;quot;,&amp;quot;f&amp;quot;:&amp;quot;Mi Vacuum&amp;quot;,&amp;quot;g&amp;quot;:0}]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zahlenkolonne &amp;quot;55387753545937326a33396943557999&amp;quot; ist der Token. Den behalten wir mal im Auge, bzw. der Zwischenablage.&lt;br /&gt;
&lt;br /&gt;
===Installation des inoffiziellen Moduls===&lt;br /&gt;
Der folgende Teil ist für völlige Noobs. Wenn ihr einen eleganteren Weg kennt, her damit.&lt;br /&gt;
&lt;br /&gt;
Zunächst bitte das Modul aus dem Forum herunterladen.&lt;br /&gt;
[https://forum.fhem.de/index.php/topic,73052.0.htmlm Hier] befindet sich der Thread. Markus M. hat sich die Mühe gemacht, ein Modul zu schreiben. Solange es nicht offiziell eingecheckt ist, muss man es händisch installieren. Das kann man wie folgt machen:&lt;br /&gt;
* das Modul zunächst auf seinem Windows PC speichern&lt;br /&gt;
&lt;br /&gt;
Wie kommt das Modul nun auf den eigenen RasPi?&lt;br /&gt;
&lt;br /&gt;
Ich nutze dafür einen kleinen HTTP Server auf meinem Windows Rechner: [http://miniweb.sourceforge.net/ MiniWeb]&lt;br /&gt;
&lt;br /&gt;
Dieses Tool runterladen und irgendwohin entpacken. Zum starten habe ich eine kleine Batchdatei geschrieben:&lt;br /&gt;
D:\Software\MiniWebServer\miniweb\miniweb.exe -p 80&lt;br /&gt;
Die sorgt nur dafür, dass der Server auf Port 80 läuft.&lt;br /&gt;
&lt;br /&gt;
Im entpackten Verzeichnis ist ein Unterverzeichnis mit dem Namen &amp;quot;htdocs&amp;quot;. Dahin kopieren wir das soeben runtergeladene Modul aus dem Forum-Thread.&lt;br /&gt;
&lt;br /&gt;
Langsam sollte das cpan Tool auf unserer SSH Verbindung durchgelaufen sein.&lt;br /&gt;
&lt;br /&gt;
Nun wechseln wir (auf dem Linux Rechner) in das FHEM Verzeichnis (cd /opt/fhem/FHEM).&lt;br /&gt;
&lt;br /&gt;
wget http://IP-Adresse_EUres_Windows_Rechners/72_XiaomiDevice.pm&lt;br /&gt;
&lt;br /&gt;
bringt die Datei in euer FHEM Verzeichnis.&lt;br /&gt;
&lt;br /&gt;
Jetzt noch die Rechte anpassen:&lt;br /&gt;
&lt;br /&gt;
sudo chown -R fhem:dialout /opt/fhem&lt;br /&gt;
&lt;br /&gt;
Fertig.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Jetzt können wir auf die FHEM Oberfläche wechseln.&lt;br /&gt;
&lt;br /&gt;
reload 72_XiaomiDevice.pm&lt;br /&gt;
&lt;br /&gt;
und unser runtergeladenes Modul steht in FHEM zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
==Einrichten des Moduls==&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
define Mi_Vacuum XiaomiDevice 192.168.222.77 55387753545937326a33396943557999&lt;br /&gt;
&lt;br /&gt;
attr Mi_Vacuum subType VacuumCleaner&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Und schon (=etwa nach 10 Sekunden) sollte euer Roboter in FHEM mit ganz vielen Readings auftauchen.&lt;br /&gt;
&lt;br /&gt;
==Anwendung: Sprachsteuerung mit Alexa (einfach, ein und aus)==&lt;br /&gt;
Wie bindet man das jetzt schnell in Alexa ein?&lt;br /&gt;
&lt;br /&gt;
Wir legen uns in FHEM einen Dummy an. Dieser wird ein Switch (on off). Dazu noch ein DOIF oder ein notify, welches diesen Switch überwacht. Je nach Status des Dummys schalten wir den Roboter.&lt;br /&gt;
&lt;br /&gt;
Ein List meines Dummys:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 Internals: &lt;br /&gt;
   CFGFN &lt;br /&gt;
   NAME       Mi_Vacuum_Staubsauger &lt;br /&gt;
   NR         719473 &lt;br /&gt;
   STATE      on &lt;br /&gt;
   TYPE       dummy &lt;br /&gt;
   Readings: &lt;br /&gt;
     2017-09-18 21:10:12   state           on &lt;br /&gt;
 Attributes: &lt;br /&gt;
   alexaName  Mi_Vacuum_Staubsauger &lt;br /&gt;
   genericDeviceType switch &lt;br /&gt;
   room       alexa &lt;br /&gt;
   setList    on off &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mein DOIF:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
define di_Mi_Vacuum DOIF ([Mi_Vacuum_Staubsauger:&amp;quot;on&amp;quot;]) (set Mi_Vacuum start) DOELSE (set Mi_Vacuum charge)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Attribut do always nicht vergessen!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Den Dummy setzen wir in den Raum, der unsere Alexa Geräte beinhaltet. Nun den Alexa FHEM Service neu starten. Anschließend sollte eine Suche nach neuen Geräten in Alexa unseren Dummy finden. Für diesen legen wir in Alexa einen neuen Raum an, z.B. Staubsauger.&lt;br /&gt;
&lt;br /&gt;
Fertig.&lt;br /&gt;
&lt;br /&gt;
Ein &amp;quot;Alexa schaltet den Staubsauger ein&amp;quot; lässt unseren Mi-Vacuum loslegen. &amp;quot;Alexa schalte den Staubsauger aus&amp;quot; schickt ihn wieder zurück zu seiner Station.&lt;br /&gt;
&lt;br /&gt;
==Quellen==&lt;br /&gt;
 [https://forum.fhem.de/index.php/topic,73052.0.html Forums-Thread]&lt;br /&gt;
 [http://miniweb.sourceforge.net/ MiniWeb], kleiner WebServer für Windows&lt;br /&gt;
 [https://xiaomi.flole.de/ Flole], alternative App für Android, die das Token nach GoogleDrive exportiert&lt;br /&gt;
 [http://www.roboter-forum.com/forumdisplay.php?130-Xiaomi Roboter-Forum] deutschsprachiges Forum, welches sich mit dem Mi Vacuum beschäftigt (auch vor dem Kauf des Roboters lohnt sich ein Besuch dort)&lt;br /&gt;
 [https://paypal.me/mm0 PayPal]-Link, um Markus M. Dankeschön zu sagen&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Mi_vacuum&amp;diff=22626</id>
		<title>Mi vacuum</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Mi_vacuum&amp;diff=22626"/>
		<updated>2017-09-20T20:45:55Z</updated>

		<summary type="html">&lt;p&gt;Rince: /* Einrichten des Moduls */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
=Mi Vacuum=&lt;br /&gt;
Wie der preiswerte Staubsaugerroboter auch auf FHEM hört...&lt;br /&gt;
&lt;br /&gt;
==Für wen ist die Anleitung gedacht?==&lt;br /&gt;
Ich gehe davon aus, dass ihr ein funktionierendes FHEM auf einem Linux Rechner (Debian) betreibt.&lt;br /&gt;
&lt;br /&gt;
Weiterhin denke ich, dass euer Hauptarbeitsrechner unter Windows läuft.&lt;br /&gt;
&lt;br /&gt;
Als Smartphone OS Android (wer Apple hat, kann gerne die Token-Auslese-Geschichte hier beschreiben).&lt;br /&gt;
&lt;br /&gt;
Um das Teil auch von Alexa aus ein und aus zu schalten, sollte auch die Installation von Alexa in FHEM fertig sein.&lt;br /&gt;
&lt;br /&gt;
==Die Einrichtung des Moduls==&lt;br /&gt;
Das ist insofern spannend, als das Modul nicht offiziell in FHEM eingecheckt ist. Man muss also das Modul runterladen, auf den FHEM Rechner bringen etc...&lt;br /&gt;
&lt;br /&gt;
===Vorarbeiten (Linux)===&lt;br /&gt;
Zunächst fangen wir mal auf unserem FHEM Rechner an. Mit Putty verbinden wir uns per SSH mit dem FHEM Computer.&lt;br /&gt;
&lt;br /&gt;
Folgende Befehle können benötigt werden (Debian):&lt;br /&gt;
* sudo apt-get install libjson-perl&lt;br /&gt;
* sudo apt-get install libdigest-md5-perl&lt;br /&gt;
* sudo apt-get install libcrypt-cbc-perl&lt;br /&gt;
* sudo apt-get install libcrypt-ecb-perl&lt;br /&gt;
* sudo cpan Crypt::Cipher::AES&lt;br /&gt;
Wenn bei dem ein oder anderen Modul die Meldung kommt, dass es schon installiert ist, einfach mit dem nächsten Befehl weiter machen. Das CPAN Teil würde ich am Schluss machen, das braucht ziemlich lang zum installieren.&lt;br /&gt;
&lt;br /&gt;
===Vorarbeiten am Smartphone (Token, Android)===&lt;br /&gt;
Das Problem ist folgendes:&lt;br /&gt;
&lt;br /&gt;
Wenn der Roboter mit dem WLAN verbunden wird, generiert er einen Token. Das ist ein Schlüssel, ohne den er sich nicht steuern lässt. Damit FHEM drauf zugreifen kann, benötigt man diesen Token.&lt;br /&gt;
&lt;br /&gt;
Für Android gibt es eine [https://xiaomi.flole.de/ alternative App] (Flole) um den Roboter zu steuern. Die originale Steuerung der Mi-Home App wird dadurch nicht beeinträchtigt! Also keine Angst, die coolen Karten bleiben erhalten.&lt;br /&gt;
&lt;br /&gt;
*Ich kann nur beschreiben, wie es bei mir funktioniert hat. Wenn es wer einfacher oder anders hinbekommen hat, ergänzt bitte den Wiki Eintrag*&lt;br /&gt;
Zunächst muss die Flole-App installiert werden. Zur Installation muss die Installation von unbekannten Quellen in den Sicherheitseinstellungen von Android erlaubt werden. Bitte nicht vergessen, die Enstellung nach der Installation der App wieder zu korrigieren.&lt;br /&gt;
&lt;br /&gt;
Ich hatte die Mi-Home App schon installiert:&lt;br /&gt;
* Mi-Vacuum aus der Mi-Home App löschen&lt;br /&gt;
* WLAN zurückgesetzt (die beiden Buttons lange gedrückt halten)&lt;br /&gt;
* den Roboter per Reset Taster zurückgesetzt&lt;br /&gt;
=&amp;gt; dennoch hat die App den Roboter nicht gefunden&lt;br /&gt;
&lt;br /&gt;
Lösung:&lt;br /&gt;
* der Mi Vacuum spannt sein eigenes WLAN Netz auf (damit verbinden)&lt;br /&gt;
* Tipp: ist man aus der App mal rausgeflogen (Verbindung gescheitert), muss man die App wirklich unter Android abschießen, bevor sie wieder funktioniert&lt;br /&gt;
* jetzt die Verbindung mit der Flole App herstellen&lt;br /&gt;
* WLAN am Android wieder auf den eigenen AP zurück stellen&lt;br /&gt;
* die IP Adresse des Roboters rausfinden (z.B. FritzBox fragen)&lt;br /&gt;
* in der Flole App die IP Adresse des Mi Vacuum eintragen&lt;br /&gt;
* Die Settings nach Google Drive exportieren (sollte wenige Sekunden dauern. Wenn das Fenster grau bleibt, hat man vermutlich die IP Adresse noch nicht eingetragen ;) )&lt;br /&gt;
* Anschließend kann man den Mi Vacuum wider mit Mi-Home suchen und verbinden&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Jetzt kann man aus Google Drive die Datei &amp;quot;FloleXiaomiRemote.settings&amp;quot; runterladen und im Editor der eigenen Wahl öffnen. Ich nehme dafür gerne Notepad++&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In meiner steht z.B.:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[{&amp;quot;c&amp;quot;:&amp;quot;192.168.222.77&amp;quot;,&amp;quot;d&amp;quot;:64647999,&amp;quot;e&amp;quot;:&amp;quot;55387753545937326a33396943557999&amp;quot;,&amp;quot;f&amp;quot;:&amp;quot;Mi Vacuum&amp;quot;,&amp;quot;g&amp;quot;:0}]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zahlenkolonne &amp;quot;55387753545937326a33396943557999&amp;quot; ist der Token. Den behalten wir mal im Auge, bzw. der Zwischenablage.&lt;br /&gt;
&lt;br /&gt;
===Installation des inoffiziellen Moduls===&lt;br /&gt;
Der folgende Teil ist für völlige Noobs. Wenn ihr einen eleganteren Weg kennt, her damit.&lt;br /&gt;
&lt;br /&gt;
Zunächst bitte das Modul aus dem Forum herunterladen.&lt;br /&gt;
[https://forum.fhem.de/index.php/topic,73052.0.htmlm Hier] befindet sich der Thread. Markus M. hat sich die Mühe gemacht, ein Modul zu schreiben. Solange es nicht offiziell eingecheckt ist, muss man es händisch installieren. Das kann man wie folgt machen:&lt;br /&gt;
* das Modul zunächst auf seinem Windows PC speichern&lt;br /&gt;
&lt;br /&gt;
Wie kommt das Modul nun auf den eigenen RasPi?&lt;br /&gt;
&lt;br /&gt;
Ich nutze dafür einen kleinen HTTP Server auf meinem Windows Rechner: [http://miniweb.sourceforge.net/ MiniWeb]&lt;br /&gt;
&lt;br /&gt;
Dieses Tool runterladen und irgendwohin entpacken. Zum starten habe ich eine kleine Batchdatei geschrieben:&lt;br /&gt;
D:\Software\MiniWebServer\miniweb\miniweb.exe -p 80&lt;br /&gt;
Die sorgt nur dafür, dass der Server auf Port 80 läuft.&lt;br /&gt;
&lt;br /&gt;
Im entpackten Verzeichnis ist ein Unterverzeichnis mit dem Namen &amp;quot;htdocs&amp;quot;. Dahin kopieren wir das soeben runtergeladene Modul aus dem Forum-Thread.&lt;br /&gt;
&lt;br /&gt;
Langsam sollte das cpan Tool auf unserer SSH Verbindung durchgelaufen sein.&lt;br /&gt;
&lt;br /&gt;
Nun wechseln wir (auf dem Linux Rechner) in das FHEM Verzeichnis (cd /opt/fhem/FHEM).&lt;br /&gt;
&lt;br /&gt;
wget http://IP-Adresse_EUres_Windows_Rechners/72_XiaomiDevice.pm&lt;br /&gt;
&lt;br /&gt;
bringt die Datei in euer FHEM Verzeichnis.&lt;br /&gt;
&lt;br /&gt;
Jetzt noch die Rechte anpassen:&lt;br /&gt;
&lt;br /&gt;
sudo chown -R fhem:dialout /opt/fhem&lt;br /&gt;
&lt;br /&gt;
Fertig.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Jetzt können wir auf die FHEM Oberfläche wechseln.&lt;br /&gt;
&lt;br /&gt;
reload 72_XiaomiDevice.pm&lt;br /&gt;
&lt;br /&gt;
und unser runtergeladenes Modul steht in FHEM zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
==Einrichten des Moduls==&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
define Mi_Vacuum XiaomiDevice 192.168.222.77 55387753545937326a33396943557999&lt;br /&gt;
&lt;br /&gt;
attr Mi_Vacuum subType VacuumCleaner&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Und schon (=etwa nach 10 Sekunden) sollte euer Roboter in FHEM mit ganz vielen Readings auftauchen.&lt;br /&gt;
&lt;br /&gt;
==Anwendung: Sprachsteuerung mit Alexa (einfach, ein und aus)==&lt;br /&gt;
Wie bindet man das jetzt schnell in Alexa ein?&lt;br /&gt;
&lt;br /&gt;
Wir legen uns in FHEM einen Dummy an. Dieser wird ein Switch (on off). Dazu noch ein DOIF oder ein notify, welches diesen Switch überwacht. Je nach Status des Dummys schalten wir den Roboter.&lt;br /&gt;
&lt;br /&gt;
Ein List meines Dummys:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 Internals: &lt;br /&gt;
   CFGFN &lt;br /&gt;
   NAME       Mi_Vacuum_Staubsauger &lt;br /&gt;
   NR         719473 &lt;br /&gt;
   STATE      on &lt;br /&gt;
   TYPE       dummy &lt;br /&gt;
   Readings: &lt;br /&gt;
     2017-09-18 21:10:12   state           on &lt;br /&gt;
 Attributes: &lt;br /&gt;
   alexaName  Mi_Vacuum_Staubsauger &lt;br /&gt;
   genericDeviceType switch &lt;br /&gt;
   room       alexa &lt;br /&gt;
   setList    on off &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mein DOIF:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
define di_Mi_Vacuum DOIF ([Mi_Vacuum_Staubsauger:&amp;quot;on&amp;quot;]) (set Mi_Vacuum start) DOELSE (set Mi_Vacuum charge)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Das Attribut do always nicht vergessen!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Den Dummy setzen wir in den Raum, der unsere Alexa Geräte beinhaltet. Nun den Alexa FHEM Service neu starten. Anschließend sollte eine Suche nach neuen Geräten in Alexa unseren Dummy finden. Für diesen legen wir in Alexa einen neuen Raum an, z.B. Staubsauger.&lt;br /&gt;
&lt;br /&gt;
Fertig.&lt;br /&gt;
&lt;br /&gt;
Ein &amp;quot;Alexa schaltet den Staubsauger ein&amp;quot; läßt unseren Mi Vacuum loslegen. &amp;quot;Alexa schalte den Staubsauger aus&amp;quot; schickt ihn wieder zurück zu seiner Station.&lt;br /&gt;
&lt;br /&gt;
==Quellen==&lt;br /&gt;
 [https://forum.fhem.de/index.php/topic,73052.0.html Forums-Thread]&lt;br /&gt;
 [http://miniweb.sourceforge.net/ MiniWeb], kleiner WebServer für Windows&lt;br /&gt;
 [https://xiaomi.flole.de/ Flole], alternative App für Android, die das Token nach GoogleDrive exportiert&lt;br /&gt;
 [http://www.roboter-forum.com/forumdisplay.php?130-Xiaomi Roboter-Forum] deutschsprachiges Forum, welches sich mit dem Mi Vacuum beschäftigt (auch vor dem Kauf des Roboters lohnt sich ein Besuch dort)&lt;br /&gt;
 [https://paypal.me/mm0 PayPal]-Link, um Markus M. Dankeschön zu sagen&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Mi_vacuum&amp;diff=22625</id>
		<title>Mi vacuum</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Mi_vacuum&amp;diff=22625"/>
		<updated>2017-09-20T20:45:41Z</updated>

		<summary type="html">&lt;p&gt;Rince: /* Einrichten des Moduls */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
=Mi Vacuum=&lt;br /&gt;
Wie der preiswerte Staubsaugerroboter auch auf FHEM hört...&lt;br /&gt;
&lt;br /&gt;
==Für wen ist die Anleitung gedacht?==&lt;br /&gt;
Ich gehe davon aus, dass ihr ein funktionierendes FHEM auf einem Linux Rechner (Debian) betreibt.&lt;br /&gt;
&lt;br /&gt;
Weiterhin denke ich, dass euer Hauptarbeitsrechner unter Windows läuft.&lt;br /&gt;
&lt;br /&gt;
Als Smartphone OS Android (wer Apple hat, kann gerne die Token-Auslese-Geschichte hier beschreiben).&lt;br /&gt;
&lt;br /&gt;
Um das Teil auch von Alexa aus ein und aus zu schalten, sollte auch die Installation von Alexa in FHEM fertig sein.&lt;br /&gt;
&lt;br /&gt;
==Die Einrichtung des Moduls==&lt;br /&gt;
Das ist insofern spannend, als das Modul nicht offiziell in FHEM eingecheckt ist. Man muss also das Modul runterladen, auf den FHEM Rechner bringen etc...&lt;br /&gt;
&lt;br /&gt;
===Vorarbeiten (Linux)===&lt;br /&gt;
Zunächst fangen wir mal auf unserem FHEM Rechner an. Mit Putty verbinden wir uns per SSH mit dem FHEM Computer.&lt;br /&gt;
&lt;br /&gt;
Folgende Befehle können benötigt werden (Debian):&lt;br /&gt;
* sudo apt-get install libjson-perl&lt;br /&gt;
* sudo apt-get install libdigest-md5-perl&lt;br /&gt;
* sudo apt-get install libcrypt-cbc-perl&lt;br /&gt;
* sudo apt-get install libcrypt-ecb-perl&lt;br /&gt;
* sudo cpan Crypt::Cipher::AES&lt;br /&gt;
Wenn bei dem ein oder anderen Modul die Meldung kommt, dass es schon installiert ist, einfach mit dem nächsten Befehl weiter machen. Das CPAN Teil würde ich am Schluss machen, das braucht ziemlich lang zum installieren.&lt;br /&gt;
&lt;br /&gt;
===Vorarbeiten am Smartphone (Token, Android)===&lt;br /&gt;
Das Problem ist folgendes:&lt;br /&gt;
&lt;br /&gt;
Wenn der Roboter mit dem WLAN verbunden wird, generiert er einen Token. Das ist ein Schlüssel, ohne den er sich nicht steuern lässt. Damit FHEM drauf zugreifen kann, benötigt man diesen Token.&lt;br /&gt;
&lt;br /&gt;
Für Android gibt es eine [https://xiaomi.flole.de/ alternative App] (Flole) um den Roboter zu steuern. Die originale Steuerung der Mi-Home App wird dadurch nicht beeinträchtigt! Also keine Angst, die coolen Karten bleiben erhalten.&lt;br /&gt;
&lt;br /&gt;
*Ich kann nur beschreiben, wie es bei mir funktioniert hat. Wenn es wer einfacher oder anders hinbekommen hat, ergänzt bitte den Wiki Eintrag*&lt;br /&gt;
Zunächst muss die Flole-App installiert werden. Zur Installation muss die Installation von unbekannten Quellen in den Sicherheitseinstellungen von Android erlaubt werden. Bitte nicht vergessen, die Enstellung nach der Installation der App wieder zu korrigieren.&lt;br /&gt;
&lt;br /&gt;
Ich hatte die Mi-Home App schon installiert:&lt;br /&gt;
* Mi-Vacuum aus der Mi-Home App löschen&lt;br /&gt;
* WLAN zurückgesetzt (die beiden Buttons lange gedrückt halten)&lt;br /&gt;
* den Roboter per Reset Taster zurückgesetzt&lt;br /&gt;
=&amp;gt; dennoch hat die App den Roboter nicht gefunden&lt;br /&gt;
&lt;br /&gt;
Lösung:&lt;br /&gt;
* der Mi Vacuum spannt sein eigenes WLAN Netz auf (damit verbinden)&lt;br /&gt;
* Tipp: ist man aus der App mal rausgeflogen (Verbindung gescheitert), muss man die App wirklich unter Android abschießen, bevor sie wieder funktioniert&lt;br /&gt;
* jetzt die Verbindung mit der Flole App herstellen&lt;br /&gt;
* WLAN am Android wieder auf den eigenen AP zurück stellen&lt;br /&gt;
* die IP Adresse des Roboters rausfinden (z.B. FritzBox fragen)&lt;br /&gt;
* in der Flole App die IP Adresse des Mi Vacuum eintragen&lt;br /&gt;
* Die Settings nach Google Drive exportieren (sollte wenige Sekunden dauern. Wenn das Fenster grau bleibt, hat man vermutlich die IP Adresse noch nicht eingetragen ;) )&lt;br /&gt;
* Anschließend kann man den Mi Vacuum wider mit Mi-Home suchen und verbinden&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Jetzt kann man aus Google Drive die Datei &amp;quot;FloleXiaomiRemote.settings&amp;quot; runterladen und im Editor der eigenen Wahl öffnen. Ich nehme dafür gerne Notepad++&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In meiner steht z.B.:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[{&amp;quot;c&amp;quot;:&amp;quot;192.168.222.77&amp;quot;,&amp;quot;d&amp;quot;:64647999,&amp;quot;e&amp;quot;:&amp;quot;55387753545937326a33396943557999&amp;quot;,&amp;quot;f&amp;quot;:&amp;quot;Mi Vacuum&amp;quot;,&amp;quot;g&amp;quot;:0}]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zahlenkolonne &amp;quot;55387753545937326a33396943557999&amp;quot; ist der Token. Den behalten wir mal im Auge, bzw. der Zwischenablage.&lt;br /&gt;
&lt;br /&gt;
===Installation des inoffiziellen Moduls===&lt;br /&gt;
Der folgende Teil ist für völlige Noobs. Wenn ihr einen eleganteren Weg kennt, her damit.&lt;br /&gt;
&lt;br /&gt;
Zunächst bitte das Modul aus dem Forum herunterladen.&lt;br /&gt;
[https://forum.fhem.de/index.php/topic,73052.0.htmlm Hier] befindet sich der Thread. Markus M. hat sich die Mühe gemacht, ein Modul zu schreiben. Solange es nicht offiziell eingecheckt ist, muss man es händisch installieren. Das kann man wie folgt machen:&lt;br /&gt;
* das Modul zunächst auf seinem Windows PC speichern&lt;br /&gt;
&lt;br /&gt;
Wie kommt das Modul nun auf den eigenen RasPi?&lt;br /&gt;
&lt;br /&gt;
Ich nutze dafür einen kleinen HTTP Server auf meinem Windows Rechner: [http://miniweb.sourceforge.net/ MiniWeb]&lt;br /&gt;
&lt;br /&gt;
Dieses Tool runterladen und irgendwohin entpacken. Zum starten habe ich eine kleine Batchdatei geschrieben:&lt;br /&gt;
D:\Software\MiniWebServer\miniweb\miniweb.exe -p 80&lt;br /&gt;
Die sorgt nur dafür, dass der Server auf Port 80 läuft.&lt;br /&gt;
&lt;br /&gt;
Im entpackten Verzeichnis ist ein Unterverzeichnis mit dem Namen &amp;quot;htdocs&amp;quot;. Dahin kopieren wir das soeben runtergeladene Modul aus dem Forum-Thread.&lt;br /&gt;
&lt;br /&gt;
Langsam sollte das cpan Tool auf unserer SSH Verbindung durchgelaufen sein.&lt;br /&gt;
&lt;br /&gt;
Nun wechseln wir (auf dem Linux Rechner) in das FHEM Verzeichnis (cd /opt/fhem/FHEM).&lt;br /&gt;
&lt;br /&gt;
wget http://IP-Adresse_EUres_Windows_Rechners/72_XiaomiDevice.pm&lt;br /&gt;
&lt;br /&gt;
bringt die Datei in euer FHEM Verzeichnis.&lt;br /&gt;
&lt;br /&gt;
Jetzt noch die Rechte anpassen:&lt;br /&gt;
&lt;br /&gt;
sudo chown -R fhem:dialout /opt/fhem&lt;br /&gt;
&lt;br /&gt;
Fertig.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Jetzt können wir auf die FHEM Oberfläche wechseln.&lt;br /&gt;
&lt;br /&gt;
reload 72_XiaomiDevice.pm&lt;br /&gt;
&lt;br /&gt;
und unser runtergeladenes Modul steht in FHEM zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
==Einrichten des Moduls==&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
define Mi_Vacuum XiaomiDevice 192.168.222.77 55387753545937326a33396943557999&lt;br /&gt;
attr Mi_Vacuum subType VacuumCleaner&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Und schon (=etwa nach 10 Sekunden) sollte euer Roboter in FHEM mit ganz vielen Readings auftauchen.&lt;br /&gt;
&lt;br /&gt;
==Anwendung: Sprachsteuerung mit Alexa (einfach, ein und aus)==&lt;br /&gt;
Wie bindet man das jetzt schnell in Alexa ein?&lt;br /&gt;
&lt;br /&gt;
Wir legen uns in FHEM einen Dummy an. Dieser wird ein Switch (on off). Dazu noch ein DOIF oder ein notify, welches diesen Switch überwacht. Je nach Status des Dummys schalten wir den Roboter.&lt;br /&gt;
&lt;br /&gt;
Ein List meines Dummys:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 Internals: &lt;br /&gt;
   CFGFN &lt;br /&gt;
   NAME       Mi_Vacuum_Staubsauger &lt;br /&gt;
   NR         719473 &lt;br /&gt;
   STATE      on &lt;br /&gt;
   TYPE       dummy &lt;br /&gt;
   Readings: &lt;br /&gt;
     2017-09-18 21:10:12   state           on &lt;br /&gt;
 Attributes: &lt;br /&gt;
   alexaName  Mi_Vacuum_Staubsauger &lt;br /&gt;
   genericDeviceType switch &lt;br /&gt;
   room       alexa &lt;br /&gt;
   setList    on off &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mein DOIF:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
define di_Mi_Vacuum DOIF ([Mi_Vacuum_Staubsauger:&amp;quot;on&amp;quot;]) (set Mi_Vacuum start) DOELSE (set Mi_Vacuum charge)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Das Attribut do always nicht vergessen!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Den Dummy setzen wir in den Raum, der unsere Alexa Geräte beinhaltet. Nun den Alexa FHEM Service neu starten. Anschließend sollte eine Suche nach neuen Geräten in Alexa unseren Dummy finden. Für diesen legen wir in Alexa einen neuen Raum an, z.B. Staubsauger.&lt;br /&gt;
&lt;br /&gt;
Fertig.&lt;br /&gt;
&lt;br /&gt;
Ein &amp;quot;Alexa schaltet den Staubsauger ein&amp;quot; läßt unseren Mi Vacuum loslegen. &amp;quot;Alexa schalte den Staubsauger aus&amp;quot; schickt ihn wieder zurück zu seiner Station.&lt;br /&gt;
&lt;br /&gt;
==Quellen==&lt;br /&gt;
 [https://forum.fhem.de/index.php/topic,73052.0.html Forums-Thread]&lt;br /&gt;
 [http://miniweb.sourceforge.net/ MiniWeb], kleiner WebServer für Windows&lt;br /&gt;
 [https://xiaomi.flole.de/ Flole], alternative App für Android, die das Token nach GoogleDrive exportiert&lt;br /&gt;
 [http://www.roboter-forum.com/forumdisplay.php?130-Xiaomi Roboter-Forum] deutschsprachiges Forum, welches sich mit dem Mi Vacuum beschäftigt (auch vor dem Kauf des Roboters lohnt sich ein Besuch dort)&lt;br /&gt;
 [https://paypal.me/mm0 PayPal]-Link, um Markus M. Dankeschön zu sagen&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Mi_vacuum&amp;diff=22624</id>
		<title>Mi vacuum</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Mi_vacuum&amp;diff=22624"/>
		<updated>2017-09-20T20:45:02Z</updated>

		<summary type="html">&lt;p&gt;Rince: /* Vorarbeiten am Smartphone (Token, Android) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
=Mi Vacuum=&lt;br /&gt;
Wie der preiswerte Staubsaugerroboter auch auf FHEM hört...&lt;br /&gt;
&lt;br /&gt;
==Für wen ist die Anleitung gedacht?==&lt;br /&gt;
Ich gehe davon aus, dass ihr ein funktionierendes FHEM auf einem Linux Rechner (Debian) betreibt.&lt;br /&gt;
&lt;br /&gt;
Weiterhin denke ich, dass euer Hauptarbeitsrechner unter Windows läuft.&lt;br /&gt;
&lt;br /&gt;
Als Smartphone OS Android (wer Apple hat, kann gerne die Token-Auslese-Geschichte hier beschreiben).&lt;br /&gt;
&lt;br /&gt;
Um das Teil auch von Alexa aus ein und aus zu schalten, sollte auch die Installation von Alexa in FHEM fertig sein.&lt;br /&gt;
&lt;br /&gt;
==Die Einrichtung des Moduls==&lt;br /&gt;
Das ist insofern spannend, als das Modul nicht offiziell in FHEM eingecheckt ist. Man muss also das Modul runterladen, auf den FHEM Rechner bringen etc...&lt;br /&gt;
&lt;br /&gt;
===Vorarbeiten (Linux)===&lt;br /&gt;
Zunächst fangen wir mal auf unserem FHEM Rechner an. Mit Putty verbinden wir uns per SSH mit dem FHEM Computer.&lt;br /&gt;
&lt;br /&gt;
Folgende Befehle können benötigt werden (Debian):&lt;br /&gt;
* sudo apt-get install libjson-perl&lt;br /&gt;
* sudo apt-get install libdigest-md5-perl&lt;br /&gt;
* sudo apt-get install libcrypt-cbc-perl&lt;br /&gt;
* sudo apt-get install libcrypt-ecb-perl&lt;br /&gt;
* sudo cpan Crypt::Cipher::AES&lt;br /&gt;
Wenn bei dem ein oder anderen Modul die Meldung kommt, dass es schon installiert ist, einfach mit dem nächsten Befehl weiter machen. Das CPAN Teil würde ich am Schluss machen, das braucht ziemlich lang zum installieren.&lt;br /&gt;
&lt;br /&gt;
===Vorarbeiten am Smartphone (Token, Android)===&lt;br /&gt;
Das Problem ist folgendes:&lt;br /&gt;
&lt;br /&gt;
Wenn der Roboter mit dem WLAN verbunden wird, generiert er einen Token. Das ist ein Schlüssel, ohne den er sich nicht steuern lässt. Damit FHEM drauf zugreifen kann, benötigt man diesen Token.&lt;br /&gt;
&lt;br /&gt;
Für Android gibt es eine [https://xiaomi.flole.de/ alternative App] (Flole) um den Roboter zu steuern. Die originale Steuerung der Mi-Home App wird dadurch nicht beeinträchtigt! Also keine Angst, die coolen Karten bleiben erhalten.&lt;br /&gt;
&lt;br /&gt;
*Ich kann nur beschreiben, wie es bei mir funktioniert hat. Wenn es wer einfacher oder anders hinbekommen hat, ergänzt bitte den Wiki Eintrag*&lt;br /&gt;
Zunächst muss die Flole-App installiert werden. Zur Installation muss die Installation von unbekannten Quellen in den Sicherheitseinstellungen von Android erlaubt werden. Bitte nicht vergessen, die Enstellung nach der Installation der App wieder zu korrigieren.&lt;br /&gt;
&lt;br /&gt;
Ich hatte die Mi-Home App schon installiert:&lt;br /&gt;
* Mi-Vacuum aus der Mi-Home App löschen&lt;br /&gt;
* WLAN zurückgesetzt (die beiden Buttons lange gedrückt halten)&lt;br /&gt;
* den Roboter per Reset Taster zurückgesetzt&lt;br /&gt;
=&amp;gt; dennoch hat die App den Roboter nicht gefunden&lt;br /&gt;
&lt;br /&gt;
Lösung:&lt;br /&gt;
* der Mi Vacuum spannt sein eigenes WLAN Netz auf (damit verbinden)&lt;br /&gt;
* Tipp: ist man aus der App mal rausgeflogen (Verbindung gescheitert), muss man die App wirklich unter Android abschießen, bevor sie wieder funktioniert&lt;br /&gt;
* jetzt die Verbindung mit der Flole App herstellen&lt;br /&gt;
* WLAN am Android wieder auf den eigenen AP zurück stellen&lt;br /&gt;
* die IP Adresse des Roboters rausfinden (z.B. FritzBox fragen)&lt;br /&gt;
* in der Flole App die IP Adresse des Mi Vacuum eintragen&lt;br /&gt;
* Die Settings nach Google Drive exportieren (sollte wenige Sekunden dauern. Wenn das Fenster grau bleibt, hat man vermutlich die IP Adresse noch nicht eingetragen ;) )&lt;br /&gt;
* Anschließend kann man den Mi Vacuum wider mit Mi-Home suchen und verbinden&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Jetzt kann man aus Google Drive die Datei &amp;quot;FloleXiaomiRemote.settings&amp;quot; runterladen und im Editor der eigenen Wahl öffnen. Ich nehme dafür gerne Notepad++&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In meiner steht z.B.:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;[{&amp;quot;c&amp;quot;:&amp;quot;192.168.222.77&amp;quot;,&amp;quot;d&amp;quot;:64647999,&amp;quot;e&amp;quot;:&amp;quot;55387753545937326a33396943557999&amp;quot;,&amp;quot;f&amp;quot;:&amp;quot;Mi Vacuum&amp;quot;,&amp;quot;g&amp;quot;:0}]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zahlenkolonne &amp;quot;55387753545937326a33396943557999&amp;quot; ist der Token. Den behalten wir mal im Auge, bzw. der Zwischenablage.&lt;br /&gt;
&lt;br /&gt;
===Installation des inoffiziellen Moduls===&lt;br /&gt;
Der folgende Teil ist für völlige Noobs. Wenn ihr einen eleganteren Weg kennt, her damit.&lt;br /&gt;
&lt;br /&gt;
Zunächst bitte das Modul aus dem Forum herunterladen.&lt;br /&gt;
[https://forum.fhem.de/index.php/topic,73052.0.htmlm Hier] befindet sich der Thread. Markus M. hat sich die Mühe gemacht, ein Modul zu schreiben. Solange es nicht offiziell eingecheckt ist, muss man es händisch installieren. Das kann man wie folgt machen:&lt;br /&gt;
* das Modul zunächst auf seinem Windows PC speichern&lt;br /&gt;
&lt;br /&gt;
Wie kommt das Modul nun auf den eigenen RasPi?&lt;br /&gt;
&lt;br /&gt;
Ich nutze dafür einen kleinen HTTP Server auf meinem Windows Rechner: [http://miniweb.sourceforge.net/ MiniWeb]&lt;br /&gt;
&lt;br /&gt;
Dieses Tool runterladen und irgendwohin entpacken. Zum starten habe ich eine kleine Batchdatei geschrieben:&lt;br /&gt;
D:\Software\MiniWebServer\miniweb\miniweb.exe -p 80&lt;br /&gt;
Die sorgt nur dafür, dass der Server auf Port 80 läuft.&lt;br /&gt;
&lt;br /&gt;
Im entpackten Verzeichnis ist ein Unterverzeichnis mit dem Namen &amp;quot;htdocs&amp;quot;. Dahin kopieren wir das soeben runtergeladene Modul aus dem Forum-Thread.&lt;br /&gt;
&lt;br /&gt;
Langsam sollte das cpan Tool auf unserer SSH Verbindung durchgelaufen sein.&lt;br /&gt;
&lt;br /&gt;
Nun wechseln wir (auf dem Linux Rechner) in das FHEM Verzeichnis (cd /opt/fhem/FHEM).&lt;br /&gt;
&lt;br /&gt;
wget http://IP-Adresse_EUres_Windows_Rechners/72_XiaomiDevice.pm&lt;br /&gt;
&lt;br /&gt;
bringt die Datei in euer FHEM Verzeichnis.&lt;br /&gt;
&lt;br /&gt;
Jetzt noch die Rechte anpassen:&lt;br /&gt;
&lt;br /&gt;
sudo chown -R fhem:dialout /opt/fhem&lt;br /&gt;
&lt;br /&gt;
Fertig.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Jetzt können wir auf die FHEM Oberfläche wechseln.&lt;br /&gt;
&lt;br /&gt;
reload 72_XiaomiDevice.pm&lt;br /&gt;
&lt;br /&gt;
und unser runtergeladenes Modul steht in FHEM zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
==Einrichten des Moduls==&lt;br /&gt;
define Mi_Vacuum XiaomiDevice 192.168.222.77 55387753545937326a33396943557999&lt;br /&gt;
&lt;br /&gt;
attr Mi_Vacuum subType VacuumCleaner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Und schon (=etwa nach 10 Sekunden) sollte euer Roboter in FHEM mit ganz vielen Readings auftauchen.&lt;br /&gt;
&lt;br /&gt;
==Anwendung: Sprachsteuerung mit Alexa (einfach, ein und aus)==&lt;br /&gt;
Wie bindet man das jetzt schnell in Alexa ein?&lt;br /&gt;
&lt;br /&gt;
Wir legen uns in FHEM einen Dummy an. Dieser wird ein Switch (on off). Dazu noch ein DOIF oder ein notify, welches diesen Switch überwacht. Je nach Status des Dummys schalten wir den Roboter.&lt;br /&gt;
&lt;br /&gt;
Ein List meines Dummys:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 Internals: &lt;br /&gt;
   CFGFN &lt;br /&gt;
   NAME       Mi_Vacuum_Staubsauger &lt;br /&gt;
   NR         719473 &lt;br /&gt;
   STATE      on &lt;br /&gt;
   TYPE       dummy &lt;br /&gt;
   Readings: &lt;br /&gt;
     2017-09-18 21:10:12   state           on &lt;br /&gt;
 Attributes: &lt;br /&gt;
   alexaName  Mi_Vacuum_Staubsauger &lt;br /&gt;
   genericDeviceType switch &lt;br /&gt;
   room       alexa &lt;br /&gt;
   setList    on off &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mein DOIF:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
define di_Mi_Vacuum DOIF ([Mi_Vacuum_Staubsauger:&amp;quot;on&amp;quot;]) (set Mi_Vacuum start) DOELSE (set Mi_Vacuum charge)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Das Attribut do always nicht vergessen!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Den Dummy setzen wir in den Raum, der unsere Alexa Geräte beinhaltet. Nun den Alexa FHEM Service neu starten. Anschließend sollte eine Suche nach neuen Geräten in Alexa unseren Dummy finden. Für diesen legen wir in Alexa einen neuen Raum an, z.B. Staubsauger.&lt;br /&gt;
&lt;br /&gt;
Fertig.&lt;br /&gt;
&lt;br /&gt;
Ein &amp;quot;Alexa schaltet den Staubsauger ein&amp;quot; läßt unseren Mi Vacuum loslegen. &amp;quot;Alexa schalte den Staubsauger aus&amp;quot; schickt ihn wieder zurück zu seiner Station.&lt;br /&gt;
&lt;br /&gt;
==Quellen==&lt;br /&gt;
 [https://forum.fhem.de/index.php/topic,73052.0.html Forums-Thread]&lt;br /&gt;
 [http://miniweb.sourceforge.net/ MiniWeb], kleiner WebServer für Windows&lt;br /&gt;
 [https://xiaomi.flole.de/ Flole], alternative App für Android, die das Token nach GoogleDrive exportiert&lt;br /&gt;
 [http://www.roboter-forum.com/forumdisplay.php?130-Xiaomi Roboter-Forum] deutschsprachiges Forum, welches sich mit dem Mi Vacuum beschäftigt (auch vor dem Kauf des Roboters lohnt sich ein Besuch dort)&lt;br /&gt;
 [https://paypal.me/mm0 PayPal]-Link, um Markus M. Dankeschön zu sagen&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Mi_vacuum&amp;diff=22623</id>
		<title>Mi vacuum</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Mi_vacuum&amp;diff=22623"/>
		<updated>2017-09-20T20:43:23Z</updated>

		<summary type="html">&lt;p&gt;Rince: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
=Mi Vacuum=&lt;br /&gt;
Wie der preiswerte Staubsaugerroboter auch auf FHEM hört...&lt;br /&gt;
&lt;br /&gt;
==Für wen ist die Anleitung gedacht?==&lt;br /&gt;
Ich gehe davon aus, dass ihr ein funktionierendes FHEM auf einem Linux Rechner (Debian) betreibt.&lt;br /&gt;
&lt;br /&gt;
Weiterhin denke ich, dass euer Hauptarbeitsrechner unter Windows läuft.&lt;br /&gt;
&lt;br /&gt;
Als Smartphone OS Android (wer Apple hat, kann gerne die Token-Auslese-Geschichte hier beschreiben).&lt;br /&gt;
&lt;br /&gt;
Um das Teil auch von Alexa aus ein und aus zu schalten, sollte auch die Installation von Alexa in FHEM fertig sein.&lt;br /&gt;
&lt;br /&gt;
==Die Einrichtung des Moduls==&lt;br /&gt;
Das ist insofern spannend, als das Modul nicht offiziell in FHEM eingecheckt ist. Man muss also das Modul runterladen, auf den FHEM Rechner bringen etc...&lt;br /&gt;
&lt;br /&gt;
===Vorarbeiten (Linux)===&lt;br /&gt;
Zunächst fangen wir mal auf unserem FHEM Rechner an. Mit Putty verbinden wir uns per SSH mit dem FHEM Computer.&lt;br /&gt;
&lt;br /&gt;
Folgende Befehle können benötigt werden (Debian):&lt;br /&gt;
* sudo apt-get install libjson-perl&lt;br /&gt;
* sudo apt-get install libdigest-md5-perl&lt;br /&gt;
* sudo apt-get install libcrypt-cbc-perl&lt;br /&gt;
* sudo apt-get install libcrypt-ecb-perl&lt;br /&gt;
* sudo cpan Crypt::Cipher::AES&lt;br /&gt;
Wenn bei dem ein oder anderen Modul die Meldung kommt, dass es schon installiert ist, einfach mit dem nächsten Befehl weiter machen. Das CPAN Teil würde ich am Schluss machen, das braucht ziemlich lang zum installieren.&lt;br /&gt;
&lt;br /&gt;
===Vorarbeiten am Smartphone (Token, Android)===&lt;br /&gt;
Das Problem ist folgendes:&lt;br /&gt;
&lt;br /&gt;
Wenn der Roboter mit dem WLAN verbunden wird, generiert er einen Token. Das ist ein Schlüssel, ohne den er sich nicht steuern lässt. Damit FHEM drauf zugreifen kann, benötigt man diesen Token.&lt;br /&gt;
&lt;br /&gt;
Für Android gibt es eine [https://xiaomi.flole.de/ alternative App] (Flole) um den Roboter zu steuern. Die originale Steuerung der Mi-Home App wird dadurch nicht beeinträchtigt! Also keine Angst, die coolen Karten bleiben erhalten.&lt;br /&gt;
&lt;br /&gt;
*Ich kann nur beschreiben, wie es bei mir funktioniert hat. Wenn es wer einfacher oder anders hinbekommen hat, ergänzt bitte den Wiki Eintrag*&lt;br /&gt;
Zunächst muss die Flole-App installiert werden. Zur Installation muss die Installation von unbekannten Quellen in den Sicherheitseinstellungen von Android erlaubt werden. Bitte nicht vergessen, die Enstellung nach der Installation der App wieder zu korrigieren.&lt;br /&gt;
&lt;br /&gt;
Ich hatte die Mi-Home App schon installiert:&lt;br /&gt;
* Mi-Vacuum aus der Mi-Home App löschen&lt;br /&gt;
* WLAN zurückgesetzt (die beiden Buttons lange gedrückt halten)&lt;br /&gt;
* den Roboter per Reset Taster zurückgesetzt&lt;br /&gt;
=&amp;gt; dennoch hat die App den Roboter nicht gefunden&lt;br /&gt;
&lt;br /&gt;
Lösung:&lt;br /&gt;
* der Mi Vacuum spannt sein eigenes WLAN Netz auf (damit verbinden)&lt;br /&gt;
* Tipp: ist man aus der App mal rausgeflogen (Verbindung gescheitert), muss man die App wirklich unter Android abschießen, bevor sie wieder funktioniert&lt;br /&gt;
* jetzt die Verbindung mit der Flole App herstellen&lt;br /&gt;
* WLAN am Android wieder auf den eigenen AP zurück stellen&lt;br /&gt;
* die IP Adresse des Roboters rausfinden (z.B. FritzBox fragen)&lt;br /&gt;
* in der Flole App die IP Adresse des Mi Vacuum eintragen&lt;br /&gt;
* Die Settings nach Google Drive exportieren (sollte wenige Sekunden dauern. Wenn das Fenster grau bleibt, hat man vermutlich die IP Adresse noch nicht eingetragen ;) )&lt;br /&gt;
* Anschließend kann man den Mi Vacuum wider mit Mi-Home suchen und verbinden&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Jetzt kann man aus Google Drive die Datei &amp;quot;FloleXiaomiRemote.settings&amp;quot; runterladen und im Editor der eigenen Wahl öffnen. Ich nehme dafür gerne Notepad++&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In meiner steht z.B.:&lt;br /&gt;
[{&amp;quot;c&amp;quot;:&amp;quot;192.168.222.77&amp;quot;,&amp;quot;d&amp;quot;:64647999,&amp;quot;e&amp;quot;:&amp;quot;55387753545937326a33396943557999&amp;quot;,&amp;quot;f&amp;quot;:&amp;quot;Mi Vacuum&amp;quot;,&amp;quot;g&amp;quot;:0}]&lt;br /&gt;
Die Zahlenkolonne &amp;quot;55387753545937326a33396943557999&amp;quot; ist der Token. Den behalten wir mal im Auge, bzw. der Zwischenablage.&lt;br /&gt;
&lt;br /&gt;
===Installation des inoffiziellen Moduls===&lt;br /&gt;
Der folgende Teil ist für völlige Noobs. Wenn ihr einen eleganteren Weg kennt, her damit.&lt;br /&gt;
&lt;br /&gt;
Zunächst bitte das Modul aus dem Forum herunterladen.&lt;br /&gt;
[https://forum.fhem.de/index.php/topic,73052.0.htmlm Hier] befindet sich der Thread. Markus M. hat sich die Mühe gemacht, ein Modul zu schreiben. Solange es nicht offiziell eingecheckt ist, muss man es händisch installieren. Das kann man wie folgt machen:&lt;br /&gt;
* das Modul zunächst auf seinem Windows PC speichern&lt;br /&gt;
&lt;br /&gt;
Wie kommt das Modul nun auf den eigenen RasPi?&lt;br /&gt;
&lt;br /&gt;
Ich nutze dafür einen kleinen HTTP Server auf meinem Windows Rechner: [http://miniweb.sourceforge.net/ MiniWeb]&lt;br /&gt;
&lt;br /&gt;
Dieses Tool runterladen und irgendwohin entpacken. Zum starten habe ich eine kleine Batchdatei geschrieben:&lt;br /&gt;
D:\Software\MiniWebServer\miniweb\miniweb.exe -p 80&lt;br /&gt;
Die sorgt nur dafür, dass der Server auf Port 80 läuft.&lt;br /&gt;
&lt;br /&gt;
Im entpackten Verzeichnis ist ein Unterverzeichnis mit dem Namen &amp;quot;htdocs&amp;quot;. Dahin kopieren wir das soeben runtergeladene Modul aus dem Forum-Thread.&lt;br /&gt;
&lt;br /&gt;
Langsam sollte das cpan Tool auf unserer SSH Verbindung durchgelaufen sein.&lt;br /&gt;
&lt;br /&gt;
Nun wechseln wir (auf dem Linux Rechner) in das FHEM Verzeichnis (cd /opt/fhem/FHEM).&lt;br /&gt;
&lt;br /&gt;
wget http://IP-Adresse_EUres_Windows_Rechners/72_XiaomiDevice.pm&lt;br /&gt;
&lt;br /&gt;
bringt die Datei in euer FHEM Verzeichnis.&lt;br /&gt;
&lt;br /&gt;
Jetzt noch die Rechte anpassen:&lt;br /&gt;
&lt;br /&gt;
sudo chown -R fhem:dialout /opt/fhem&lt;br /&gt;
&lt;br /&gt;
Fertig.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Jetzt können wir auf die FHEM Oberfläche wechseln.&lt;br /&gt;
&lt;br /&gt;
reload 72_XiaomiDevice.pm&lt;br /&gt;
&lt;br /&gt;
und unser runtergeladenes Modul steht in FHEM zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
==Einrichten des Moduls==&lt;br /&gt;
define Mi_Vacuum XiaomiDevice 192.168.222.77 55387753545937326a33396943557999&lt;br /&gt;
&lt;br /&gt;
attr Mi_Vacuum subType VacuumCleaner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Und schon (=etwa nach 10 Sekunden) sollte euer Roboter in FHEM mit ganz vielen Readings auftauchen.&lt;br /&gt;
&lt;br /&gt;
==Anwendung: Sprachsteuerung mit Alexa (einfach, ein und aus)==&lt;br /&gt;
Wie bindet man das jetzt schnell in Alexa ein?&lt;br /&gt;
&lt;br /&gt;
Wir legen uns in FHEM einen Dummy an. Dieser wird ein Switch (on off). Dazu noch ein DOIF oder ein notify, welches diesen Switch überwacht. Je nach Status des Dummys schalten wir den Roboter.&lt;br /&gt;
&lt;br /&gt;
Ein List meines Dummys:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 Internals: &lt;br /&gt;
   CFGFN &lt;br /&gt;
   NAME       Mi_Vacuum_Staubsauger &lt;br /&gt;
   NR         719473 &lt;br /&gt;
   STATE      on &lt;br /&gt;
   TYPE       dummy &lt;br /&gt;
   Readings: &lt;br /&gt;
     2017-09-18 21:10:12   state           on &lt;br /&gt;
 Attributes: &lt;br /&gt;
   alexaName  Mi_Vacuum_Staubsauger &lt;br /&gt;
   genericDeviceType switch &lt;br /&gt;
   room       alexa &lt;br /&gt;
   setList    on off &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mein DOIF:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
define di_Mi_Vacuum DOIF ([Mi_Vacuum_Staubsauger:&amp;quot;on&amp;quot;]) (set Mi_Vacuum start) DOELSE (set Mi_Vacuum charge)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Das Attribut do always nicht vergessen!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Den Dummy setzen wir in den Raum, der unsere Alexa Geräte beinhaltet. Nun den Alexa FHEM Service neu starten. Anschließend sollte eine Suche nach neuen Geräten in Alexa unseren Dummy finden. Für diesen legen wir in Alexa einen neuen Raum an, z.B. Staubsauger.&lt;br /&gt;
&lt;br /&gt;
Fertig.&lt;br /&gt;
&lt;br /&gt;
Ein &amp;quot;Alexa schaltet den Staubsauger ein&amp;quot; läßt unseren Mi Vacuum loslegen. &amp;quot;Alexa schalte den Staubsauger aus&amp;quot; schickt ihn wieder zurück zu seiner Station.&lt;br /&gt;
&lt;br /&gt;
==Quellen==&lt;br /&gt;
 [https://forum.fhem.de/index.php/topic,73052.0.html Forums-Thread]&lt;br /&gt;
 [http://miniweb.sourceforge.net/ MiniWeb], kleiner WebServer für Windows&lt;br /&gt;
 [https://xiaomi.flole.de/ Flole], alternative App für Android, die das Token nach GoogleDrive exportiert&lt;br /&gt;
 [http://www.roboter-forum.com/forumdisplay.php?130-Xiaomi Roboter-Forum] deutschsprachiges Forum, welches sich mit dem Mi Vacuum beschäftigt (auch vor dem Kauf des Roboters lohnt sich ein Besuch dort)&lt;br /&gt;
 [https://paypal.me/mm0 PayPal]-Link, um Markus M. Dankeschön zu sagen&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Mi_vacuum&amp;diff=22622</id>
		<title>Mi vacuum</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Mi_vacuum&amp;diff=22622"/>
		<updated>2017-09-20T20:36:58Z</updated>

		<summary type="html">&lt;p&gt;Rince: /* Anwendung: Sprachsteuerung mit Alexa (einfach, ein und aus) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
=Mi Vacuum=&lt;br /&gt;
Wie der preiswerte Staubsaugerroboter auch auf FHEM hört...&lt;br /&gt;
&lt;br /&gt;
==Für wen ist die Anleitung gedacht?==&lt;br /&gt;
Ich gehe davon aus, dass ihr ein funktionierendes FHEM auf einem Linux Rechner (Debian) betreibt.&lt;br /&gt;
&lt;br /&gt;
Weiterhin denke ich, dass euer Hauptarbeitsrechner unter Windows läuft.&lt;br /&gt;
&lt;br /&gt;
Als Smartphone OS Android (wer Apple hat, kann gerne die Token-Auslese-Geschichte hier beschreiben).&lt;br /&gt;
&lt;br /&gt;
Um das Teil auch von Alexa aus ein und aus zu schalten, sollte auch die Installation von Alexa in FHEM fertig sein.&lt;br /&gt;
&lt;br /&gt;
==Die Einrichtung des Moduls==&lt;br /&gt;
Das ist insofern spannend, als das Modul nicht offiziell in FHEM eingecheckt ist. Man muss also das Modul runterladen, auf den FHEM Rechner bringen etc...&lt;br /&gt;
&lt;br /&gt;
===Vorarbeiten (Linux)===&lt;br /&gt;
Zunächst fangen wir mal auf unserem FHEM Rechner an. Mit Putty verbinden wir uns per SSH mit dem FHEM Computer.&lt;br /&gt;
&lt;br /&gt;
Folgende Befehle können benötigt werden (Debian):&lt;br /&gt;
* sudo apt-get install libjson-perl&lt;br /&gt;
* sudo apt-get install libdigest-md5-perl&lt;br /&gt;
* sudo apt-get install libcrypt-cbc-perl&lt;br /&gt;
* sudo apt-get install libcrypt-ecb-perl&lt;br /&gt;
* sudo cpan Crypt::Cipher::AES&lt;br /&gt;
Wenn bei dem ein oder anderen Modul die Meldung kommt, dass es schon installiert ist, einfach mit dem nächsten Befehl weiter machen. Das CPAN Teil würde ich am Schluss machen, das braucht ziemlich lang zum installieren.&lt;br /&gt;
&lt;br /&gt;
===Vorarbeiten am Smartphone (Token, Android)===&lt;br /&gt;
Das Problem ist folgendes:&lt;br /&gt;
&lt;br /&gt;
Wenn der Roboter mit dem WLAN verbunden wird, generiert er einen Token. Das ist ein Schlüssel, ohne den er sich nicht steuern lässt. Damit FHEM drauf zugreifen kann, benötigt man diesen Token.&lt;br /&gt;
&lt;br /&gt;
Für Android gibt es eine [https://xiaomi.flole.de/ alternative App] (Flole) um den Roboter zu steuern. Die originale Steuerung der Mi-Home App wird dadurch nicht beeinträchtigt! Also keine Angst, die coolen Karten bleiben erhalten.&lt;br /&gt;
&lt;br /&gt;
*Ich kann nur beschreiben, wie es bei mir funktioniert hat. Wenn es wer einfacher oder anders hinbekommen hat, ergänzt bitte den Wiki Eintrag*&lt;br /&gt;
Zunächst muss die Flole-App installiert werden. Zur Installation muss die Installation von unbekannten Quellen in den Sicherheitseinstellungen von Android erlaubt werden. Bitte nicht vergessen, die Enstellung nach der Installation der App wieder zu korrigieren.&lt;br /&gt;
&lt;br /&gt;
Ich hatte die Mi-Home App schon installiert:&lt;br /&gt;
* Mi-Vacuum aus der Mi-Home App löschen&lt;br /&gt;
* WLAN zurückgesetzt (die beiden Buttons lange gedrückt halten)&lt;br /&gt;
* den Roboter per Reset Taster zurückgesetzt&lt;br /&gt;
=&amp;gt; dennoch hat die App den Roboter nicht gefunden&lt;br /&gt;
&lt;br /&gt;
Lösung:&lt;br /&gt;
* der Mi Vacuum spannt sein eigenes WLAN Netz auf (damit verbinden)&lt;br /&gt;
* Tipp: ist man aus der App mal rausgeflogen (Verbindung gescheitert), muss man die App wirklich unter Android abschießen, bevor sie wieder funktioniert&lt;br /&gt;
* jetzt die Verbindung mit der Flole App herstellen&lt;br /&gt;
* WLAN am Android wieder auf den eigenen AP zurück stellen&lt;br /&gt;
* die IP Adresse des Roboters rausfinden (z.B. FritzBox fragen)&lt;br /&gt;
* in der Flole App die IP Adresse des Mi Vacuum eintragen&lt;br /&gt;
* Die Settings nach Google Drive exportieren (sollte wenige Sekunden dauern. Wenn das Fenster grau bleibt, hat man vermutlich die IP Adresse noch nicht eingetragen ;) )&lt;br /&gt;
* Anschließend kann man den Mi Vacuum wider mit Mi-Home suchen und verbinden&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Jetzt kann man aus Google Drive die Datei &amp;quot;FloleXiaomiRemote.settings&amp;quot; runterladen und im Editor der eigenen Wahl öffnen. Ich nehme dafür gerne Notepad++&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In meiner steht z.B.:&lt;br /&gt;
[{&amp;quot;c&amp;quot;:&amp;quot;192.168.222.77&amp;quot;,&amp;quot;d&amp;quot;:64647999,&amp;quot;e&amp;quot;:&amp;quot;55387753545937326a33396943557999&amp;quot;,&amp;quot;f&amp;quot;:&amp;quot;Mi Vacuum&amp;quot;,&amp;quot;g&amp;quot;:0}]&lt;br /&gt;
Die Zahlenkolonne &amp;quot;55387753545937326a33396943557999&amp;quot; ist der Token. Den behalten wir mal im Auge, bzw. der Zwischenablage.&lt;br /&gt;
&lt;br /&gt;
===Installation des inoffiziellen Moduls===&lt;br /&gt;
Der folgende Teil ist für völlige Noobs. Wenn ihr einen eleganteren Weg kennt, her damit.&lt;br /&gt;
&lt;br /&gt;
Zunächst bitte das Modul aus dem Forum herunterladen.&lt;br /&gt;
[https://forum.fhem.de/index.php/topic,73052.0.htmlm Hier] befindet sich der Thread. Markus M. hat sich die Mühe gemacht, ein Modul zu schreiben. Solange es nicht offiziell eingecheckt ist, muss man es händisch installieren. Das kann man wie folgt machen:&lt;br /&gt;
* das Modul zunächst auf seinem Windows PC speichern&lt;br /&gt;
&lt;br /&gt;
Wie kommt das Modul nun auf den eigenen RasPi?&lt;br /&gt;
&lt;br /&gt;
Ich nutze dafür einen kleinen HTTP Server auf meinem Windows Rechner: [http://miniweb.sourceforge.net/ MiniWeb]&lt;br /&gt;
&lt;br /&gt;
Dieses Tool runterladen und irgendwohin entpacken. Zum starten habe ich eine kleine Batchdatei geschrieben:&lt;br /&gt;
D:\Software\MiniWebServer\miniweb\miniweb.exe -p 80&lt;br /&gt;
Die sorgt nur dafür, dass der Server auf Port 80 läuft.&lt;br /&gt;
&lt;br /&gt;
Im entpackten Verzeichnis ist ein Unterverzeichnis mit dem Namen &amp;quot;htdocs&amp;quot;. Dahin kopieren wir das soeben runtergeladene Modul aus dem Forum-Thread.&lt;br /&gt;
&lt;br /&gt;
Langsam sollte das cpan Tool auf unserer SSH Verbindung durchgelaufen sein.&lt;br /&gt;
&lt;br /&gt;
Nun wechseln wir (auf dem Linux Rechner) in das FHEM Verzeichnis (cd /opt/fhem/FHEM).&lt;br /&gt;
&lt;br /&gt;
wget http://IP-Adresse_EUres_Windows_Rechners/72_XiaomiDevice.pm&lt;br /&gt;
&lt;br /&gt;
bringt die Datei in euer FHEM Verzeichnis.&lt;br /&gt;
&lt;br /&gt;
Jetzt noch die Rechte anpassen:&lt;br /&gt;
&lt;br /&gt;
sudo chown -R fhem:dialout /opt/fhem&lt;br /&gt;
&lt;br /&gt;
Fertig.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Jetzt können wir auf die FHEM Oberfläche wechseln.&lt;br /&gt;
&lt;br /&gt;
reload 72_XiaomiDevice.pm&lt;br /&gt;
&lt;br /&gt;
und unser runtergeladenes Modul steht in FHEM zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
==Einrichten des Moduls==&lt;br /&gt;
define Mi_Vacuum XiaomiDevice 192.168.222.77 55387753545937326a33396943557999&lt;br /&gt;
&lt;br /&gt;
attr Mi_Vacuum subType VacuumCleaner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Und schon (=etwa nach 10 Sekunden) sollte euer Roboter in FHEM mit ganz vielen Readings auftauchen.&lt;br /&gt;
&lt;br /&gt;
==Anwendung: Sprachsteuerung mit Alexa (einfach, ein und aus)==&lt;br /&gt;
Wie bindet man das jetzt schnell in Alexa ein?&lt;br /&gt;
&lt;br /&gt;
Wir legen uns in FHEM einen Dummy an. Dieser wird ein Switch (on off). Dazu noch ein DOIF oder ein notify, welches diesen Switch überwacht. Je nach Status des Dummys schalten wir den Roboter.&lt;br /&gt;
&lt;br /&gt;
Ein List meines Dummys:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 Internals: &lt;br /&gt;
   CFGFN &lt;br /&gt;
   NAME       Mi_Vacuum_Staubsauger &lt;br /&gt;
   NR         719473 &lt;br /&gt;
   STATE      on &lt;br /&gt;
   TYPE       dummy &lt;br /&gt;
   Readings: &lt;br /&gt;
     2017-09-18 21:10:12   state           on &lt;br /&gt;
 Attributes: &lt;br /&gt;
   alexaName  Mi_Vacuum_Staubsauger &lt;br /&gt;
   genericDeviceType switch &lt;br /&gt;
   room       alexa &lt;br /&gt;
   setList    on off &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mein DOIF:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
define di_Mi_Vacuum DOIF ([Mi_Vacuum_Staubsauger:&amp;quot;on&amp;quot;]) (set Mi_Vacuum start) DOELSE (set Mi_Vacuum charge)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Das Attribut do always nicht vergessen!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Den Dummy setzen wir in den Raum, der unsere Alexa Geräte beinhaltet. Nun den Alexa FHEM Service neu starten. Anschließend sollte eine Suche nach neuen Geräten in Alexa unseren Dummy finden. Für diesen legen wir in Alexa einen neuen Raum an, z.B. Staubsauger.&lt;br /&gt;
&lt;br /&gt;
Fertig.&lt;br /&gt;
&lt;br /&gt;
Ein &amp;quot;Alexa schaltet den Staubsauger ein&amp;quot; läßt unseren Mi Vacuum loslegen. &amp;quot;Alexa schalte den Staubsauger aus&amp;quot; schickt ihn wieder zurück zu seiner Station.&lt;br /&gt;
&lt;br /&gt;
==Quellen==&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Mi_vacuum&amp;diff=22620</id>
		<title>Mi vacuum</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Mi_vacuum&amp;diff=22620"/>
		<updated>2017-09-20T20:34:26Z</updated>

		<summary type="html">&lt;p&gt;Rince: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
=Mi Vacuum=&lt;br /&gt;
Wie der preiswerte Staubsaugerroboter auch auf FHEM hört...&lt;br /&gt;
&lt;br /&gt;
==Für wen ist die Anleitung gedacht?==&lt;br /&gt;
Ich gehe davon aus, dass ihr ein funktionierendes FHEM auf einem Linux Rechner (Debian) betreibt.&lt;br /&gt;
&lt;br /&gt;
Weiterhin denke ich, dass euer Hauptarbeitsrechner unter Windows läuft.&lt;br /&gt;
&lt;br /&gt;
Als Smartphone OS Android (wer Apple hat, kann gerne die Token-Auslese-Geschichte hier beschreiben).&lt;br /&gt;
&lt;br /&gt;
Um das Teil auch von Alexa aus ein und aus zu schalten, sollte auch die Installation von Alexa in FHEM fertig sein.&lt;br /&gt;
&lt;br /&gt;
==Die Einrichtung des Moduls==&lt;br /&gt;
Das ist insofern spannend, als das Modul nicht offiziell in FHEM eingecheckt ist. Man muss also das Modul runterladen, auf den FHEM Rechner bringen etc...&lt;br /&gt;
&lt;br /&gt;
===Vorarbeiten (Linux)===&lt;br /&gt;
Zunächst fangen wir mal auf unserem FHEM Rechner an. Mit Putty verbinden wir uns per SSH mit dem FHEM Computer.&lt;br /&gt;
&lt;br /&gt;
Folgende Befehle können benötigt werden (Debian):&lt;br /&gt;
* sudo apt-get install libjson-perl&lt;br /&gt;
* sudo apt-get install libdigest-md5-perl&lt;br /&gt;
* sudo apt-get install libcrypt-cbc-perl&lt;br /&gt;
* sudo apt-get install libcrypt-ecb-perl&lt;br /&gt;
* sudo cpan Crypt::Cipher::AES&lt;br /&gt;
Wenn bei dem ein oder anderen Modul die Meldung kommt, dass es schon installiert ist, einfach mit dem nächsten Befehl weiter machen. Das CPAN Teil würde ich am Schluss machen, das braucht ziemlich lang zum installieren.&lt;br /&gt;
&lt;br /&gt;
===Vorarbeiten am Smartphone (Token, Android)===&lt;br /&gt;
Das Problem ist folgendes:&lt;br /&gt;
&lt;br /&gt;
Wenn der Roboter mit dem WLAN verbunden wird, generiert er einen Token. Das ist ein Schlüssel, ohne den er sich nicht steuern lässt. Damit FHEM drauf zugreifen kann, benötigt man diesen Token.&lt;br /&gt;
&lt;br /&gt;
Für Android gibt es eine [https://xiaomi.flole.de/ alternative App] (Flole) um den Roboter zu steuern. Die originale Steuerung der Mi-Home App wird dadurch nicht beeinträchtigt! Also keine Angst, die coolen Karten bleiben erhalten.&lt;br /&gt;
&lt;br /&gt;
*Ich kann nur beschreiben, wie es bei mir funktioniert hat. Wenn es wer einfacher oder anders hinbekommen hat, ergänzt bitte den Wiki Eintrag*&lt;br /&gt;
Zunächst muss die Flole-App installiert werden. Zur Installation muss die Installation von unbekannten Quellen in den Sicherheitseinstellungen von Android erlaubt werden. Bitte nicht vergessen, die Enstellung nach der Installation der App wieder zu korrigieren.&lt;br /&gt;
&lt;br /&gt;
Ich hatte die Mi-Home App schon installiert:&lt;br /&gt;
* Mi-Vacuum aus der Mi-Home App löschen&lt;br /&gt;
* WLAN zurückgesetzt (die beiden Buttons lange gedrückt halten)&lt;br /&gt;
* den Roboter per Reset Taster zurückgesetzt&lt;br /&gt;
=&amp;gt; dennoch hat die App den Roboter nicht gefunden&lt;br /&gt;
&lt;br /&gt;
Lösung:&lt;br /&gt;
* der Mi Vacuum spannt sein eigenes WLAN Netz auf (damit verbinden)&lt;br /&gt;
* Tipp: ist man aus der App mal rausgeflogen (Verbindung gescheitert), muss man die App wirklich unter Android abschießen, bevor sie wieder funktioniert&lt;br /&gt;
* jetzt die Verbindung mit der Flole App herstellen&lt;br /&gt;
* WLAN am Android wieder auf den eigenen AP zurück stellen&lt;br /&gt;
* die IP Adresse des Roboters rausfinden (z.B. FritzBox fragen)&lt;br /&gt;
* in der Flole App die IP Adresse des Mi Vacuum eintragen&lt;br /&gt;
* Die Settings nach Google Drive exportieren (sollte wenige Sekunden dauern. Wenn das Fenster grau bleibt, hat man vermutlich die IP Adresse noch nicht eingetragen ;) )&lt;br /&gt;
* Anschließend kann man den Mi Vacuum wider mit Mi-Home suchen und verbinden&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Jetzt kann man aus Google Drive die Datei &amp;quot;FloleXiaomiRemote.settings&amp;quot; runterladen und im Editor der eigenen Wahl öffnen. Ich nehme dafür gerne Notepad++&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In meiner steht z.B.:&lt;br /&gt;
[{&amp;quot;c&amp;quot;:&amp;quot;192.168.222.77&amp;quot;,&amp;quot;d&amp;quot;:64647999,&amp;quot;e&amp;quot;:&amp;quot;55387753545937326a33396943557999&amp;quot;,&amp;quot;f&amp;quot;:&amp;quot;Mi Vacuum&amp;quot;,&amp;quot;g&amp;quot;:0}]&lt;br /&gt;
Die Zahlenkolonne &amp;quot;55387753545937326a33396943557999&amp;quot; ist der Token. Den behalten wir mal im Auge, bzw. der Zwischenablage.&lt;br /&gt;
&lt;br /&gt;
===Installation des inoffiziellen Moduls===&lt;br /&gt;
Der folgende Teil ist für völlige Noobs. Wenn ihr einen eleganteren Weg kennt, her damit.&lt;br /&gt;
&lt;br /&gt;
Zunächst bitte das Modul aus dem Forum herunterladen.&lt;br /&gt;
[https://forum.fhem.de/index.php/topic,73052.0.htmlm Hier] befindet sich der Thread. Markus M. hat sich die Mühe gemacht, ein Modul zu schreiben. Solange es nicht offiziell eingecheckt ist, muss man es händisch installieren. Das kann man wie folgt machen:&lt;br /&gt;
* das Modul zunächst auf seinem Windows PC speichern&lt;br /&gt;
&lt;br /&gt;
Wie kommt das Modul nun auf den eigenen RasPi?&lt;br /&gt;
&lt;br /&gt;
Ich nutze dafür einen kleinen HTTP Server auf meinem Windows Rechner: [http://miniweb.sourceforge.net/ MiniWeb]&lt;br /&gt;
&lt;br /&gt;
Dieses Tool runterladen und irgendwohin entpacken. Zum starten habe ich eine kleine Batchdatei geschrieben:&lt;br /&gt;
D:\Software\MiniWebServer\miniweb\miniweb.exe -p 80&lt;br /&gt;
Die sorgt nur dafür, dass der Server auf Port 80 läuft.&lt;br /&gt;
&lt;br /&gt;
Im entpackten Verzeichnis ist ein Unterverzeichnis mit dem Namen &amp;quot;htdocs&amp;quot;. Dahin kopieren wir das soeben runtergeladene Modul aus dem Forum-Thread.&lt;br /&gt;
&lt;br /&gt;
Langsam sollte das cpan Tool auf unserer SSH Verbindung durchgelaufen sein.&lt;br /&gt;
&lt;br /&gt;
Nun wechseln wir (auf dem Linux Rechner) in das FHEM Verzeichnis (cd /opt/fhem/FHEM).&lt;br /&gt;
&lt;br /&gt;
wget http://IP-Adresse_EUres_Windows_Rechners/72_XiaomiDevice.pm&lt;br /&gt;
&lt;br /&gt;
bringt die Datei in euer FHEM Verzeichnis.&lt;br /&gt;
&lt;br /&gt;
Jetzt noch die Rechte anpassen:&lt;br /&gt;
&lt;br /&gt;
sudo chown -R fhem:dialout /opt/fhem&lt;br /&gt;
&lt;br /&gt;
Fertig.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Jetzt können wir auf die FHEM Oberfläche wechseln.&lt;br /&gt;
&lt;br /&gt;
reload 72_XiaomiDevice.pm&lt;br /&gt;
&lt;br /&gt;
und unser runtergeladenes Modul steht in FHEM zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
==Einrichten des Moduls==&lt;br /&gt;
define Mi_Vacuum XiaomiDevice 192.168.222.77 55387753545937326a33396943557999&lt;br /&gt;
&lt;br /&gt;
attr Mi_Vacuum subType VacuumCleaner&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Und schon (=etwa nach 10 Sekunden) sollte euer Roboter in FHEM mit ganz vielen Readings auftauchen.&lt;br /&gt;
&lt;br /&gt;
==Anwendung: Sprachsteuerung mit Alexa (einfach, ein und aus)==&lt;br /&gt;
Wie bindet man das jetzt schnell in Alexa ein?&lt;br /&gt;
&lt;br /&gt;
Wir legen uns in FHEM einen Dummy an. Dieser wird ein Switch (on off). Dazu noch ein DOIF oder ein notify, welches diesen Switch überwacht. Je nach Status des Dummys schalten wir den Roboter.&lt;br /&gt;
&lt;br /&gt;
Ein List meines Dummys:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
Internals: &lt;br /&gt;
   CFGFN &lt;br /&gt;
   NAME       Mi_Vacuum_Staubsauger &lt;br /&gt;
   NR         719473 &lt;br /&gt;
   STATE      on &lt;br /&gt;
   TYPE       dummy &lt;br /&gt;
   Readings: &lt;br /&gt;
     2017-09-18 21:10:12   state           on &lt;br /&gt;
Attributes: &lt;br /&gt;
   alexaName  Mi_Vacuum_Staubsauger &lt;br /&gt;
   genericDeviceType switch &lt;br /&gt;
   room       alexa &lt;br /&gt;
   setList    on off &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Mein DOIF:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
([Mi_Vacuum_Staubsauger:&amp;quot;on&amp;quot;]) (set Mi_Vacuum start) DOELSE (set Mi_Vacuum charge)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Den Dummy setzen wir in den Raum, der unsere Alexa Geräte beinhaltet. Nun den Alexa FHEM Service neu starten. Anschließend sollte eine Suche nach neuen Geräten in Alexa unseren Dummy finden. Für diesen legen wir in Alexa einen neuen Raum an, z.B. Staubsauger.&lt;br /&gt;
&lt;br /&gt;
Fertig.&lt;br /&gt;
&lt;br /&gt;
Ein &amp;quot;Alexa schaltet den Staubsauger ein&amp;quot; läßt unseren Mi Vacuum loslegen. &amp;quot;Alexa schalte den Staubsauger aus&amp;quot; schickt ihn wieder zurück zu seiner Station.&lt;br /&gt;
&lt;br /&gt;
==Quellen==&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Mi_vacuum&amp;diff=22619</id>
		<title>Mi vacuum</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Mi_vacuum&amp;diff=22619"/>
		<updated>2017-09-20T20:14:27Z</updated>

		<summary type="html">&lt;p&gt;Rince: /* Vorarbeiten am Smartphone (Token, Android) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
=Mi Vacuum=&lt;br /&gt;
Wie der preiswerte Staubsaugerroboter auch auf FHEM hört...&lt;br /&gt;
&lt;br /&gt;
==Für wen ist die Anleitung gedacht?==&lt;br /&gt;
Ich gehe davon aus, dass ihr ein funktionierendes FHEM auf einem Linux Rechner (Debian) betreibt.&lt;br /&gt;
&lt;br /&gt;
Weiterhin denke ich, dass euer Hauptarbeitsrechner unter Windows läuft.&lt;br /&gt;
&lt;br /&gt;
Als Smartphone OS Android (wer Apple hat, kann gerne die Token-Auslese-Geschichte hier beschreiben).&lt;br /&gt;
&lt;br /&gt;
Um das Teil auch von Alexa aus ein und aus zu schalten, sollte auch die Installation von Alexa in FHEM fertig sein.&lt;br /&gt;
&lt;br /&gt;
==Die Einrichtung des Moduls==&lt;br /&gt;
Das ist insofern spannend, als das Modul nicht offiziell in FHEM eingecheckt ist. Man muss also das Modul runterladen, auf den FHEM Rechner bringen etc...&lt;br /&gt;
&lt;br /&gt;
===Vorarbeiten (Linux)===&lt;br /&gt;
Zunächst fangen wir mal auf unserem FHEM Rechner an. Mit Putty verbinden wir uns per SSH mit dem FHEM Computer.&lt;br /&gt;
&lt;br /&gt;
Folgende Befehle können benötigt werden (Debian):&lt;br /&gt;
* sudo apt-get install libjson-perl&lt;br /&gt;
* sudo apt-get install libdigest-md5-perl&lt;br /&gt;
* sudo apt-get install libcrypt-cbc-perl&lt;br /&gt;
* sudo apt-get install libcrypt-ecb-perl&lt;br /&gt;
* sudo cpan Crypt::Cipher::AES&lt;br /&gt;
Wenn bei dem ein oder anderen Modul die Meldung kommt, dass es schon installiert ist, einfach mit dem nächsten Befehl weiter machen. Das CPAN Teil würde ich am Schluss machen, das braucht ziemlich lang zum installieren.&lt;br /&gt;
&lt;br /&gt;
===Vorarbeiten am Smartphone (Token, Android)===&lt;br /&gt;
Das Problem ist folgendes:&lt;br /&gt;
&lt;br /&gt;
Wenn der Roboter mit dem WLAN verbunden wird, generiert er einen Token. Das ist ein Schlüssel, ohne den er sich nicht steuern lässt. Damit FHEM drauf zugreifen kann, benötigt man diesen Token.&lt;br /&gt;
&lt;br /&gt;
Für Android gibt es eine [https://xiaomi.flole.de/ alternative App] (Flole) um den Roboter zu steuern. Die originale Steuerung der Mi-Home App wird dadurch nicht beeinträchtigt! Also keine Angst, die coolen Karten bleiben erhalten.&lt;br /&gt;
&lt;br /&gt;
*Ich kann nur beschreiben, wie es bei mir funktioniert hat. Wenn es wer einfacher oder anders hinbekommen hat, ergänzt bitte den Wiki Eintrag*&lt;br /&gt;
Zunächst muss die Flole-App installiert werden. Zur Installation muss die Installation von unbekannten Quellen in den Sicherheitseinstellungen von Android erlaubt werden. Bitte nicht vergessen, die Enstellung nach der Installation der App wieder zu korrigieren.&lt;br /&gt;
&lt;br /&gt;
Ich hatte die Mi-Home App schon installiert:&lt;br /&gt;
* Mi-Vacuum aus der Mi-Home App löschen&lt;br /&gt;
* WLAN zurückgesetzt (die beiden Buttons lange gedrückt halten)&lt;br /&gt;
* den Roboter per Reset Taster zurückgesetzt&lt;br /&gt;
=&amp;gt; dennoch hat die App den Roboter nicht gefunden&lt;br /&gt;
&lt;br /&gt;
Lösung:&lt;br /&gt;
* der Mi Vacuum spannt sein eigenes WLAN Netz auf (damit verbinden)&lt;br /&gt;
* Tipp: ist man aus der App mal rausgeflogen (Verbindung gescheitert), muss man die App wirklich unter Android abschießen, bevor sie wieder funktioniert&lt;br /&gt;
* jetzt die Verbindung mit der Flole App herstellen&lt;br /&gt;
* WLAN am Android wieder auf den eigenen AP zurück stellen&lt;br /&gt;
* die IP Adresse des Roboters rausfinden (z.B. FritzBox fragen)&lt;br /&gt;
* in der Flole App die IP Adresse des Mi Vacuum eintragen&lt;br /&gt;
* Die Settings nach Google Drive exportieren (sollte wenige Sekunden dauern. Wenn das Fenster grau bleibt, hat man vermutlich die IP Adresse noch nicht eingetragen ;) )&lt;br /&gt;
* Anschließend kann man den Mi Vacuum wider mit Mi-Home suchen und verbinden&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Jetzt kann man aus Google Drive die Datei &amp;quot;FloleXiaomiRemote.settings&amp;quot; runterladen und im Editor der eigenen Wahl öffnen. Ich nehme dafür gerne Notepad++&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In meiner steht z.B.:&lt;br /&gt;
[{&amp;quot;c&amp;quot;:&amp;quot;192.168.XXX.77&amp;quot;,&amp;quot;d&amp;quot;:64647999,&amp;quot;e&amp;quot;:&amp;quot;55387753545937326a33396943557999&amp;quot;,&amp;quot;f&amp;quot;:&amp;quot;Mi Vacuum&amp;quot;,&amp;quot;g&amp;quot;:0}]&lt;br /&gt;
Die Zahlenkolonne &amp;quot;55387753545937326a33396943557999&amp;quot; ist der Token. Den behalten wir mal im Auge, bzw. der Zwischenablage.&lt;br /&gt;
&lt;br /&gt;
===Installation des inoffiziellen Moduls===&lt;br /&gt;
Der folgende Teil ist für völlige Noobs. Wenn ihr einen eleganteren Weg kennt, her damit.&lt;br /&gt;
&lt;br /&gt;
Zunächst bitte das Modul aus dem Forum herunterladen.&lt;br /&gt;
[https://forum.fhem.de/index.php/topic,73052.0.htmlm Hier] befindet sich der Thread. Markus M. hat sich die Mühe gemacht, ein Modul zu schreiben. Solange es nicht offiziell eingecheckt ist, muss man es händisch installieren. Das kann man wie folgt machen:&lt;br /&gt;
* das Modul zunächst auf seinem Windows PC speichern&lt;br /&gt;
&lt;br /&gt;
Wie kommt das Modul nun auf den eigenen RasPi?&lt;br /&gt;
&lt;br /&gt;
Ich nutze dafür einen kleinen HTTP Server auf meinem Windows Rechner: [http://miniweb.sourceforge.net/ MiniWeb]&lt;br /&gt;
&lt;br /&gt;
Dieses Tool runterladen und irgendwohin entpacken. Zum starten habe ich eine kleine Batchdatei geschrieben:&lt;br /&gt;
D:\Software\MiniWebServer\miniweb\miniweb.exe -p 80&lt;br /&gt;
Die sorgt nur dafür, dass der Server auf Port 80 läuft.&lt;br /&gt;
&lt;br /&gt;
Im entpackten Verzeichnis ist ein Unterverzeichnis mit dem Namen &amp;quot;htdocs&amp;quot;. Dahin kopieren wir das soeben runtergeladene Modul aus dem Forum-Thread.&lt;br /&gt;
&lt;br /&gt;
Langsam sollte das cpan Tool auf unserer SSH Verbindung durchgelaufen sein.&lt;br /&gt;
&lt;br /&gt;
Nun wechseln wir (auf dem Linux Rechner) in das FHEM Verzeichnis (cd /opt/fhem/FHEM).&lt;br /&gt;
&lt;br /&gt;
wget http://IP-Adresse_EUres_Windows_Rechners/72_XiaomiDevice.pm&lt;br /&gt;
&lt;br /&gt;
bringt die Datei in euer FHEM Verzeichnis.&lt;br /&gt;
&lt;br /&gt;
Jetzt noch die Rechte anpassen:&lt;br /&gt;
&lt;br /&gt;
sudo chown -R fhem:dialout /opt/fhem&lt;br /&gt;
&lt;br /&gt;
Fertig.&lt;br /&gt;
&lt;br /&gt;
Jetzt können wir auf die FHEM Oberfläche wechseln.&lt;br /&gt;
&lt;br /&gt;
reload 72_XiaomiDevice.pm&lt;br /&gt;
&lt;br /&gt;
und unser runtergeladenes Modul steht in FHEM zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
==Anwendung: Sprachsteuerung mit Alexa (einfach, ein und aus)==&lt;br /&gt;
&lt;br /&gt;
==Quellen==&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Mi_vacuum&amp;diff=22618</id>
		<title>Mi vacuum</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Mi_vacuum&amp;diff=22618"/>
		<updated>2017-09-20T20:11:52Z</updated>

		<summary type="html">&lt;p&gt;Rince: /* Die Einrichtung des Moduls */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
=Mi Vacuum=&lt;br /&gt;
Wie der preiswerte Staubsaugerroboter auch auf FHEM hört...&lt;br /&gt;
&lt;br /&gt;
==Für wen ist die Anleitung gedacht?==&lt;br /&gt;
Ich gehe davon aus, dass ihr ein funktionierendes FHEM auf einem Linux Rechner (Debian) betreibt.&lt;br /&gt;
&lt;br /&gt;
Weiterhin denke ich, dass euer Hauptarbeitsrechner unter Windows läuft.&lt;br /&gt;
&lt;br /&gt;
Als Smartphone OS Android (wer Apple hat, kann gerne die Token-Auslese-Geschichte hier beschreiben).&lt;br /&gt;
&lt;br /&gt;
Um das Teil auch von Alexa aus ein und aus zu schalten, sollte auch die Installation von Alexa in FHEM fertig sein.&lt;br /&gt;
&lt;br /&gt;
==Die Einrichtung des Moduls==&lt;br /&gt;
Das ist insofern spannend, als das Modul nicht offiziell in FHEM eingecheckt ist. Man muss also das Modul runterladen, auf den FHEM Rechner bringen etc...&lt;br /&gt;
&lt;br /&gt;
===Vorarbeiten (Linux)===&lt;br /&gt;
Zunächst fangen wir mal auf unserem FHEM Rechner an. Mit Putty verbinden wir uns per SSH mit dem FHEM Computer.&lt;br /&gt;
&lt;br /&gt;
Folgende Befehle können benötigt werden (Debian):&lt;br /&gt;
* sudo apt-get install libjson-perl&lt;br /&gt;
* sudo apt-get install libdigest-md5-perl&lt;br /&gt;
* sudo apt-get install libcrypt-cbc-perl&lt;br /&gt;
* sudo apt-get install libcrypt-ecb-perl&lt;br /&gt;
* sudo cpan Crypt::Cipher::AES&lt;br /&gt;
Wenn bei dem ein oder anderen Modul die Meldung kommt, dass es schon installiert ist, einfach mit dem nächsten Befehl weiter machen. Das CPAN Teil würde ich am Schluss machen, das braucht ziemlich lang zum installieren.&lt;br /&gt;
&lt;br /&gt;
===Vorarbeiten am Smartphone (Token, Android)===&lt;br /&gt;
Das Problem ist folgendes:&lt;br /&gt;
&lt;br /&gt;
Wenn der Roboter mit dem WLAN verbunden wird, generiert er einen Token. Das ist ein Schlüssel, ohne den er sich nicht steuern lässt. Damit FHEM drauf zugreifen kann, benötigt man diesen Token.&lt;br /&gt;
&lt;br /&gt;
Für Android gibt es eine [https://xiaomi.flole.de/ alternative App] (Flole) um den Roboter zu steuern. Die originale Steuerung der Mi-Home App wird dadurch nicht beeinträchtigt! Also keine Angst, die coolen Karten bleiben erhalten.&lt;br /&gt;
&lt;br /&gt;
*Ich kann nur beschreiben, wie es bei mir funktioniert hat. Wenn es wer einfacher oder anders hinbekommen hat, ergänzt bitte den Wiki Eintrag*&lt;br /&gt;
Zunächst muss die Flole-App installiert werden. Zur Installation muss die Installation von unbekannten Quellen in den Sicherheitseinstellungen von Android erlaubt werden. Bitte nicht vergessen, die Enstellung nach der Installation der App wieder zu korrigieren.&lt;br /&gt;
&lt;br /&gt;
Ich hatte die Mi-Home App schon installiert:&lt;br /&gt;
* Mi-Vacuum aus der Mi-Home App löschen&lt;br /&gt;
* WLAN zurückgesetzt (die beiden Buttons lange gedrückt halten)&lt;br /&gt;
* den Roboter per Reset Taster zurückgesetzt&lt;br /&gt;
=&amp;gt; dennoch hat die App den Roboter nicht gefunden&lt;br /&gt;
Lösung:&lt;br /&gt;
* der Mi Vacuum spannt sein eigenes WLAN Netz auf (damit verbinden)&lt;br /&gt;
* Tipp: ist man aus der App mal rausgeflogen (Verbindung gescheitert), muss man die App wirklich unter Android abschießen, bevor sie wieder funktioniert&lt;br /&gt;
* WLAN am Android wieder auf den eigenen AP zurück stellen&lt;br /&gt;
* die IP Adresse des Roboters rausfinden (z.B. FritzBox fragen)&lt;br /&gt;
* in der Flole App die IP Adresse eintragen&lt;br /&gt;
* Die Settings nach Google Drive exportieren (sollte wenige Sekunden dauern. Wenn das Fenster grau bleibt, hat man vermutlich die IP Adresse noch nicht eingetragen ;) )&lt;br /&gt;
* Anschließend kann man den Mi Vacuum wider mit Mi-Home suchen und verbinden.&lt;br /&gt;
&lt;br /&gt;
Jetzt kann man aus Google Drive die Datei &amp;quot;FloleXiaomiRemote.settings&amp;quot; runterladen und im Editor der eigenen Wahl öffnen. Ich nehme dafür gerne Notepad++&lt;br /&gt;
&lt;br /&gt;
In meiner steht z.B.:&lt;br /&gt;
[{&amp;quot;c&amp;quot;:&amp;quot;192.168.XXX.77&amp;quot;,&amp;quot;d&amp;quot;:64647999,&amp;quot;e&amp;quot;:&amp;quot;55387753545937326a33396943557999&amp;quot;,&amp;quot;f&amp;quot;:&amp;quot;Mi Vacuum&amp;quot;,&amp;quot;g&amp;quot;:0}]&lt;br /&gt;
Die Zahlenkolonne &amp;quot;55387753545937326a33396943557999&amp;quot; ist der Token. Den behalten wir mal im Auge, bzw. der Zwischenablage.&lt;br /&gt;
&lt;br /&gt;
===Installation des inoffiziellen Moduls===&lt;br /&gt;
Der folgende Teil ist für völlige Noobs. Wenn ihr einen eleganteren Weg kennt, her damit.&lt;br /&gt;
&lt;br /&gt;
Zunächst bitte das Modul aus dem Forum herunterladen.&lt;br /&gt;
[https://forum.fhem.de/index.php/topic,73052.0.htmlm Hier] befindet sich der Thread. Markus M. hat sich die Mühe gemacht, ein Modul zu schreiben. Solange es nicht offiziell eingecheckt ist, muss man es händisch installieren. Das kann man wie folgt machen:&lt;br /&gt;
* das Modul zunächst auf seinem Windows PC speichern&lt;br /&gt;
&lt;br /&gt;
Wie kommt das Modul nun auf den eigenen RasPi?&lt;br /&gt;
&lt;br /&gt;
Ich nutze dafür einen kleinen HTTP Server auf meinem Windows Rechner: [http://miniweb.sourceforge.net/ MiniWeb]&lt;br /&gt;
&lt;br /&gt;
Dieses Tool runterladen und irgendwohin entpacken. Zum starten habe ich eine kleine Batchdatei geschrieben:&lt;br /&gt;
D:\Software\MiniWebServer\miniweb\miniweb.exe -p 80&lt;br /&gt;
Die sorgt nur dafür, dass der Server auf Port 80 läuft.&lt;br /&gt;
&lt;br /&gt;
Im entpackten Verzeichnis ist ein Unterverzeichnis mit dem Namen &amp;quot;htdocs&amp;quot;. Dahin kopieren wir das soeben runtergeladene Modul aus dem Forum-Thread.&lt;br /&gt;
&lt;br /&gt;
Langsam sollte das cpan Tool auf unserer SSH Verbindung durchgelaufen sein.&lt;br /&gt;
&lt;br /&gt;
Nun wechseln wir (auf dem Linux Rechner) in das FHEM Verzeichnis (cd /opt/fhem/FHEM).&lt;br /&gt;
&lt;br /&gt;
wget http://IP-Adresse_EUres_Windows_Rechners/72_XiaomiDevice.pm&lt;br /&gt;
&lt;br /&gt;
bringt die Datei in euer FHEM Verzeichnis.&lt;br /&gt;
&lt;br /&gt;
Jetzt noch die Rechte anpassen:&lt;br /&gt;
&lt;br /&gt;
sudo chown -R fhem:dialout /opt/fhem&lt;br /&gt;
&lt;br /&gt;
Fertig.&lt;br /&gt;
&lt;br /&gt;
Jetzt können wir auf die FHEM Oberfläche wechseln.&lt;br /&gt;
&lt;br /&gt;
reload 72_XiaomiDevice.pm&lt;br /&gt;
&lt;br /&gt;
und unser runtergeladenes Modul steht in FHEM zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
==Anwendung: Sprachsteuerung mit Alexa (einfach, ein und aus)==&lt;br /&gt;
&lt;br /&gt;
==Quellen==&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Mi_vacuum&amp;diff=22608</id>
		<title>Mi vacuum</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Mi_vacuum&amp;diff=22608"/>
		<updated>2017-09-18T19:45:01Z</updated>

		<summary type="html">&lt;p&gt;Rince: WIP =&amp;gt; noch nicht fertig&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Mi Vacuum=&lt;br /&gt;
Wie der preiswerte Staubsaugerroboter auch auf FHEM hört...&lt;br /&gt;
&lt;br /&gt;
==Für wen ist die Anleitung gedacht?==&lt;br /&gt;
Ich gehe davon aus, dass ihr ein funktionierendes FHEM auf einem Linux Rechner (Debian) betreibt.&lt;br /&gt;
&lt;br /&gt;
Weiterhin denke ich, dass euer Hauptarbeitsrechner unter Windows läuft.&lt;br /&gt;
&lt;br /&gt;
Als Smartphone OS Android (wer Apple hat, kann gerne die Token-Auslese-Geschichte hier beschreiben).&lt;br /&gt;
&lt;br /&gt;
Um das Teil auch von Alexa aus ein und aus zu schalten, sollte auch die Installation von Alexa in FHEM fertig sein.&lt;br /&gt;
&lt;br /&gt;
==Die Einrichtung des Moduls==&lt;br /&gt;
Das ist insofern spannend, als das Modul nicht offiziell in FHEM eingecheckt ist. Man muss also das Modul runterladen, auf den FHEM Rechner bringen etc...&lt;br /&gt;
&lt;br /&gt;
===Vorarbeiten (Linux)===&lt;br /&gt;
Zunächst fangen wir mal auf unserem FHEM Rechner an. Mit Putty verbinden wir uns per SSH mit dem FHEM Computer.&lt;br /&gt;
&lt;br /&gt;
Folgende Befehle können benötigt werden (Debian):&lt;br /&gt;
* sudo apt-get install &lt;br /&gt;
* sudo apt-get install&lt;br /&gt;
* sudo apt-get install&lt;br /&gt;
* sudo cpan&lt;br /&gt;
&lt;br /&gt;
===Vorarbeiten am Smartphone (Token, Android)===&lt;br /&gt;
Das Problem ist folgendes:&lt;br /&gt;
&lt;br /&gt;
Wenn der Roboter mit dem WLAN verbunden wird, generiert er einen Token. Das ist ein Schlüssel, ohne den er sich nicht steuern lässt. Damit FHEM drauf zugreifen kann, benötigt man diesen Token.&lt;br /&gt;
&lt;br /&gt;
Für Android gibt es eine alternative App um den Roboter zu steuern. Die originale Steuerung der Mi Home App wird dadurch nicht beeinträchtigt! Also keine Angst, die coolen Karten bleiben erhalten.&lt;br /&gt;
&lt;br /&gt;
===Installation des inoffiziellen Moduls===&lt;br /&gt;
==Anwendung: Sprachsteuerung mit Alexa (einfach, ein und aus)==&lt;br /&gt;
&lt;br /&gt;
==Quellen==&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung_Teil_3&amp;diff=21113</id>
		<title>MQTT Einführung Teil 3</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung_Teil_3&amp;diff=21113"/>
		<updated>2017-04-01T18:59:56Z</updated>

		<summary type="html">&lt;p&gt;Rince: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= MQTT Einführung Teil 3 =&lt;br /&gt;
Zeit sich die Hände schmutzig zu machen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOCH NICHT GANZ FERTIG&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Übersicht ==&lt;br /&gt;
Im folgenden basteln wir einen einfachen Temperatursensor.&lt;br /&gt;
&lt;br /&gt;
Das ist nicht aufregend. Jedoch ist der Code im Originalzustand sehr gut überschaubar. Man kann daher gut die Änderungen sehen.&lt;br /&gt;
&lt;br /&gt;
== Originales Projekt ==&lt;br /&gt;
[http://fluuux.de/2012/10/arduino-temperatur-und-luftfeuchtigkeit-mit-dem-dht22-prufen/ hier bitte nachlesen]&lt;br /&gt;
&lt;br /&gt;
Mit freundlicher Genehmigung des Autors hier der originale Quellcode:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;arduino&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;quot;DHT.h&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
#define DHTPIN 9     &lt;br /&gt;
#define DHTTYPE DHT22 //DHT11, DHT21, DHT22&lt;br /&gt;
 &lt;br /&gt;
DHT dht(DHTPIN, DHTTYPE);&lt;br /&gt;
 &lt;br /&gt;
void setup() &lt;br /&gt;
{&lt;br /&gt;
  Serial.begin(9600); &lt;br /&gt;
  Serial.println(&amp;quot;DHT22 - Test!&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  dht.begin();&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
void loop() &lt;br /&gt;
{&lt;br /&gt;
  float h = dht.readHumidity();     //Luftfeuchte auslesen&lt;br /&gt;
  float t = dht.readTemperature();  //Temperatur auslesen&lt;br /&gt;
 &lt;br /&gt;
  // Prüfen ob eine gültige Zahl zurückgegeben wird. Wenn NaN (not a number) zurückgegeben wird, dann Fehler ausgeben.&lt;br /&gt;
  if (isnan(t) || isnan(h)) &lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;DHT22 konnte nicht ausgelesen werden&amp;quot;);&lt;br /&gt;
  } &lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    Serial.print(&amp;quot;Luftfeuchte: &amp;quot;); &lt;br /&gt;
    Serial.print(h);&lt;br /&gt;
    Serial.print(&amp;quot; %\t&amp;quot;);&lt;br /&gt;
    Serial.print(&amp;quot;Temperatur: &amp;quot;); &lt;br /&gt;
    Serial.print(t);&lt;br /&gt;
    Serial.println(&amp;quot; C&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Benötigte Hardware ===&lt;br /&gt;
* Arduino&lt;br /&gt;
* DHT-22 Sensor (nicht der Beste, aber seine Verwendung hält den Code einfach)&lt;br /&gt;
* 10 kOhm Widerstand&lt;br /&gt;
* Steckbrett&lt;br /&gt;
* Drähte&lt;br /&gt;
&lt;br /&gt;
Zusätzlich&lt;br /&gt;
* Ethernetshield mit W5100 Chip&lt;br /&gt;
* MQTT Broker (Testweise: 37.187.106.16 =&amp;gt; IP von test.mosquitto.org)&lt;br /&gt;
&lt;br /&gt;
== Kurze Beschreibung was der originale Code tut ==&lt;br /&gt;
* Zeilen 1-6: Library einbinden, PIN festlegen, initialisieren.&lt;br /&gt;
* Zeilen 8-14: Serielle Schnittstelle konfigurieren, netten Text schreiben...&lt;br /&gt;
* Zeilen 18-19: Sensorwerte auslesen&lt;br /&gt;
* Zeilen 21-25: Fehlerbehandlung&lt;br /&gt;
* Zeilen 26-34: Sensorwerte mit Beschreibung an die serielle Schnittstelle senden&lt;br /&gt;
&lt;br /&gt;
=== Bibliotheken die zu installieren sind ===&lt;br /&gt;
Anmerkung:&lt;br /&gt;
&lt;br /&gt;
Die Arduino IDE bietet viele Möglichkeiten Bibliotheken einzubinden. Bevorzugt verwendet man den eingebauten Library-Manager. Wer das nicht will, kann auch die Bibliotheken als ZIP Datei herunterladen, und dann mit &amp;quot;Bibliothek aus ZIP Datei hinzufügen&amp;quot; einbinden.&lt;br /&gt;
&lt;br /&gt;
Im folgenden die Links zu den ZIP Dateien&lt;br /&gt;
Für den originalen Sketch&lt;br /&gt;
* [https://github.com/adafruit/DHT-sensor-library Adafruit DHT Library]&lt;br /&gt;
* [https://github.com/adafruit/Adafruit_Sensor Adafruit Sensor Library]&lt;br /&gt;
In der Adruino IDE gibt es eine Warnung, &#039;&#039;WARNUNG: Unberechtigter Ordner .github in der Bibliothek &#039;DHT sensor library&#039;&#039;&#039;; diese kann ignoriert werden. Da die Meldung aber immer kommt, löschen wir einfach besagten Ordner &amp;quot;.github&amp;quot; im Ordner der DHT Sensor Library.&lt;br /&gt;
&lt;br /&gt;
Für MQTT brauchen wir drei weitere Libraries:&lt;br /&gt;
* [https://github.com/knolleary/pubsubclient PubSubClient Library, MQTT]&lt;br /&gt;
* Ethernet, ist in der Arduino IDE schon mit dabei&lt;br /&gt;
* SPI, für das Netzwerkshield, ist auch schon dabei&lt;br /&gt;
&lt;br /&gt;
== Notwendige Änderungen ==&lt;br /&gt;
&lt;br /&gt;
Im folgenden bauen wir den Sketch um. Zunächst prüfen wir, was am Sketch an sich geändert werden muss, anschließend fügen wir den MQTT Code hinzu. Zuletzt nutzen wir noch einige MQTT Features für weitere Optimierungen.&lt;br /&gt;
&lt;br /&gt;
=== Änderungen am Skript selbst ===&lt;br /&gt;
Die einfachste Möglichkeit ein Skript auf MQTT umzustellen, ist das Ändern der Ausgabe von Serial.print in ein mqtt.publish. Hier ergibt sich im Sketch ein Problem: Pubsubclient kann keine Werte vom Typ &amp;quot;float&amp;quot; als Payload versenden. Daher müssen wir zwei Konvertierungen hinzufügen:&lt;br /&gt;
* dtostrf(h,6, 1, humidity);&lt;br /&gt;
* dtostrf(t,6, 1, temperature);&lt;br /&gt;
machen den Trick: Nehme float h, benutze insgesamt 6 Stellen, 1 Nachkommastelle und schreibe das Ergebnis in humidity.&lt;br /&gt;
&lt;br /&gt;
Weiterhin ist es angenehmer, Variablen etc. am Anfang eines Sketches zu definieren, das machen wir auch noch.&lt;br /&gt;
&lt;br /&gt;
=== Änderungen für MQTT ===&lt;br /&gt;
Am einfachsten ist, wir nehmen uns einen der mitgelieferten MQTT Beispielsketche: mqtt_reconnect_nonblocking. Das müssen wir eigentlich nur an den jeweiligen Stellen in den originalen Sketch kopieren.&lt;br /&gt;
Dabei sind die IP Adressen anzupassen und eine MAC Adresse zu vergeben.&lt;br /&gt;
&lt;br /&gt;
Statt oder zusätzlich zu unserer Ausgabe über die serielle Schnittstelle fügen wir noch einen client.publish ein, so dass die Werte auf dem Broker landen.&lt;br /&gt;
&lt;br /&gt;
Der Vollständigkeit halber, hier der Sketch für das nicht - blockierende MQTT reconnect:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;arduino&amp;quot;&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 Reconnecting MQTT example - non-blocking&lt;br /&gt;
&lt;br /&gt;
 This sketch demonstrates how to keep the client connected&lt;br /&gt;
 using a non-blocking reconnect function. If the client loses&lt;br /&gt;
 its connection, it attempts to reconnect every 5 seconds&lt;br /&gt;
 without blocking the main loop.&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;SPI.h&amp;gt;&lt;br /&gt;
#include &amp;lt;Ethernet.h&amp;gt;&lt;br /&gt;
#include &amp;lt;PubSubClient.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// Update these with values suitable for your hardware/network.&lt;br /&gt;
byte mac[]    = {  0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED };&lt;br /&gt;
IPAddress ip(172, 16, 0, 100);&lt;br /&gt;
IPAddress server(172, 16, 0, 2);&lt;br /&gt;
&lt;br /&gt;
void callback(char* topic, byte* payload, unsigned int length) {&lt;br /&gt;
  // handle message arrived&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
EthernetClient ethClient;&lt;br /&gt;
PubSubClient client(ethClient);&lt;br /&gt;
&lt;br /&gt;
long lastReconnectAttempt = 0;&lt;br /&gt;
&lt;br /&gt;
boolean reconnect() {&lt;br /&gt;
  if (client.connect(&amp;quot;arduinoClient&amp;quot;)) {&lt;br /&gt;
    // Once connected, publish an announcement...&lt;br /&gt;
    client.publish(&amp;quot;outTopic&amp;quot;,&amp;quot;hello world&amp;quot;);&lt;br /&gt;
    // ... and resubscribe&lt;br /&gt;
    client.subscribe(&amp;quot;inTopic&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  return client.connected();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setup()&lt;br /&gt;
{&lt;br /&gt;
  client.setServer(server, 1883);&lt;br /&gt;
  client.setCallback(callback);&lt;br /&gt;
&lt;br /&gt;
  Ethernet.begin(mac, ip);&lt;br /&gt;
  delay(1500);&lt;br /&gt;
  lastReconnectAttempt = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void loop()&lt;br /&gt;
{&lt;br /&gt;
  if (!client.connected()) {&lt;br /&gt;
    long now = millis();&lt;br /&gt;
    if (now - lastReconnectAttempt &amp;gt; 5000) {&lt;br /&gt;
      lastReconnectAttempt = now;&lt;br /&gt;
      // Attempt to reconnect&lt;br /&gt;
      if (reconnect()) {&lt;br /&gt;
        lastReconnectAttempt = 0;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  } else {&lt;br /&gt;
    // Client connected&lt;br /&gt;
&lt;br /&gt;
    client.loop();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Optimierungsmöglichkeiten === &lt;br /&gt;
&lt;br /&gt;
==== Unfreiwilliger Netzwerktest ====&lt;br /&gt;
Jedesmal wenn die Schleife durchgelaufen wird, bekämen wir eine Nachricht mit der Temperatur und eine mit der Luftfeuchtigkeit. Das ist nicht so wirklich schlau. Hier bieten sich 3 Alternativen an:&lt;br /&gt;
* Delay =&amp;gt; dumme Idee, blockiert den Arduino, nicht benutzen&lt;br /&gt;
* eine nicht-blockierende Methode für den Arduino nehmen =&amp;gt; kann man machen&lt;br /&gt;
* Senden nur bei Werteänderung =&amp;gt; vermutlich das Ressourcenschonendste&lt;br /&gt;
&lt;br /&gt;
Ich verwende Variante 3.&lt;br /&gt;
&lt;br /&gt;
Wir benötigen dazu noch zwei weitere Variablen (h_alt und t_alt); jedesmal wenn die Sendeschleife durchlaufen wird, speichern wir h und t in diese Variablen. Zusätzlich benötigt unsere Schleife nach der Fehlerbehandlung noch einen if Zweig, der dafür sorgt, dass nichts getan wird wenn beide Werte sich nicht geändert haben.&lt;br /&gt;
&lt;br /&gt;
Jetzt können wir MQTT anweisen, die letzten Messwerte retained zu senden. Sonst würden wir erst dann Werte bekommen, wenn sich entweder die Temperatur oder die Luftfeuchte verändert haben.&lt;br /&gt;
* client.publish(&amp;quot;zuHause/Arduino_1/Kueche/Kuehlschrank/Luftfeuchte&amp;quot;,humidity);&lt;br /&gt;
wird zu&lt;br /&gt;
* client.publish(&amp;quot;zuHause/Arduino_1/Kueche/Kuehlschrank/Luftfeuchte&amp;quot;,humidity, true);&lt;br /&gt;
* das true dahinter ist das Flag für retained Messages&lt;br /&gt;
&lt;br /&gt;
==== Nachtrag zum Thema Pausen ====&lt;br /&gt;
Mit den Codeänderungen oben haben wir schon mal ein dauerhaftes publishen der gleichen Daten verhindert. Jedoch gibt es natürlich noch einige technische Besonderheiten, die wir ebenfalls berücksichtigen sollten:&lt;br /&gt;
&lt;br /&gt;
Bis jetzt führt unser Sketch bei jedem Durchlauf durch void.loop() eine Messung durch. Das hat zwei Folgen:&lt;br /&gt;
* der Sensor ist im Dauerbetrieb&lt;br /&gt;
* kleine Schwankungen führen natürlich zu einem erneuten publishen.&lt;br /&gt;
Wenn wir den Code, sagen wir, nur alle 2 Minuten ausführen würden, würderd der Sensor weniger belastet. Beim dem Verwendeten spielt es nicht wirklich eine große Rolle, aber es gibt Sensoren die auf einen derart häufigen Zugriff durchaus empfindlich reagieren können.&lt;br /&gt;
&lt;br /&gt;
Gleichzeitig bekommen wir viele kleine Schwankungen  (ich nenne sie mal Messungenauigkeiten) übermittelt, die uns eigentlich nicht interessieren.&lt;br /&gt;
&lt;br /&gt;
Die einfache Variante wäre wieder ein Delay. Dieses würde recht schnell zu einem Fehler führen: Ein Delay blockiert. Für MQTT bedeutet es, dass keine Keep-alive Pakete mehr gesendet werden. Hätten wir eingehende Nachrichten, dann würden wir diese auch verpassen.&lt;br /&gt;
Wir merken uns: nutze niemals Delays.&lt;br /&gt;
&lt;br /&gt;
Die oben schon angesprochene Lösung, eine nicht blockierende Methode verwenden, ist sehr gut geeignet.&lt;br /&gt;
&lt;br /&gt;
Wie geht das?&lt;br /&gt;
&lt;br /&gt;
Zunächst zählt der Arduino seine Laufzeit in Millisekunden. Wir schreiben unseren Temperaturausleseteil in eine kleine Schleife.&lt;br /&gt;
* zwei weitere Variablen&lt;br /&gt;
** unsigned long previousMillis = 0; //Zählervariable, zählt Millisekunden seit dem letzten Funktionsaufruf nach oben&lt;br /&gt;
** const long interval = 120000; //120000 Millisekunden aka 120 Sekunden, das Interval wie oft der Sensor überhaupt benutzt wird&lt;br /&gt;
* Drei Zeilen Programmcode mehr:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;arduino&amp;quot;&amp;gt;&lt;br /&gt;
unsigned long currentMillis = millis();&lt;br /&gt;
&lt;br /&gt;
  if (currentMillis - previousMillis &amp;gt;= interval) {&lt;br /&gt;
    previousMillis = currentMillis;&lt;br /&gt;
    &lt;br /&gt;
    h = dht.readHumidity();     //Luftfeuchte auslesen&lt;br /&gt;
    t = dht.readTemperature();  //Temperatur auslesen&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Last Will &amp;amp; Testament ====&lt;br /&gt;
Retten wir auch die Statusmeldungen des Skripts nach MQTT. Dazu ergänzen wir den client.connect Aufruf:&lt;br /&gt;
* if (client.connect(&amp;quot;Arduino_1&amp;quot;)) {&lt;br /&gt;
&lt;br /&gt;
um folgendes:&lt;br /&gt;
* if (client.connect(&amp;quot;Arduino_1&amp;quot;, &amp;quot;zuHause/Arduino_1&amp;quot;, 0, true, &amp;quot;offline&amp;quot;)) { &lt;br /&gt;
** Arduino_1 nennt sich unser Sensor&lt;br /&gt;
** &amp;quot;zuHause/Arduino_1&amp;quot; ist das Topic für dessen Statusmeldungen&lt;br /&gt;
** 0 ist die QoS&lt;br /&gt;
** true bedeutet, Nachricht retained senden&lt;br /&gt;
** &amp;quot;offline&amp;quot; ist das, was auf dem Topic geschrieben werden soll, wenn die Verbindung abbricht&lt;br /&gt;
** Anmerkung:&lt;br /&gt;
** Unsauberes disconnect wird verursacht durch:&lt;br /&gt;
** Abbruch der Netzwerkverbindung&lt;br /&gt;
** Protokollfehler (z.B. ungültige Topics, fehlerhafte Payload)&lt;br /&gt;
&lt;br /&gt;
Warum machen wir das?&lt;br /&gt;
* beim Start des Sensors steht nun &amp;quot;online&amp;quot; im Status&lt;br /&gt;
* bei einem Sensorfehler werden wir auf den Sensorfehler aufmerksam gemacht &amp;quot;Sensorfehler&amp;quot;&lt;br /&gt;
* bricht die Netzwerkverbindung ab, steht automatisch &amp;quot;offline&amp;quot; in dem Topic&lt;br /&gt;
* bei einer erfolgreichen Messung mit Datenübertragung steht wieder &amp;quot;online&amp;quot; im Topic&lt;br /&gt;
Auf diese Art und Weise haben wir eine aussagekräftige Zustandsmeldung in unserem Topic. Diese können wir bequem mit FHEM überwachen, um bei einem Fehler weitere Maßnahmen einzuleiten. Ein Vergleich des Alters der Sensorwerte wird überflüssig.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== MQTT an sich ===&lt;br /&gt;
Wer keinen eigenen Broker hat und (für diesen einen Test) keinen aufsetzen will, kann testweise auch einen öffentlichen Broker benutzen: test.mosquitto.org stellt so einen bereit. Bitte beachten, dass dieser Broker wirklich öffentlich ist. Mit &#039;&#039;ping test.mosquitto.org&#039;&#039; bekommt man die IP Adresse, die man, ich möchte es nochmal betonen, zu Testzwecken, in seinen Sketch schreiben kann.&lt;br /&gt;
&lt;br /&gt;
Wir benötigen für MQTT entsprechende Topics.&lt;br /&gt;
* &amp;quot;zuHause/Arduino_1/Kueche/Kuehlschrank/Luftfeuchte&amp;quot;&lt;br /&gt;
* &amp;quot;zuHause/Arduino_1/Kueche/Kuehlschrank/Temperatur&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Daus ergibt sich letztlich folgender Sketch ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;arduino&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;DHT.h&amp;gt;&lt;br /&gt;
#include &amp;lt;SPI.h&amp;gt;&lt;br /&gt;
#include &amp;lt;Ethernet.h&amp;gt;&lt;br /&gt;
#include &amp;lt;PubSubClient.h&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
#define DHTPIN 9     &lt;br /&gt;
#define DHTTYPE DHT22 //DHT11, DHT21, DHT22&lt;br /&gt;
 &lt;br /&gt;
DHT dht(DHTPIN, DHTTYPE);&lt;br /&gt;
&lt;br /&gt;
byte mac[]    = {  0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; //eine MAC Adresse wählen, darf im eigenen Netz nur 1x vorkommen&lt;br /&gt;
IPAddress ip(192, 168, 5, 220); //eine gültige IP Adresse für das eigene Netz&lt;br /&gt;
IPAddress server(192, 168, 5, 2); //die Adresse wo der eigene MQTT Broker drauf läuft&lt;br /&gt;
&lt;br /&gt;
void callback(char* topic, byte* payload, unsigned int length) {&lt;br /&gt;
  // handle message arrived&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
EthernetClient ethClient;&lt;br /&gt;
PubSubClient client(ethClient);&lt;br /&gt;
&lt;br /&gt;
long lastReconnectAttempt = 0;&lt;br /&gt;
&lt;br /&gt;
boolean reconnect() {&lt;br /&gt;
  if (client.connect(&amp;quot;Arduino_1&amp;quot;, &amp;quot;zuHause/Arduino_1&amp;quot;, 0, true, &amp;quot;offline&amp;quot;)) {&lt;br /&gt;
    // Once connected, publish an announcement...&lt;br /&gt;
    client.publish(&amp;quot;zuHause/Arduino_1&amp;quot;,&amp;quot;online&amp;quot;, true);&lt;br /&gt;
    // ... and resubscribe&lt;br /&gt;
    client.subscribe(&amp;quot;inTopic&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  return client.connected();&lt;br /&gt;
}&lt;br /&gt;
static char humidity[15]; //Speicherbereich reservieren um die Fechtigkeit zu speichern&lt;br /&gt;
static char temperature[15];&lt;br /&gt;
float h = 0.0;&lt;br /&gt;
float h_alt = 0.0;&lt;br /&gt;
float t = 0.0;&lt;br /&gt;
float t_alt = 0.0;&lt;br /&gt;
unsigned long previousMillis = 0; //Zählervariable, zählt Millisekunden seit dem letzten Funktionsaufruf nach oben&lt;br /&gt;
const long interval = 120000; //120000 Millisekunden aka 120 Sekunden, das Interval wie oft der Sensor überhaupt benutzt wird&lt;br /&gt;
&lt;br /&gt;
void setup() &lt;br /&gt;
{&lt;br /&gt;
  client.setServer(server, 1883);&lt;br /&gt;
  client.setCallback(callback);&lt;br /&gt;
&lt;br /&gt;
  Ethernet.begin(mac, ip);&lt;br /&gt;
  delay(1500);&lt;br /&gt;
  lastReconnectAttempt = 0;&lt;br /&gt;
  &lt;br /&gt;
  Serial.begin(9600); &lt;br /&gt;
  Serial.println(&amp;quot;DHT22 - Test!&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  dht.begin();&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
void loop() &lt;br /&gt;
{&lt;br /&gt;
  if (!client.connected()) {&lt;br /&gt;
    long now = millis();&lt;br /&gt;
    if (now - lastReconnectAttempt &amp;gt; 5000) {&lt;br /&gt;
      lastReconnectAttempt = now;&lt;br /&gt;
      // Attempt to reconnect&lt;br /&gt;
      if (reconnect()) {&lt;br /&gt;
        lastReconnectAttempt = 0;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  } else {&lt;br /&gt;
    // Client connected&lt;br /&gt;
&lt;br /&gt;
    client.loop();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
unsigned long currentMillis = millis();&lt;br /&gt;
&lt;br /&gt;
  if (currentMillis - previousMillis &amp;gt;= interval) {&lt;br /&gt;
    previousMillis = currentMillis;&lt;br /&gt;
    &lt;br /&gt;
    h = dht.readHumidity();     //Luftfeuchte auslesen&lt;br /&gt;
    t = dht.readTemperature();  //Temperatur auslesen&lt;br /&gt;
  }&lt;br /&gt;
    &lt;br /&gt;
  // Prüfen ob eine gültige Zahl zurückgegeben wird. Wenn NaN (not a number) zurückgegeben wird, dann Fehler ausgeben.&lt;br /&gt;
  if (isnan(t) || isnan(h)) &lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;DHT22 konnte nicht ausgelesen werden&amp;quot;);&lt;br /&gt;
    client.publish(&amp;quot;zuHause/Arduino_1&amp;quot;,&amp;quot;Sensorfehler&amp;quot;,true); //true sendet die Nachricht retained, d.h. die Nachricht bleibt solange auf dem Broker, bis etwas neues kommt&lt;br /&gt;
  }&lt;br /&gt;
  else if (h == h_alt &amp;amp;&amp;amp; t == t_alt)&lt;br /&gt;
  {&lt;br /&gt;
    //nix machen&lt;br /&gt;
  }&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    client.publish(&amp;quot;zuHause/Arduino_1&amp;quot;,&amp;quot;online&amp;quot;, true);&lt;br /&gt;
    dtostrf(h,6, 1, humidity);&lt;br /&gt;
    dtostrf(t,6, 1, temperature);&lt;br /&gt;
    client.publish(&amp;quot;zuHause/Arduino_1/Kueche/Kuehlschrank/Luftfeuchte&amp;quot;,humidity, true);&lt;br /&gt;
    client.publish(&amp;quot;zuHause/Arduino_1/Kueche/Kuehlschrank/Temperatur&amp;quot;,temperature, true);&lt;br /&gt;
    h_alt = h; //den alten Messwert aufheben&lt;br /&gt;
    t_alt = t; //um nur bei Veränderung zu reagieren&lt;br /&gt;
    Serial.print(&amp;quot;Luftfeuchte: &amp;quot;); &lt;br /&gt;
    Serial.print(h);&lt;br /&gt;
    Serial.print(&amp;quot; %\t&amp;quot;);&lt;br /&gt;
    Serial.print(&amp;quot;Temperatur: &amp;quot;); &lt;br /&gt;
    Serial.print(t);&lt;br /&gt;
    Serial.println(&amp;quot; C&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Zusammenfassung ==&lt;br /&gt;
Um aus einem &amp;quot;normalen&amp;quot; Sketch einen MQTT Sketch zu machen muss man also:&lt;br /&gt;
* Netzwerk konfigurieren&lt;br /&gt;
* MQTT einrichten&lt;br /&gt;
Im wesentlichen kann man einfach den MQTT Beispielsketch &amp;quot;mqtt reconnect nonblocking&amp;quot; in seinen Sketch einbauen.&lt;br /&gt;
&lt;br /&gt;
Geringe Änderungen im vorhandenen Code sind nötig, um diversen Typen von Variablen als MQTT Payload verwenden zu können&lt;br /&gt;
&lt;br /&gt;
Als Bonus bekommen wir &amp;quot;vernünftige&amp;quot; Statuswerte für unseren Sensor, die sich einfach in FHEM abfangen und auswerten lassen. Als weiteren Bonus betrachte ich, dass die Netzwerklast sinkt. Zum Vergleich möchte ich hier die Jeelink Sensoren anführen, aber auch viele 433 MHz Sensoren, die einfach im &amp;quot;wenige Sekunden Takt&amp;quot; ihre Werte in der Gegend rumfunken. Von da her kann durch den Einsatz von MQTT-Techniken die Funkbelastung der Umgebung reduziert werden. Einerseits trägt man also weniger zur &amp;quot;Sensorischen Luftverschmutzung&amp;quot; bei, andererseits entlastet man auch sein FHEM vor der Aufgabe, unnötige Werte erst mal zu verwerfen.&lt;br /&gt;
&lt;br /&gt;
== Danke ==&lt;br /&gt;
Hier möchte ich mal Danke sagen. An Beta-User, der seit Teil 1 das Geschreibsel vorab durchliest und immer wertvolle Tipps und Änderungsvorschläge parat hat.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
[http://fluuux.de/2012/10/arduino-temperatur-und-luftfeuchtigkeit-mit-dem-dht22-prufen/ Originales Projekt]&lt;br /&gt;
&lt;br /&gt;
[https://wiki.fhem.de/wiki/MQTT_Einf%C3%BChrung_Teil_1 Teil 1 der MQTT Einführung]&lt;br /&gt;
&lt;br /&gt;
[https://wiki.fhem.de/wiki/MQTT_Einf%C3%BChrung_Teil_2 Teil 2 der MQTT Einführung]&lt;br /&gt;
&lt;br /&gt;
[https://forum.fhem.de/index.php/topic,69954.0.html Diskussionsthread im Forum]&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung_Teil_3&amp;diff=21112</id>
		<title>MQTT Einführung Teil 3</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung_Teil_3&amp;diff=21112"/>
		<updated>2017-04-01T18:59:28Z</updated>

		<summary type="html">&lt;p&gt;Rince: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= MQTT Einführung Teil 3 =&lt;br /&gt;
Zeit sich die Hände schmutzig zu machen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOCH NICHT GANZ FERTIG&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Übersicht ==&lt;br /&gt;
Im folgenden basteln wir einen einfachen Temperatursensor.&lt;br /&gt;
&lt;br /&gt;
Das ist nicht aufregend. Jedoch ist der Code im Originalzustand sehr gut überschaubar. Man kann daher gut die Änderungen sehen.&lt;br /&gt;
&lt;br /&gt;
== Originales Projekt ==&lt;br /&gt;
[http://fluuux.de/2012/10/arduino-temperatur-und-luftfeuchtigkeit-mit-dem-dht22-prufen/ hier bitte nachlesen]&lt;br /&gt;
&lt;br /&gt;
Mit freundlicher Genehmigung des Autors hier der originale Quellcode:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;arduino&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;quot;DHT.h&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
#define DHTPIN 9     &lt;br /&gt;
#define DHTTYPE DHT22 //DHT11, DHT21, DHT22&lt;br /&gt;
 &lt;br /&gt;
DHT dht(DHTPIN, DHTTYPE);&lt;br /&gt;
 &lt;br /&gt;
void setup() &lt;br /&gt;
{&lt;br /&gt;
  Serial.begin(9600); &lt;br /&gt;
  Serial.println(&amp;quot;DHT22 - Test!&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  dht.begin();&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
void loop() &lt;br /&gt;
{&lt;br /&gt;
  float h = dht.readHumidity();     //Luftfeuchte auslesen&lt;br /&gt;
  float t = dht.readTemperature();  //Temperatur auslesen&lt;br /&gt;
 &lt;br /&gt;
  // Prüfen ob eine gültige Zahl zurückgegeben wird. Wenn NaN (not a number) zurückgegeben wird, dann Fehler ausgeben.&lt;br /&gt;
  if (isnan(t) || isnan(h)) &lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;DHT22 konnte nicht ausgelesen werden&amp;quot;);&lt;br /&gt;
  } &lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    Serial.print(&amp;quot;Luftfeuchte: &amp;quot;); &lt;br /&gt;
    Serial.print(h);&lt;br /&gt;
    Serial.print(&amp;quot; %\t&amp;quot;);&lt;br /&gt;
    Serial.print(&amp;quot;Temperatur: &amp;quot;); &lt;br /&gt;
    Serial.print(t);&lt;br /&gt;
    Serial.println(&amp;quot; C&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Benötigte Hardware ===&lt;br /&gt;
* Arduino&lt;br /&gt;
* DHT-22 Sensor (nicht der Beste, aber seine Verwendung hält den Code einfach)&lt;br /&gt;
* 10 kOhm Widerstand&lt;br /&gt;
* Steckbrett&lt;br /&gt;
* Drähte&lt;br /&gt;
&lt;br /&gt;
Zusätzlich&lt;br /&gt;
* Ethernetshield mit W5100 Chip&lt;br /&gt;
* MQTT Broker (Testweise: 37.187.106.16 =&amp;gt; IP von test.mosquitto.org)&lt;br /&gt;
&lt;br /&gt;
== Kurze Beschreibung was der originale Code tut ==&lt;br /&gt;
* Zeilen 1-6: Library einbinden, PIN festlegen, initialisieren.&lt;br /&gt;
* Zeilen 8-14: Serielle Schnittstelle konfigurieren, netten Text schreiben...&lt;br /&gt;
* Zeilen 18-19: Sensorwerte auslesen&lt;br /&gt;
* Zeilen 21-25: Fehlerbehandlung&lt;br /&gt;
* Zeilen 26-34: Sensorwerte mit Beschreibung an die serielle Schnittstelle senden&lt;br /&gt;
&lt;br /&gt;
=== Bibliotheken die zu installieren sind ===&lt;br /&gt;
Anmerkung:&lt;br /&gt;
&lt;br /&gt;
Die Arduino IDE bietet viele Möglichkeiten Bibliotheken einzubinden. Bevorzugt verwendet man den eingebauten Library-Manager. Wer das nicht will, kann auch die Bibliotheken als ZIP Datei herunterladen, und dann mit &amp;quot;Bibliothek aus ZIP Datei hinzufügen&amp;quot; einbinden.&lt;br /&gt;
&lt;br /&gt;
Im folgenden die Links zu den ZIP Dateien&lt;br /&gt;
Für den originalen Sketch&lt;br /&gt;
* [https://github.com/adafruit/DHT-sensor-library Adafruit DHT Library]&lt;br /&gt;
* [https://github.com/adafruit/Adafruit_Sensor Adafruit Sensor Library]&lt;br /&gt;
In der Adruino IDE gibt es eine Warnung, &#039;&#039;WARNUNG: Unberechtigter Ordner .github in der Bibliothek &#039;DHT sensor library&#039;&#039;&#039;; diese kann ignoriert werden. Da die Meldung aber immer kommt, löschen wir einfach besagten Ordner &amp;quot;.github&amp;quot; im Ordner der DHT Sensor Library.&lt;br /&gt;
&lt;br /&gt;
Für MQTT brauchen wir drei weitere Libraries:&lt;br /&gt;
* [https://github.com/knolleary/pubsubclient PubSubClient Library, MQTT]&lt;br /&gt;
* Ethernet, ist in der Arduino IDE schon mit dabei&lt;br /&gt;
* SPI, für das Netzwerkshield, ist auch schon dabei&lt;br /&gt;
&lt;br /&gt;
== Notwendige Änderungen ==&lt;br /&gt;
&lt;br /&gt;
Im folgenden bauen wir den Sketch um. Zunächst prüfen wir, was am Sketch an sich geändert werden muss, anschließend fügen wir den MQTT Code hinzu. Zuletzt nutzen wir noch einige MQTT Features für weitere Optimierungen.&lt;br /&gt;
&lt;br /&gt;
=== Änderungen am Skript selbst ===&lt;br /&gt;
Die einfachste Möglichkeit ein Skript auf MQTT umzustellen, ist das Ändern der Ausgabe von Serial.print in ein mqtt.publish. Hier ergibt sich im Sketch ein Problem: Pubsubclient kann keine Werte vom Typ &amp;quot;float&amp;quot; als Payload versenden. Daher müssen wir zwei Konvertierungen hinzufügen:&lt;br /&gt;
* dtostrf(h,6, 1, humidity);&lt;br /&gt;
* dtostrf(t,6, 1, temperature);&lt;br /&gt;
machen den Trick: Nehme float h, benutze insgesamt 6 Stellen, 1 Nachkommastelle und schreibe das Ergebnis in humidity.&lt;br /&gt;
&lt;br /&gt;
Weiterhin ist es angenehmer, Variablen etc. am Anfang eines Sketches zu definieren, das machen wir auch noch.&lt;br /&gt;
&lt;br /&gt;
=== Änderungen für MQTT ===&lt;br /&gt;
Am einfachsten ist, wir nehmen uns einen der mitgelieferten MQTT Beispielsketche: mqtt_reconnect_nonblocking. Das müssen wir eigentlich nur an den jeweiligen Stellen in den originalen Sketch kopieren.&lt;br /&gt;
Dabei sind die IP Adressen anzupassen und eine MAC Adresse zu vergeben.&lt;br /&gt;
&lt;br /&gt;
Statt oder zusätzlich zu unserer Ausgabe über die serielle Schnittstelle fügen wir noch einen client.publish ein, so dass die Werte auf dem Broker landen.&lt;br /&gt;
&lt;br /&gt;
Der Vollständigkeit halber, hier der Sketch für das nicht - blockierende MQTT reconnect:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;arduino&amp;quot;&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 Reconnecting MQTT example - non-blocking&lt;br /&gt;
&lt;br /&gt;
 This sketch demonstrates how to keep the client connected&lt;br /&gt;
 using a non-blocking reconnect function. If the client loses&lt;br /&gt;
 its connection, it attempts to reconnect every 5 seconds&lt;br /&gt;
 without blocking the main loop.&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;SPI.h&amp;gt;&lt;br /&gt;
#include &amp;lt;Ethernet.h&amp;gt;&lt;br /&gt;
#include &amp;lt;PubSubClient.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// Update these with values suitable for your hardware/network.&lt;br /&gt;
byte mac[]    = {  0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED };&lt;br /&gt;
IPAddress ip(172, 16, 0, 100);&lt;br /&gt;
IPAddress server(172, 16, 0, 2);&lt;br /&gt;
&lt;br /&gt;
void callback(char* topic, byte* payload, unsigned int length) {&lt;br /&gt;
  // handle message arrived&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
EthernetClient ethClient;&lt;br /&gt;
PubSubClient client(ethClient);&lt;br /&gt;
&lt;br /&gt;
long lastReconnectAttempt = 0;&lt;br /&gt;
&lt;br /&gt;
boolean reconnect() {&lt;br /&gt;
  if (client.connect(&amp;quot;arduinoClient&amp;quot;)) {&lt;br /&gt;
    // Once connected, publish an announcement...&lt;br /&gt;
    client.publish(&amp;quot;outTopic&amp;quot;,&amp;quot;hello world&amp;quot;);&lt;br /&gt;
    // ... and resubscribe&lt;br /&gt;
    client.subscribe(&amp;quot;inTopic&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  return client.connected();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setup()&lt;br /&gt;
{&lt;br /&gt;
  client.setServer(server, 1883);&lt;br /&gt;
  client.setCallback(callback);&lt;br /&gt;
&lt;br /&gt;
  Ethernet.begin(mac, ip);&lt;br /&gt;
  delay(1500);&lt;br /&gt;
  lastReconnectAttempt = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void loop()&lt;br /&gt;
{&lt;br /&gt;
  if (!client.connected()) {&lt;br /&gt;
    long now = millis();&lt;br /&gt;
    if (now - lastReconnectAttempt &amp;gt; 5000) {&lt;br /&gt;
      lastReconnectAttempt = now;&lt;br /&gt;
      // Attempt to reconnect&lt;br /&gt;
      if (reconnect()) {&lt;br /&gt;
        lastReconnectAttempt = 0;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  } else {&lt;br /&gt;
    // Client connected&lt;br /&gt;
&lt;br /&gt;
    client.loop();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Optimierungsmöglichkeiten === &lt;br /&gt;
&lt;br /&gt;
==== Unfreiwilliger Netzwerktest ====&lt;br /&gt;
Jedesmal wenn die Schleife durchgelaufen wird, bekämen wir eine Nachricht mit der Temperatur und eine mit der Luftfeuchtigkeit. Das ist nicht so wirklich schlau. Hier bieten sich 3 Alternativen an:&lt;br /&gt;
* Delay =&amp;gt; dumme Idee, blockiert den Arduino, nicht benutzen&lt;br /&gt;
* eine nicht-blockierende Methode für den Arduino nehmen =&amp;gt; kann man machen&lt;br /&gt;
* Senden nur bei Werteänderung =&amp;gt; vermutlich das Ressourcenschonendste&lt;br /&gt;
&lt;br /&gt;
Ich verwende Variante 3.&lt;br /&gt;
&lt;br /&gt;
Wir benötigen dazu noch zwei weitere Variablen (h_alt und t_alt); jedesmal wenn die Sendeschleife durchlaufen wird, speichern wir h und t in diese Variablen. Zusätzlich benötigt unsere Schleife nach der Fehlerbehandlung noch einen if Zweig, der dafür sorgt, dass nichts getan wird wenn beide Werte sich nicht geändert haben.&lt;br /&gt;
&lt;br /&gt;
Jetzt können wir MQTT anweisen, die letzten Messwerte retained zu senden. Sonst würden wir erst dann Werte bekommen, wenn sich entweder die Temperatur oder die Luftfeuchte verändert haben.&lt;br /&gt;
* client.publish(&amp;quot;zuHause/Arduino_1/Kueche/Kuehlschrank/Luftfeuchte&amp;quot;,humidity);&lt;br /&gt;
wird zu&lt;br /&gt;
* client.publish(&amp;quot;zuHause/Arduino_1/Kueche/Kuehlschrank/Luftfeuchte&amp;quot;,humidity, true);&lt;br /&gt;
* das true dahinter ist das Flag für retained Messages&lt;br /&gt;
&lt;br /&gt;
==== Nachtrag zum Thema Pausen ====&lt;br /&gt;
Mit den Codeänderungen oben haben wir schon mal ein dauerhaftes publishen der gleichen Daten verhindert. Jedoch gibt es natürlich noch einige technische Besonderheiten, die wir ebenfalls berücksichtigen sollten:&lt;br /&gt;
&lt;br /&gt;
Bis jetzt führt unser Sketch bei jedem Durchlauf durch void.loop() eine Messung durch. Das hat zwei Folgen:&lt;br /&gt;
* der Sensor ist im Dauerbetrieb&lt;br /&gt;
* kleine Schwankungen führen natürlich zu einem erneuten publishen.&lt;br /&gt;
Wenn wir den Code, sagen wir, nur alle 2 Minuten ausführen würden, würderd der Sensor weniger belastet. Beim dem Verwendeten spielt es nicht wirklich eine große Rolle, aber es gibt Sensoren die auf einen derart häufigen Zugriff durchaus empfindlich reagieren können.&lt;br /&gt;
&lt;br /&gt;
Gleichzeitig bekommen wir viele kleine Schwankungen  (ich nenne sie mal Messungenauigkeiten) übermittelt, die uns eigentlich nicht interessieren.&lt;br /&gt;
&lt;br /&gt;
Die einfache Variante wäre wieder ein Delay. Dieses würde recht schnell zu einem Fehler führen: Ein Delay blockiert. Für MQTT bedeutet es, dass keine Keep-alive Pakete mehr gesendet werden. Hätten wir eingehende Nachrichten, dann würden wir diese auch verpassen.&lt;br /&gt;
Wir merken uns: nutze niemals Delays.&lt;br /&gt;
&lt;br /&gt;
Die oben schon angesprochene Lösung, eine nicht blockierende Methode verwenden, ist sehr gut geeignet.&lt;br /&gt;
&lt;br /&gt;
Wie geht das?&lt;br /&gt;
&lt;br /&gt;
Zunächst zählt der Arduino seine Laufzeit in Millisekunden. Wir schreiben unseren Temperaturausleseteil in eine kleine Schleife.&lt;br /&gt;
* zwei weitere Variablen&lt;br /&gt;
** unsigned long previousMillis = 0; //Zählervariable, zählt Millisekunden seit dem letzten Funktionsaufruf nach oben&lt;br /&gt;
** const long interval = 120000; //120000 Millisekunden aka 120 Sekunden, das Interval wie oft der Sensor überhaupt benutzt wird&lt;br /&gt;
* Drei Zeilen Programmcode mehr:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;arduino&amp;quot;&amp;gt;&lt;br /&gt;
unsigned long currentMillis = millis();&lt;br /&gt;
&lt;br /&gt;
  if (currentMillis - previousMillis &amp;gt;= interval) {&lt;br /&gt;
    previousMillis = currentMillis;&lt;br /&gt;
    &lt;br /&gt;
    h = dht.readHumidity();     //Luftfeuchte auslesen&lt;br /&gt;
    t = dht.readTemperature();  //Temperatur auslesen&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Last Will &amp;amp; Testament ====&lt;br /&gt;
Retten wir auch die Statusmeldungen des Skripts nach MQTT. Dazu ergänzen wir den client.connect Aufruf:&lt;br /&gt;
* if (client.connect(&amp;quot;Arduino_1&amp;quot;)) {&lt;br /&gt;
&lt;br /&gt;
um folgendes:&lt;br /&gt;
* if (client.connect(&amp;quot;Arduino_1&amp;quot;, &amp;quot;zuHause/Arduino_1&amp;quot;, 0, true, &amp;quot;offline&amp;quot;)) { &lt;br /&gt;
** Arduino_1 nennt sich unser Sensor&lt;br /&gt;
** &amp;quot;zuHause/Arduino_1&amp;quot; ist das Topic für dessen Statusmeldungen&lt;br /&gt;
** 0 ist die QoS&lt;br /&gt;
** true bedeutet, Nachricht retained senden&lt;br /&gt;
** &amp;quot;offline&amp;quot; ist das, was auf dem Topic geschrieben werden soll, wenn die Verbindung abbricht&lt;br /&gt;
** Anmerkung:&lt;br /&gt;
** Unsauberes disconnect wird verursacht durch:&lt;br /&gt;
** Abbruch der Netzwerkverbindung&lt;br /&gt;
** Protokollfehler (z.B. ungültige Topics, fehlerhafte Payload)&lt;br /&gt;
&lt;br /&gt;
Warum machen wir das?&lt;br /&gt;
* beim Start des Sensors steht nun &amp;quot;online&amp;quot; im Status&lt;br /&gt;
* bei einem Sensorfehler werden wir auf den Sensorfehler aufmerksam gemacht &amp;quot;Sensorfehler&amp;quot;&lt;br /&gt;
* bricht die Netzwerkverbindung ab, steht automatisch &amp;quot;offline&amp;quot; in dem Topic&lt;br /&gt;
* bei einer erfolgreichen Messung mit Datenübertragung steht wieder &amp;quot;online&amp;quot; im Topic&lt;br /&gt;
Auf diese Art und Weise haben wir eine aussagekräftige Zustandsmeldung in unserem Topic. Diese können wir bequem mit FHEM überwachen, um bei einem Fehler weitere Maßnahmen einzuleiten. Ein Vergleich des Alters der Sensorwerte wird überflüssig.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== MQTT an sich ===&lt;br /&gt;
Wer keinen eigenen Broker hat und (für diesen einen Test) keinen aufsetzen will, kann testweise auch einen öffentlichen Broker benutzen: test.mosquitto.org stellt so einen bereit. Bitte beachten, dass dieser Broker wirklich öffentlich ist. Mit &#039;&#039;ping test.mosquitto.org&#039;&#039; bekommt man die IP Adresse, die man, ich möchte es nochmal betonen, zu Testzwecken, in seinen Sketch schreiben kann.&lt;br /&gt;
&lt;br /&gt;
Wir benötigen für MQTT entsprechende Topics.&lt;br /&gt;
* &amp;quot;zuHause/Arduino_1/Kueche/Kuehlschrank/Luftfeuchte&amp;quot;&lt;br /&gt;
* &amp;quot;zuHause/Arduino_1/Kueche/Kuehlschrank/Temperatur&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Daus ergibt sich letztlich folgender Sketch &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;arduino&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;DHT.h&amp;gt;&lt;br /&gt;
#include &amp;lt;SPI.h&amp;gt;&lt;br /&gt;
#include &amp;lt;Ethernet.h&amp;gt;&lt;br /&gt;
#include &amp;lt;PubSubClient.h&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
#define DHTPIN 9     &lt;br /&gt;
#define DHTTYPE DHT22 //DHT11, DHT21, DHT22&lt;br /&gt;
 &lt;br /&gt;
DHT dht(DHTPIN, DHTTYPE);&lt;br /&gt;
&lt;br /&gt;
byte mac[]    = {  0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; //eine MAC Adresse wählen, darf im eigenen Netz nur 1x vorkommen&lt;br /&gt;
IPAddress ip(192, 168, 5, 220); //eine gültige IP Adresse für das eigene Netz&lt;br /&gt;
IPAddress server(192, 168, 5, 2); //die Adresse wo der eigene MQTT Broker drauf läuft&lt;br /&gt;
&lt;br /&gt;
void callback(char* topic, byte* payload, unsigned int length) {&lt;br /&gt;
  // handle message arrived&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
EthernetClient ethClient;&lt;br /&gt;
PubSubClient client(ethClient);&lt;br /&gt;
&lt;br /&gt;
long lastReconnectAttempt = 0;&lt;br /&gt;
&lt;br /&gt;
boolean reconnect() {&lt;br /&gt;
  if (client.connect(&amp;quot;Arduino_1&amp;quot;, &amp;quot;zuHause/Arduino_1&amp;quot;, 0, true, &amp;quot;offline&amp;quot;)) {&lt;br /&gt;
    // Once connected, publish an announcement...&lt;br /&gt;
    client.publish(&amp;quot;zuHause/Arduino_1&amp;quot;,&amp;quot;online&amp;quot;, true);&lt;br /&gt;
    // ... and resubscribe&lt;br /&gt;
    client.subscribe(&amp;quot;inTopic&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  return client.connected();&lt;br /&gt;
}&lt;br /&gt;
static char humidity[15]; //Speicherbereich reservieren um die Fechtigkeit zu speichern&lt;br /&gt;
static char temperature[15];&lt;br /&gt;
float h = 0.0;&lt;br /&gt;
float h_alt = 0.0;&lt;br /&gt;
float t = 0.0;&lt;br /&gt;
float t_alt = 0.0;&lt;br /&gt;
unsigned long previousMillis = 0; //Zählervariable, zählt Millisekunden seit dem letzten Funktionsaufruf nach oben&lt;br /&gt;
const long interval = 120000; //120000 Millisekunden aka 120 Sekunden, das Interval wie oft der Sensor überhaupt benutzt wird&lt;br /&gt;
&lt;br /&gt;
void setup() &lt;br /&gt;
{&lt;br /&gt;
  client.setServer(server, 1883);&lt;br /&gt;
  client.setCallback(callback);&lt;br /&gt;
&lt;br /&gt;
  Ethernet.begin(mac, ip);&lt;br /&gt;
  delay(1500);&lt;br /&gt;
  lastReconnectAttempt = 0;&lt;br /&gt;
  &lt;br /&gt;
  Serial.begin(9600); &lt;br /&gt;
  Serial.println(&amp;quot;DHT22 - Test!&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  dht.begin();&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
void loop() &lt;br /&gt;
{&lt;br /&gt;
  if (!client.connected()) {&lt;br /&gt;
    long now = millis();&lt;br /&gt;
    if (now - lastReconnectAttempt &amp;gt; 5000) {&lt;br /&gt;
      lastReconnectAttempt = now;&lt;br /&gt;
      // Attempt to reconnect&lt;br /&gt;
      if (reconnect()) {&lt;br /&gt;
        lastReconnectAttempt = 0;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  } else {&lt;br /&gt;
    // Client connected&lt;br /&gt;
&lt;br /&gt;
    client.loop();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
unsigned long currentMillis = millis();&lt;br /&gt;
&lt;br /&gt;
  if (currentMillis - previousMillis &amp;gt;= interval) {&lt;br /&gt;
    previousMillis = currentMillis;&lt;br /&gt;
    &lt;br /&gt;
    h = dht.readHumidity();     //Luftfeuchte auslesen&lt;br /&gt;
    t = dht.readTemperature();  //Temperatur auslesen&lt;br /&gt;
  }&lt;br /&gt;
    &lt;br /&gt;
  // Prüfen ob eine gültige Zahl zurückgegeben wird. Wenn NaN (not a number) zurückgegeben wird, dann Fehler ausgeben.&lt;br /&gt;
  if (isnan(t) || isnan(h)) &lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;DHT22 konnte nicht ausgelesen werden&amp;quot;);&lt;br /&gt;
    client.publish(&amp;quot;zuHause/Arduino_1&amp;quot;,&amp;quot;Sensorfehler&amp;quot;,true); //true sendet die Nachricht retained, d.h. die Nachricht bleibt solange auf dem Broker, bis etwas neues kommt&lt;br /&gt;
  }&lt;br /&gt;
  else if (h == h_alt &amp;amp;&amp;amp; t == t_alt)&lt;br /&gt;
  {&lt;br /&gt;
    //nix machen&lt;br /&gt;
  }&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    client.publish(&amp;quot;zuHause/Arduino_1&amp;quot;,&amp;quot;online&amp;quot;, true);&lt;br /&gt;
    dtostrf(h,6, 1, humidity);&lt;br /&gt;
    dtostrf(t,6, 1, temperature);&lt;br /&gt;
    client.publish(&amp;quot;zuHause/Arduino_1/Kueche/Kuehlschrank/Luftfeuchte&amp;quot;,humidity, true);&lt;br /&gt;
    client.publish(&amp;quot;zuHause/Arduino_1/Kueche/Kuehlschrank/Temperatur&amp;quot;,temperature, true);&lt;br /&gt;
    h_alt = h; //den alten Messwert aufheben&lt;br /&gt;
    t_alt = t; //um nur bei Veränderung zu reagieren&lt;br /&gt;
    Serial.print(&amp;quot;Luftfeuchte: &amp;quot;); &lt;br /&gt;
    Serial.print(h);&lt;br /&gt;
    Serial.print(&amp;quot; %\t&amp;quot;);&lt;br /&gt;
    Serial.print(&amp;quot;Temperatur: &amp;quot;); &lt;br /&gt;
    Serial.print(t);&lt;br /&gt;
    Serial.println(&amp;quot; C&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Zusammenfassung ==&lt;br /&gt;
Um aus einem &amp;quot;normalen&amp;quot; Sketch einen MQTT Sketch zu machen muss man also:&lt;br /&gt;
* Netzwerk konfigurieren&lt;br /&gt;
* MQTT einrichten&lt;br /&gt;
Im wesentlichen kann man einfach den MQTT Beispielsketch &amp;quot;mqtt reconnect nonblocking&amp;quot; in seinen Sketch einbauen.&lt;br /&gt;
&lt;br /&gt;
Geringe Änderungen im vorhandenen Code sind nötig, um diversen Typen von Variablen als MQTT Payload verwenden zu können&lt;br /&gt;
&lt;br /&gt;
Als Bonus bekommen wir &amp;quot;vernünftige&amp;quot; Statuswerte für unseren Sensor, die sich einfach in FHEM abfangen und auswerten lassen. Als weiteren Bonus betrachte ich, dass die Netzwerklast sinkt. Zum Vergleich möchte ich hier die Jeelink Sensoren anführen, aber auch viele 433 MHz Sensoren, die einfach im &amp;quot;wenige Sekunden Takt&amp;quot; ihre Werte in der Gegend rumfunken. Von da her kann durch den Einsatz von MQTT-Techniken die Funkbelastung der Umgebung reduziert werden. Einerseits trägt man also weniger zur &amp;quot;Sensorischen Luftverschmutzung&amp;quot; bei, andererseits entlastet man auch sein FHEM vor der Aufgabe, unnötige Werte erst mal zu verwerfen.&lt;br /&gt;
&lt;br /&gt;
== Danke ==&lt;br /&gt;
Hier möchte ich mal Danke sagen. An Beta-User, der seit Teil 1 das Geschreibsel vorab durchliest und immer wertvolle Tipps und Änderungsvorschläge parat hat.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
[http://fluuux.de/2012/10/arduino-temperatur-und-luftfeuchtigkeit-mit-dem-dht22-prufen/ Originales Projekt]&lt;br /&gt;
&lt;br /&gt;
[https://wiki.fhem.de/wiki/MQTT_Einf%C3%BChrung_Teil_1 Teil 1 der MQTT Einführung]&lt;br /&gt;
&lt;br /&gt;
[https://wiki.fhem.de/wiki/MQTT_Einf%C3%BChrung_Teil_2 Teil 2 der MQTT Einführung]&lt;br /&gt;
&lt;br /&gt;
[https://forum.fhem.de/index.php/topic,69954.0.html Diskussionsthread im Forum]&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung_Teil_3&amp;diff=21111</id>
		<title>MQTT Einführung Teil 3</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung_Teil_3&amp;diff=21111"/>
		<updated>2017-04-01T18:58:06Z</updated>

		<summary type="html">&lt;p&gt;Rince: /* Nachtrag zum Thema Pausen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= MQTT Einführung Teil 3 =&lt;br /&gt;
Zeit sich die Hände schmutzig zu machen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOCH NICHT GANZ FERTIG&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Übersicht ==&lt;br /&gt;
Im folgenden basteln wir einen einfachen Temperatursensor.&lt;br /&gt;
&lt;br /&gt;
Das ist nicht aufregend. Jedoch ist der Code im Originalzustand sehr gut überschaubar. Man kann daher gut die Änderungen sehen.&lt;br /&gt;
&lt;br /&gt;
== Originales Projekt ==&lt;br /&gt;
[http://fluuux.de/2012/10/arduino-temperatur-und-luftfeuchtigkeit-mit-dem-dht22-prufen/ hier bitte nachlesen]&lt;br /&gt;
&lt;br /&gt;
Mit freundlicher Genehmigung des Autors hier der originale Quellcode:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;arduino&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;quot;DHT.h&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
#define DHTPIN 9     &lt;br /&gt;
#define DHTTYPE DHT22 //DHT11, DHT21, DHT22&lt;br /&gt;
 &lt;br /&gt;
DHT dht(DHTPIN, DHTTYPE);&lt;br /&gt;
 &lt;br /&gt;
void setup() &lt;br /&gt;
{&lt;br /&gt;
  Serial.begin(9600); &lt;br /&gt;
  Serial.println(&amp;quot;DHT22 - Test!&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  dht.begin();&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
void loop() &lt;br /&gt;
{&lt;br /&gt;
  float h = dht.readHumidity();     //Luftfeuchte auslesen&lt;br /&gt;
  float t = dht.readTemperature();  //Temperatur auslesen&lt;br /&gt;
 &lt;br /&gt;
  // Prüfen ob eine gültige Zahl zurückgegeben wird. Wenn NaN (not a number) zurückgegeben wird, dann Fehler ausgeben.&lt;br /&gt;
  if (isnan(t) || isnan(h)) &lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;DHT22 konnte nicht ausgelesen werden&amp;quot;);&lt;br /&gt;
  } &lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    Serial.print(&amp;quot;Luftfeuchte: &amp;quot;); &lt;br /&gt;
    Serial.print(h);&lt;br /&gt;
    Serial.print(&amp;quot; %\t&amp;quot;);&lt;br /&gt;
    Serial.print(&amp;quot;Temperatur: &amp;quot;); &lt;br /&gt;
    Serial.print(t);&lt;br /&gt;
    Serial.println(&amp;quot; C&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Benötigte Hardware ===&lt;br /&gt;
* Arduino&lt;br /&gt;
* DHT-22 Sensor (nicht der Beste, aber seine Verwendung hält den Code einfach)&lt;br /&gt;
* 10 kOhm Widerstand&lt;br /&gt;
* Steckbrett&lt;br /&gt;
* Drähte&lt;br /&gt;
&lt;br /&gt;
Zusätzlich&lt;br /&gt;
* Ethernetshield mit W5100 Chip&lt;br /&gt;
* MQTT Broker (Testweise: 37.187.106.16 =&amp;gt; IP von test.mosquitto.org)&lt;br /&gt;
&lt;br /&gt;
== Kurze Beschreibung was der originale Code tut ==&lt;br /&gt;
* Zeilen 1-6: Library einbinden, PIN festlegen, initialisieren.&lt;br /&gt;
* Zeilen 8-14: Serielle Schnittstelle konfigurieren, netten Text schreiben...&lt;br /&gt;
* Zeilen 18-19: Sensorwerte auslesen&lt;br /&gt;
* Zeilen 21-25: Fehlerbehandlung&lt;br /&gt;
* Zeilen 26-34: Sensorwerte mit Beschreibung an die serielle Schnittstelle senden&lt;br /&gt;
&lt;br /&gt;
=== Bibliotheken die zu installieren sind ===&lt;br /&gt;
Anmerkung:&lt;br /&gt;
&lt;br /&gt;
Die Arduino IDE bietet viele Möglichkeiten Bibliotheken einzubinden. Bevorzugt verwendet man den eingebauten Library-Manager. Wer das nicht will, kann auch die Bibliotheken als ZIP Datei herunterladen, und dann mit &amp;quot;Bibliothek aus ZIP Datei hinzufügen&amp;quot; einbinden.&lt;br /&gt;
&lt;br /&gt;
Im folgenden die Links zu den ZIP Dateien&lt;br /&gt;
Für den originalen Sketch&lt;br /&gt;
* [https://github.com/adafruit/DHT-sensor-library Adafruit DHT Library]&lt;br /&gt;
* [https://github.com/adafruit/Adafruit_Sensor Adafruit Sensor Library]&lt;br /&gt;
In der Adruino IDE gibt es eine Warnung, &#039;&#039;WARNUNG: Unberechtigter Ordner .github in der Bibliothek &#039;DHT sensor library&#039;&#039;&#039;; diese kann ignoriert werden. Da die Meldung aber immer kommt, löschen wir einfach besagten Ordner &amp;quot;.github&amp;quot; im Ordner der DHT Sensor Library.&lt;br /&gt;
&lt;br /&gt;
Für MQTT brauchen wir drei weitere Libraries:&lt;br /&gt;
* [https://github.com/knolleary/pubsubclient PubSubClient Library, MQTT]&lt;br /&gt;
* Ethernet, ist in der Arduino IDE schon mit dabei&lt;br /&gt;
* SPI, für das Netzwerkshield, ist auch schon dabei&lt;br /&gt;
&lt;br /&gt;
== Notwendige Änderungen ==&lt;br /&gt;
&lt;br /&gt;
Im folgenden bauen wir den Sketch um. Zunächst prüfen wir, was am Sketch an sich geändert werden muss, anschließend fügen wir den MQTT Code hinzu. Zuletzt nutzen wir noch einige MQTT Features für weitere Optimierungen.&lt;br /&gt;
&lt;br /&gt;
=== Änderungen am Skript selbst ===&lt;br /&gt;
Die einfachste Möglichkeit ein Skript auf MQTT umzustellen, ist das Ändern der Ausgabe von Serial.print in ein mqtt.publish. Hier ergibt sich im Sketch ein Problem: Pubsubclient kann keine Werte vom Typ &amp;quot;float&amp;quot; als Payload versenden. Daher müssen wir zwei Konvertierungen hinzufügen:&lt;br /&gt;
* dtostrf(h,6, 1, humidity);&lt;br /&gt;
* dtostrf(t,6, 1, temperature);&lt;br /&gt;
machen den Trick: Nehme float h, benutze insgesamt 6 Stellen, 1 Nachkommastelle und schreibe das Ergebnis in humidity.&lt;br /&gt;
&lt;br /&gt;
Weiterhin ist es angenehmer, Variablen etc. am Anfang eines Sketches zu definieren, das machen wir auch noch.&lt;br /&gt;
&lt;br /&gt;
=== Änderungen für MQTT ===&lt;br /&gt;
Am einfachsten ist, wir nehmen uns einen der mitgelieferten MQTT Beispielsketche: mqtt_reconnect_nonblocking. Das müssen wir eigentlich nur an den jeweiligen Stellen in den originalen Sketch kopieren.&lt;br /&gt;
Dabei sind die IP Adressen anzupassen und eine MAC Adresse zu vergeben.&lt;br /&gt;
&lt;br /&gt;
Statt oder zusätzlich zu unserer Ausgabe über die serielle Schnittstelle fügen wir noch einen client.publish ein, so dass die Werte auf dem Broker landen.&lt;br /&gt;
&lt;br /&gt;
Der Vollständigkeit halber, hier der Sketch für das nicht - blockierende MQTT reconnect:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;arduino&amp;quot;&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 Reconnecting MQTT example - non-blocking&lt;br /&gt;
&lt;br /&gt;
 This sketch demonstrates how to keep the client connected&lt;br /&gt;
 using a non-blocking reconnect function. If the client loses&lt;br /&gt;
 its connection, it attempts to reconnect every 5 seconds&lt;br /&gt;
 without blocking the main loop.&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;SPI.h&amp;gt;&lt;br /&gt;
#include &amp;lt;Ethernet.h&amp;gt;&lt;br /&gt;
#include &amp;lt;PubSubClient.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// Update these with values suitable for your hardware/network.&lt;br /&gt;
byte mac[]    = {  0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED };&lt;br /&gt;
IPAddress ip(172, 16, 0, 100);&lt;br /&gt;
IPAddress server(172, 16, 0, 2);&lt;br /&gt;
&lt;br /&gt;
void callback(char* topic, byte* payload, unsigned int length) {&lt;br /&gt;
  // handle message arrived&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
EthernetClient ethClient;&lt;br /&gt;
PubSubClient client(ethClient);&lt;br /&gt;
&lt;br /&gt;
long lastReconnectAttempt = 0;&lt;br /&gt;
&lt;br /&gt;
boolean reconnect() {&lt;br /&gt;
  if (client.connect(&amp;quot;arduinoClient&amp;quot;)) {&lt;br /&gt;
    // Once connected, publish an announcement...&lt;br /&gt;
    client.publish(&amp;quot;outTopic&amp;quot;,&amp;quot;hello world&amp;quot;);&lt;br /&gt;
    // ... and resubscribe&lt;br /&gt;
    client.subscribe(&amp;quot;inTopic&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  return client.connected();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setup()&lt;br /&gt;
{&lt;br /&gt;
  client.setServer(server, 1883);&lt;br /&gt;
  client.setCallback(callback);&lt;br /&gt;
&lt;br /&gt;
  Ethernet.begin(mac, ip);&lt;br /&gt;
  delay(1500);&lt;br /&gt;
  lastReconnectAttempt = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void loop()&lt;br /&gt;
{&lt;br /&gt;
  if (!client.connected()) {&lt;br /&gt;
    long now = millis();&lt;br /&gt;
    if (now - lastReconnectAttempt &amp;gt; 5000) {&lt;br /&gt;
      lastReconnectAttempt = now;&lt;br /&gt;
      // Attempt to reconnect&lt;br /&gt;
      if (reconnect()) {&lt;br /&gt;
        lastReconnectAttempt = 0;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  } else {&lt;br /&gt;
    // Client connected&lt;br /&gt;
&lt;br /&gt;
    client.loop();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Optimierungsmöglichkeiten === &lt;br /&gt;
&lt;br /&gt;
==== Unfreiwilliger Netzwerktest ====&lt;br /&gt;
Jedesmal wenn die Schleife durchgelaufen wird, bekämen wir eine Nachricht mit der Temperatur und eine mit der Luftfeuchtigkeit. Das ist nicht so wirklich schlau. Hier bieten sich 3 Alternativen an:&lt;br /&gt;
* Delay =&amp;gt; dumme Idee, blockiert den Arduino, nicht benutzen&lt;br /&gt;
* eine nicht-blockierende Methode für den Arduino nehmen =&amp;gt; kann man machen&lt;br /&gt;
* Senden nur bei Werteänderung =&amp;gt; vermutlich das Ressourcenschonendste&lt;br /&gt;
&lt;br /&gt;
Ich verwende Variante 3.&lt;br /&gt;
&lt;br /&gt;
Wir benötigen dazu noch zwei weitere Variablen (h_alt und t_alt); jedesmal wenn die Sendeschleife durchlaufen wird, speichern wir h und t in diese Variablen. Zusätzlich benötigt unsere Schleife nach der Fehlerbehandlung noch einen if Zweig, der dafür sorgt, dass nichts getan wird wenn beide Werte sich nicht geändert haben.&lt;br /&gt;
&lt;br /&gt;
Jetzt können wir MQTT anweisen, die letzten Messwerte retained zu senden. Sonst würden wir erst dann Werte bekommen, wenn sich entweder die Temperatur oder die Luftfeuchte verändert haben.&lt;br /&gt;
* client.publish(&amp;quot;zuHause/Arduino_1/Kueche/Kuehlschrank/Luftfeuchte&amp;quot;,humidity);&lt;br /&gt;
wird zu&lt;br /&gt;
* client.publish(&amp;quot;zuHause/Arduino_1/Kueche/Kuehlschrank/Luftfeuchte&amp;quot;,humidity, true);&lt;br /&gt;
* das true dahinter ist das Flag für retained Messages&lt;br /&gt;
&lt;br /&gt;
==== Nachtrag zum Thema Pausen ====&lt;br /&gt;
Mit den Codeänderungen oben haben wir schon mal ein dauerhaftes publishen der gleichen Daten verhindert. Jedoch gibt es natürlich noch einige technische Besonderheiten, die wir ebenfalls berücksichtigen sollten:&lt;br /&gt;
&lt;br /&gt;
Bis jetzt führt unser Sketch bei jedem Durchlauf durch void.loop() eine Messung durch. Das hat zwei Folgen:&lt;br /&gt;
* der Sensor ist im Dauerbetrieb&lt;br /&gt;
* kleine Schwankungen führen natürlich zu einem erneuten publishen.&lt;br /&gt;
Wenn wir den Code, sagen wir, nur alle 2 Minuten ausführen würden, würderd der Sensor weniger belastet. Beim dem Verwendeten spielt es nicht wirklich eine große Rolle, aber es gibt Sensoren die auf einen derart häufigen Zugriff durchaus empfindlich reagieren können.&lt;br /&gt;
&lt;br /&gt;
Gleichzeitig bekommen wir viele kleine Schwankungen  (ich nenne sie mal Messungenauigkeiten) übermittelt, die uns eigentlich nicht interessieren.&lt;br /&gt;
&lt;br /&gt;
Die einfache Variante wäre wieder ein Delay. Dieses würde recht schnell zu einem Fehler führen: Ein Delay blockiert. Für MQTT bedeutet es, dass keine Keep-alive Pakete mehr gesendet werden. Hätten wir eingehende Nachrichten, dann würden wir diese auch verpassen.&lt;br /&gt;
Wir merken uns: nutze niemals Delays.&lt;br /&gt;
&lt;br /&gt;
Die oben schon angesprochene Lösung, eine nicht blockierende Methode verwenden, ist sehr gut geeignet.&lt;br /&gt;
&lt;br /&gt;
Wie geht das?&lt;br /&gt;
&lt;br /&gt;
Zunächst zählt der Arduino seine Laufzeit in Millisekunden. Wir schreiben unseren Temperaturausleseteil in eine kleine Schleife.&lt;br /&gt;
* zwei weitere Variablen&lt;br /&gt;
** unsigned long previousMillis = 0; //Zählervariable, zählt Millisekunden seit dem letzten Funktionsaufruf nach oben&lt;br /&gt;
** const long interval = 120000; //120000 Millisekunden aka 120 Sekunden, das Interval wie oft der Sensor überhaupt benutzt wird&lt;br /&gt;
* Drei Zeilen Programmcode mehr:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;arduino&amp;quot;&amp;gt;&lt;br /&gt;
unsigned long currentMillis = millis();&lt;br /&gt;
&lt;br /&gt;
  if (currentMillis - previousMillis &amp;gt;= interval) {&lt;br /&gt;
    previousMillis = currentMillis;&lt;br /&gt;
    &lt;br /&gt;
    h = dht.readHumidity();     //Luftfeuchte auslesen&lt;br /&gt;
    t = dht.readTemperature();  //Temperatur auslesen&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Last Will &amp;amp; Testament ====&lt;br /&gt;
Retten wir auch die Statusmeldungen des Skripts nach MQTT. Dazu ergänzen wir den client.connect Aufruf:&lt;br /&gt;
* if (client.connect(&amp;quot;Arduino_1&amp;quot;)) {&lt;br /&gt;
&lt;br /&gt;
um folgendes:&lt;br /&gt;
* if (client.connect(&amp;quot;Arduino_1&amp;quot;, &amp;quot;zuHause/Arduino_1&amp;quot;, 0, true, &amp;quot;offline&amp;quot;)) { &lt;br /&gt;
** Arduino_1 nennt sich unser Sensor&lt;br /&gt;
** &amp;quot;zuHause/Arduino_1&amp;quot; ist das Topic für dessen Statusmeldungen&lt;br /&gt;
** 0 ist die QoS&lt;br /&gt;
** true bedeutet, Nachricht retained senden&lt;br /&gt;
** &amp;quot;offline&amp;quot; ist das, was auf dem Topic geschrieben werden soll, wenn die Verbindung abbricht&lt;br /&gt;
** Anmerkung:&lt;br /&gt;
** Unsauberes disconnect wird verursacht durch:&lt;br /&gt;
** Abbruch der Netzwerkverbindung&lt;br /&gt;
** Protokollfehler (z.B. ungültige Topics, fehlerhafte Payload)&lt;br /&gt;
&lt;br /&gt;
Warum machen wir das?&lt;br /&gt;
* beim Start des Sensors steht nun &amp;quot;online&amp;quot; im Status&lt;br /&gt;
* bei einem Sensorfehler werden wir auf den Sensorfehler aufmerksam gemacht &amp;quot;Sensorfehler&amp;quot;&lt;br /&gt;
* bricht die Netzwerkverbindung ab, steht automatisch &amp;quot;offline&amp;quot; in dem Topic&lt;br /&gt;
* bei einer erfolgreichen Messung mit Datenübertragung steht wieder &amp;quot;online&amp;quot; im Topic&lt;br /&gt;
Auf diese Art und Weise haben wir eine aussagekräftige Zustandsmeldung in unserem Topic. Diese können wir bequem mit FHEM überwachen, um bei einem Fehler weitere Maßnahmen einzuleiten. Ein Vergleich des Alters der Sensorwerte wird überflüssig.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== MQTT an sich ===&lt;br /&gt;
Wer keinen eigenen Broker hat und (für diesen einen Test) keinen aufsetzen will, kann testweise auch einen öffentlichen Broker benutzen: test.mosquitto.org stellt so einen bereit. Bitte beachten, dass dieser Broker wirklich öffentlich ist. Mit ping test.mosquitto.org bekommt man (unter Windows) die IP Adresse, die man, ich möchte es nochmal betonen, zu Testzwecken, in seinen Sketch schreiben kann.&lt;br /&gt;
&lt;br /&gt;
Wir benötigen für MQTT entsprechende Topics.&lt;br /&gt;
* &amp;quot;zuHause/Arduino_1/Kueche/Kuehlschrank/Luftfeuchte&amp;quot;&lt;br /&gt;
* &amp;quot;zuHause/Arduino_1/Kueche/Kuehlschrank/Temperatur&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Daus ergibt sich letztlich folgender Sketch &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;arduino&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;DHT.h&amp;gt;&lt;br /&gt;
#include &amp;lt;SPI.h&amp;gt;&lt;br /&gt;
#include &amp;lt;Ethernet.h&amp;gt;&lt;br /&gt;
#include &amp;lt;PubSubClient.h&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
#define DHTPIN 9     &lt;br /&gt;
#define DHTTYPE DHT22 //DHT11, DHT21, DHT22&lt;br /&gt;
 &lt;br /&gt;
DHT dht(DHTPIN, DHTTYPE);&lt;br /&gt;
&lt;br /&gt;
byte mac[]    = {  0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; //eine MAC Adresse wählen, darf im eigenen Netz nur 1x vorkommen&lt;br /&gt;
IPAddress ip(192, 168, 5, 220); //eine gültige IP Adresse für das eigene Netz&lt;br /&gt;
IPAddress server(192, 168, 5, 2); //die Adresse wo der eigene MQTT Broker drauf läuft&lt;br /&gt;
&lt;br /&gt;
void callback(char* topic, byte* payload, unsigned int length) {&lt;br /&gt;
  // handle message arrived&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
EthernetClient ethClient;&lt;br /&gt;
PubSubClient client(ethClient);&lt;br /&gt;
&lt;br /&gt;
long lastReconnectAttempt = 0;&lt;br /&gt;
&lt;br /&gt;
boolean reconnect() {&lt;br /&gt;
  if (client.connect(&amp;quot;Arduino_1&amp;quot;, &amp;quot;zuHause/Arduino_1&amp;quot;, 0, true, &amp;quot;offline&amp;quot;)) {&lt;br /&gt;
    // Once connected, publish an announcement...&lt;br /&gt;
    client.publish(&amp;quot;zuHause/Arduino_1&amp;quot;,&amp;quot;online&amp;quot;, true);&lt;br /&gt;
    // ... and resubscribe&lt;br /&gt;
    client.subscribe(&amp;quot;inTopic&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  return client.connected();&lt;br /&gt;
}&lt;br /&gt;
static char humidity[15]; //Speicherbereich reservieren um die Fechtigkeit zu speichern&lt;br /&gt;
static char temperature[15];&lt;br /&gt;
float h = 0.0;&lt;br /&gt;
float h_alt = 0.0;&lt;br /&gt;
float t = 0.0;&lt;br /&gt;
float t_alt = 0.0;&lt;br /&gt;
unsigned long previousMillis = 0; //Zählervariable, zählt Millisekunden seit dem letzten Funktionsaufruf nach oben&lt;br /&gt;
const long interval = 120000; //120000 Millisekunden aka 120 Sekunden, das Interval wie oft der Sensor überhaupt benutzt wird&lt;br /&gt;
&lt;br /&gt;
void setup() &lt;br /&gt;
{&lt;br /&gt;
  client.setServer(server, 1883);&lt;br /&gt;
  client.setCallback(callback);&lt;br /&gt;
&lt;br /&gt;
  Ethernet.begin(mac, ip);&lt;br /&gt;
  delay(1500);&lt;br /&gt;
  lastReconnectAttempt = 0;&lt;br /&gt;
  &lt;br /&gt;
  Serial.begin(9600); &lt;br /&gt;
  Serial.println(&amp;quot;DHT22 - Test!&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  dht.begin();&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
void loop() &lt;br /&gt;
{&lt;br /&gt;
  if (!client.connected()) {&lt;br /&gt;
    long now = millis();&lt;br /&gt;
    if (now - lastReconnectAttempt &amp;gt; 5000) {&lt;br /&gt;
      lastReconnectAttempt = now;&lt;br /&gt;
      // Attempt to reconnect&lt;br /&gt;
      if (reconnect()) {&lt;br /&gt;
        lastReconnectAttempt = 0;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  } else {&lt;br /&gt;
    // Client connected&lt;br /&gt;
&lt;br /&gt;
    client.loop();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
unsigned long currentMillis = millis();&lt;br /&gt;
&lt;br /&gt;
  if (currentMillis - previousMillis &amp;gt;= interval) {&lt;br /&gt;
    previousMillis = currentMillis;&lt;br /&gt;
    &lt;br /&gt;
    h = dht.readHumidity();     //Luftfeuchte auslesen&lt;br /&gt;
    t = dht.readTemperature();  //Temperatur auslesen&lt;br /&gt;
  }&lt;br /&gt;
    &lt;br /&gt;
  // Prüfen ob eine gültige Zahl zurückgegeben wird. Wenn NaN (not a number) zurückgegeben wird, dann Fehler ausgeben.&lt;br /&gt;
  if (isnan(t) || isnan(h)) &lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;DHT22 konnte nicht ausgelesen werden&amp;quot;);&lt;br /&gt;
    client.publish(&amp;quot;zuHause/Arduino_1&amp;quot;,&amp;quot;Sensorfehler&amp;quot;,true); //true sendet die Nachricht retained, d.h. die Nachricht bleibt solange auf dem Broker, bis etwas neues kommt&lt;br /&gt;
  }&lt;br /&gt;
  else if (h == h_alt &amp;amp;&amp;amp; t == t_alt)&lt;br /&gt;
  {&lt;br /&gt;
    //nix machen&lt;br /&gt;
  }&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    client.publish(&amp;quot;zuHause/Arduino_1&amp;quot;,&amp;quot;online&amp;quot;, true);&lt;br /&gt;
    dtostrf(h,6, 1, humidity);&lt;br /&gt;
    dtostrf(t,6, 1, temperature);&lt;br /&gt;
    client.publish(&amp;quot;zuHause/Arduino_1/Kueche/Kuehlschrank/Luftfeuchte&amp;quot;,humidity, true);&lt;br /&gt;
    client.publish(&amp;quot;zuHause/Arduino_1/Kueche/Kuehlschrank/Temperatur&amp;quot;,temperature, true);&lt;br /&gt;
    h_alt = h; //den alten Messwert aufheben&lt;br /&gt;
    t_alt = t; //um nur bei Veränderung zu reagieren&lt;br /&gt;
    Serial.print(&amp;quot;Luftfeuchte: &amp;quot;); &lt;br /&gt;
    Serial.print(h);&lt;br /&gt;
    Serial.print(&amp;quot; %\t&amp;quot;);&lt;br /&gt;
    Serial.print(&amp;quot;Temperatur: &amp;quot;); &lt;br /&gt;
    Serial.print(t);&lt;br /&gt;
    Serial.println(&amp;quot; C&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Zusammenfassung ==&lt;br /&gt;
Um aus einem &amp;quot;normalen&amp;quot; Sketch einen MQTT Sketch zu machen muss man also:&lt;br /&gt;
* Netzwerk konfigurieren&lt;br /&gt;
* MQTT einrichten&lt;br /&gt;
Im wesentlichen kann man einfach den MQTT Beispielsketch &amp;quot;mqtt reconnect nonblocking&amp;quot; in seinen Sketch einbauen.&lt;br /&gt;
&lt;br /&gt;
Geringe Änderungen im vorhandenen Code sind nötig, um diversen Typen von Variablen als MQTT Payload verwenden zu können&lt;br /&gt;
&lt;br /&gt;
Als Bonus bekommen wir &amp;quot;vernünftige&amp;quot; Statuswerte für unseren Sensor, die sich einfach in FHEM abfangen und auswerten lassen. Als weiteren Bonus betrachte ich, dass die Netzwerklast sinkt. Zum Vergleich möchte ich hier die Jeelink Sensoren anführen, aber auch viele 433 MHz Sensoren, die einfach im &amp;quot;wenige Sekunden Takt&amp;quot; ihre Werte in der Gegend rumfunken. Von da her kann durch den Einsatz von MQTT-Techniken die Funkbelastung der Umgebung reduziert werden. Einerseits trägt man also weniger zur &amp;quot;Sensorischen Luftverschmutzung&amp;quot; bei, andererseits entlastet man auch sein FHEM vor der Aufgabe, unnötige Werte erst mal zu verwerfen.&lt;br /&gt;
&lt;br /&gt;
== Danke ==&lt;br /&gt;
Hier möchte ich mal Danke sagen. An Beta-User, der seit Teil 1 das Geschreibsel vorab durchliest und immer wertvolle Tipps und Änderungsvorschläge parat hat.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
[http://fluuux.de/2012/10/arduino-temperatur-und-luftfeuchtigkeit-mit-dem-dht22-prufen/ Originales Projekt]&lt;br /&gt;
&lt;br /&gt;
[https://wiki.fhem.de/wiki/MQTT_Einf%C3%BChrung_Teil_1 Teil 1 der MQTT Einführung]&lt;br /&gt;
&lt;br /&gt;
[https://wiki.fhem.de/wiki/MQTT_Einf%C3%BChrung_Teil_2 Teil 2 der MQTT Einführung]&lt;br /&gt;
&lt;br /&gt;
[https://forum.fhem.de/index.php/topic,69954.0.html Diskussionsthread im Forum]&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung_Teil_3&amp;diff=21110</id>
		<title>MQTT Einführung Teil 3</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung_Teil_3&amp;diff=21110"/>
		<updated>2017-04-01T18:54:15Z</updated>

		<summary type="html">&lt;p&gt;Rince: Artikel neu angeegt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= MQTT Einführung Teil 3 =&lt;br /&gt;
Zeit sich die Hände schmutzig zu machen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOCH NICHT GANZ FERTIG&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Übersicht ==&lt;br /&gt;
Im folgenden basteln wir einen einfachen Temperatursensor.&lt;br /&gt;
&lt;br /&gt;
Das ist nicht aufregend. Jedoch ist der Code im Originalzustand sehr gut überschaubar. Man kann daher gut die Änderungen sehen.&lt;br /&gt;
&lt;br /&gt;
== Originales Projekt ==&lt;br /&gt;
[http://fluuux.de/2012/10/arduino-temperatur-und-luftfeuchtigkeit-mit-dem-dht22-prufen/ hier bitte nachlesen]&lt;br /&gt;
&lt;br /&gt;
Mit freundlicher Genehmigung des Autors hier der originale Quellcode:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;arduino&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;quot;DHT.h&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
#define DHTPIN 9     &lt;br /&gt;
#define DHTTYPE DHT22 //DHT11, DHT21, DHT22&lt;br /&gt;
 &lt;br /&gt;
DHT dht(DHTPIN, DHTTYPE);&lt;br /&gt;
 &lt;br /&gt;
void setup() &lt;br /&gt;
{&lt;br /&gt;
  Serial.begin(9600); &lt;br /&gt;
  Serial.println(&amp;quot;DHT22 - Test!&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  dht.begin();&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
void loop() &lt;br /&gt;
{&lt;br /&gt;
  float h = dht.readHumidity();     //Luftfeuchte auslesen&lt;br /&gt;
  float t = dht.readTemperature();  //Temperatur auslesen&lt;br /&gt;
 &lt;br /&gt;
  // Prüfen ob eine gültige Zahl zurückgegeben wird. Wenn NaN (not a number) zurückgegeben wird, dann Fehler ausgeben.&lt;br /&gt;
  if (isnan(t) || isnan(h)) &lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;DHT22 konnte nicht ausgelesen werden&amp;quot;);&lt;br /&gt;
  } &lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    Serial.print(&amp;quot;Luftfeuchte: &amp;quot;); &lt;br /&gt;
    Serial.print(h);&lt;br /&gt;
    Serial.print(&amp;quot; %\t&amp;quot;);&lt;br /&gt;
    Serial.print(&amp;quot;Temperatur: &amp;quot;); &lt;br /&gt;
    Serial.print(t);&lt;br /&gt;
    Serial.println(&amp;quot; C&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Benötigte Hardware ===&lt;br /&gt;
* Arduino&lt;br /&gt;
* DHT-22 Sensor (nicht der Beste, aber seine Verwendung hält den Code einfach)&lt;br /&gt;
* 10 kOhm Widerstand&lt;br /&gt;
* Steckbrett&lt;br /&gt;
* Drähte&lt;br /&gt;
&lt;br /&gt;
Zusätzlich&lt;br /&gt;
* Ethernetshield mit W5100 Chip&lt;br /&gt;
* MQTT Broker (Testweise: 37.187.106.16 =&amp;gt; IP von test.mosquitto.org)&lt;br /&gt;
&lt;br /&gt;
== Kurze Beschreibung was der originale Code tut ==&lt;br /&gt;
* Zeilen 1-6: Library einbinden, PIN festlegen, initialisieren.&lt;br /&gt;
* Zeilen 8-14: Serielle Schnittstelle konfigurieren, netten Text schreiben...&lt;br /&gt;
* Zeilen 18-19: Sensorwerte auslesen&lt;br /&gt;
* Zeilen 21-25: Fehlerbehandlung&lt;br /&gt;
* Zeilen 26-34: Sensorwerte mit Beschreibung an die serielle Schnittstelle senden&lt;br /&gt;
&lt;br /&gt;
=== Bibliotheken die zu installieren sind ===&lt;br /&gt;
Anmerkung:&lt;br /&gt;
&lt;br /&gt;
Die Arduino IDE bietet viele Möglichkeiten Bibliotheken einzubinden. Bevorzugt verwendet man den eingebauten Library-Manager. Wer das nicht will, kann auch die Bibliotheken als ZIP Datei herunterladen, und dann mit &amp;quot;Bibliothek aus ZIP Datei hinzufügen&amp;quot; einbinden.&lt;br /&gt;
&lt;br /&gt;
Im folgenden die Links zu den ZIP Dateien&lt;br /&gt;
Für den originalen Sketch&lt;br /&gt;
* [https://github.com/adafruit/DHT-sensor-library Adafruit DHT Library]&lt;br /&gt;
* [https://github.com/adafruit/Adafruit_Sensor Adafruit Sensor Library]&lt;br /&gt;
In der Adruino IDE gibt es eine Warnung, &#039;&#039;WARNUNG: Unberechtigter Ordner .github in der Bibliothek &#039;DHT sensor library&#039;&#039;&#039;; diese kann ignoriert werden. Da die Meldung aber immer kommt, löschen wir einfach besagten Ordner &amp;quot;.github&amp;quot; im Ordner der DHT Sensor Library.&lt;br /&gt;
&lt;br /&gt;
Für MQTT brauchen wir drei weitere Libraries:&lt;br /&gt;
* [https://github.com/knolleary/pubsubclient PubSubClient Library, MQTT]&lt;br /&gt;
* Ethernet, ist in der Arduino IDE schon mit dabei&lt;br /&gt;
* SPI, für das Netzwerkshield, ist auch schon dabei&lt;br /&gt;
&lt;br /&gt;
== Notwendige Änderungen ==&lt;br /&gt;
&lt;br /&gt;
Im folgenden bauen wir den Sketch um. Zunächst prüfen wir, was am Sketch an sich geändert werden muss, anschließend fügen wir den MQTT Code hinzu. Zuletzt nutzen wir noch einige MQTT Features für weitere Optimierungen.&lt;br /&gt;
&lt;br /&gt;
=== Änderungen am Skript selbst ===&lt;br /&gt;
Die einfachste Möglichkeit ein Skript auf MQTT umzustellen, ist das Ändern der Ausgabe von Serial.print in ein mqtt.publish. Hier ergibt sich im Sketch ein Problem: Pubsubclient kann keine Werte vom Typ &amp;quot;float&amp;quot; als Payload versenden. Daher müssen wir zwei Konvertierungen hinzufügen:&lt;br /&gt;
* dtostrf(h,6, 1, humidity);&lt;br /&gt;
* dtostrf(t,6, 1, temperature);&lt;br /&gt;
machen den Trick: Nehme float h, benutze insgesamt 6 Stellen, 1 Nachkommastelle und schreibe das Ergebnis in humidity.&lt;br /&gt;
&lt;br /&gt;
Weiterhin ist es angenehmer, Variablen etc. am Anfang eines Sketches zu definieren, das machen wir auch noch.&lt;br /&gt;
&lt;br /&gt;
=== Änderungen für MQTT ===&lt;br /&gt;
Am einfachsten ist, wir nehmen uns einen der mitgelieferten MQTT Beispielsketche: mqtt_reconnect_nonblocking. Das müssen wir eigentlich nur an den jeweiligen Stellen in den originalen Sketch kopieren.&lt;br /&gt;
Dabei sind die IP Adressen anzupassen und eine MAC Adresse zu vergeben.&lt;br /&gt;
&lt;br /&gt;
Statt oder zusätzlich zu unserer Ausgabe über die serielle Schnittstelle fügen wir noch einen client.publish ein, so dass die Werte auf dem Broker landen.&lt;br /&gt;
&lt;br /&gt;
Der Vollständigkeit halber, hier der Sketch für das nicht - blockierende MQTT reconnect:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;arduino&amp;quot;&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 Reconnecting MQTT example - non-blocking&lt;br /&gt;
&lt;br /&gt;
 This sketch demonstrates how to keep the client connected&lt;br /&gt;
 using a non-blocking reconnect function. If the client loses&lt;br /&gt;
 its connection, it attempts to reconnect every 5 seconds&lt;br /&gt;
 without blocking the main loop.&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;SPI.h&amp;gt;&lt;br /&gt;
#include &amp;lt;Ethernet.h&amp;gt;&lt;br /&gt;
#include &amp;lt;PubSubClient.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// Update these with values suitable for your hardware/network.&lt;br /&gt;
byte mac[]    = {  0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED };&lt;br /&gt;
IPAddress ip(172, 16, 0, 100);&lt;br /&gt;
IPAddress server(172, 16, 0, 2);&lt;br /&gt;
&lt;br /&gt;
void callback(char* topic, byte* payload, unsigned int length) {&lt;br /&gt;
  // handle message arrived&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
EthernetClient ethClient;&lt;br /&gt;
PubSubClient client(ethClient);&lt;br /&gt;
&lt;br /&gt;
long lastReconnectAttempt = 0;&lt;br /&gt;
&lt;br /&gt;
boolean reconnect() {&lt;br /&gt;
  if (client.connect(&amp;quot;arduinoClient&amp;quot;)) {&lt;br /&gt;
    // Once connected, publish an announcement...&lt;br /&gt;
    client.publish(&amp;quot;outTopic&amp;quot;,&amp;quot;hello world&amp;quot;);&lt;br /&gt;
    // ... and resubscribe&lt;br /&gt;
    client.subscribe(&amp;quot;inTopic&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  return client.connected();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void setup()&lt;br /&gt;
{&lt;br /&gt;
  client.setServer(server, 1883);&lt;br /&gt;
  client.setCallback(callback);&lt;br /&gt;
&lt;br /&gt;
  Ethernet.begin(mac, ip);&lt;br /&gt;
  delay(1500);&lt;br /&gt;
  lastReconnectAttempt = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void loop()&lt;br /&gt;
{&lt;br /&gt;
  if (!client.connected()) {&lt;br /&gt;
    long now = millis();&lt;br /&gt;
    if (now - lastReconnectAttempt &amp;gt; 5000) {&lt;br /&gt;
      lastReconnectAttempt = now;&lt;br /&gt;
      // Attempt to reconnect&lt;br /&gt;
      if (reconnect()) {&lt;br /&gt;
        lastReconnectAttempt = 0;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  } else {&lt;br /&gt;
    // Client connected&lt;br /&gt;
&lt;br /&gt;
    client.loop();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Optimierungsmöglichkeiten === &lt;br /&gt;
&lt;br /&gt;
==== Unfreiwilliger Netzwerktest ====&lt;br /&gt;
Jedesmal wenn die Schleife durchgelaufen wird, bekämen wir eine Nachricht mit der Temperatur und eine mit der Luftfeuchtigkeit. Das ist nicht so wirklich schlau. Hier bieten sich 3 Alternativen an:&lt;br /&gt;
* Delay =&amp;gt; dumme Idee, blockiert den Arduino, nicht benutzen&lt;br /&gt;
* eine nicht-blockierende Methode für den Arduino nehmen =&amp;gt; kann man machen&lt;br /&gt;
* Senden nur bei Werteänderung =&amp;gt; vermutlich das Ressourcenschonendste&lt;br /&gt;
&lt;br /&gt;
Ich verwende Variante 3.&lt;br /&gt;
&lt;br /&gt;
Wir benötigen dazu noch zwei weitere Variablen (h_alt und t_alt); jedesmal wenn die Sendeschleife durchlaufen wird, speichern wir h und t in diese Variablen. Zusätzlich benötigt unsere Schleife nach der Fehlerbehandlung noch einen if Zweig, der dafür sorgt, dass nichts getan wird wenn beide Werte sich nicht geändert haben.&lt;br /&gt;
&lt;br /&gt;
Jetzt können wir MQTT anweisen, die letzten Messwerte retained zu senden. Sonst würden wir erst dann Werte bekommen, wenn sich entweder die Temperatur oder die Luftfeuchte verändert haben.&lt;br /&gt;
* client.publish(&amp;quot;zuHause/Arduino_1/Kueche/Kuehlschrank/Luftfeuchte&amp;quot;,humidity);&lt;br /&gt;
wird zu&lt;br /&gt;
* client.publish(&amp;quot;zuHause/Arduino_1/Kueche/Kuehlschrank/Luftfeuchte&amp;quot;,humidity, true);&lt;br /&gt;
* das true dahinter ist das Flag für retained Messages&lt;br /&gt;
&lt;br /&gt;
==== Nachtrag zum Thema Pausen ====&lt;br /&gt;
Mit den Codeänderungen oben haben wir schon mal ein dauerhaftes publishen der gleichen Daten verhindert. Jedoch gibt es natürlich noch einige technische Besonderheiten, die wir ebenfalls berücksichtigen sollten:&lt;br /&gt;
&lt;br /&gt;
Bis jetzt führt unser Sketch bei jedem Durchlauf durch void.loop() eine Messung durch. Das hat zwei Folgen:&lt;br /&gt;
* der Sensor ist im Dauerbetrieb&lt;br /&gt;
* kleine Schwankungen führen natürlich zu einem erneuten publishen.&lt;br /&gt;
Wenn wir den Code, sagen wir, nur alle 2 Minuten ausführen würden, wird der Sensor weniger belastet. Beim dem verwendeten spielt es nicht wirklich eine große Rolle, aber es gibt Sensoren die auf einen derart häufigen Zugriff durchaus empfindlich reagieren können.&lt;br /&gt;
&lt;br /&gt;
Gleichzeitig bekommen wir viele kleine Schwankungen  (ich nenne sie mal Messungenauigkeiten) einfach gar nicht mehr mit.&lt;br /&gt;
&lt;br /&gt;
Die einfache Variante wäre wieder ein Delay. Dieses würde recht schnell zu einem Fehler führen: Ein Delay blockiert. Für MQTT bedeutet es, dass keine Keep-alive Pakete mehr gesendet werden. Hätten wir eingehende Nachrichten, dann würden wir diese auch verpassen.&lt;br /&gt;
Wir merken uns: nutze niemals Delays.&lt;br /&gt;
&lt;br /&gt;
Die oben schon angesprochene Lösung, eine nicht blockierende Methode verwenden, ist sehr gut geeignet.&lt;br /&gt;
&lt;br /&gt;
Wie geht das?&lt;br /&gt;
&lt;br /&gt;
Zunächst zählt der Arduino seine Laufzeit in Millisekunden. Wir schreiben unseren Temperaturausleseteil in eine kleine Schleife.&lt;br /&gt;
* zwei weitere Variablen&lt;br /&gt;
** unsigned long previousMillis = 0; //Zählervariable, zählt Millisekunden seit dem letzten Funktionsaufruf nach oben&lt;br /&gt;
** const long interval = 120000; //120000 Millisekunden aka 120 Sekunden, das Interval wie oft der Sensor überhaupt benutzt wird&lt;br /&gt;
* Drei Zeilen Programmcode mehr:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;arduino&amp;quot;&amp;gt;&lt;br /&gt;
unsigned long currentMillis = millis();&lt;br /&gt;
&lt;br /&gt;
  if (currentMillis - previousMillis &amp;gt;= interval) {&lt;br /&gt;
    previousMillis = currentMillis;&lt;br /&gt;
    &lt;br /&gt;
    h = dht.readHumidity();     //Luftfeuchte auslesen&lt;br /&gt;
    t = dht.readTemperature();  //Temperatur auslesen&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Last Will &amp;amp; Testament ====&lt;br /&gt;
Retten wir auch die Statusmeldungen des Skripts nach MQTT. Dazu ergänzen wir den client.connect Aufruf:&lt;br /&gt;
* if (client.connect(&amp;quot;Arduino_1&amp;quot;)) {&lt;br /&gt;
&lt;br /&gt;
um folgendes:&lt;br /&gt;
* if (client.connect(&amp;quot;Arduino_1&amp;quot;, &amp;quot;zuHause/Arduino_1&amp;quot;, 0, true, &amp;quot;offline&amp;quot;)) { &lt;br /&gt;
** Arduino_1 nennt sich unser Sensor&lt;br /&gt;
** &amp;quot;zuHause/Arduino_1&amp;quot; ist das Topic für dessen Statusmeldungen&lt;br /&gt;
** 0 ist die QoS&lt;br /&gt;
** true bedeutet, Nachricht retained senden&lt;br /&gt;
** &amp;quot;offline&amp;quot; ist das, was auf dem Topic geschrieben werden soll, wenn die Verbindung abbricht&lt;br /&gt;
** Anmerkung:&lt;br /&gt;
** Unsauberes disconnect wird verursacht durch:&lt;br /&gt;
** Abbruch der Netzwerkverbindung&lt;br /&gt;
** Protokollfehler (z.B. ungültige Topics, fehlerhafte Payload)&lt;br /&gt;
&lt;br /&gt;
Warum machen wir das?&lt;br /&gt;
* beim Start des Sensors steht nun &amp;quot;online&amp;quot; im Status&lt;br /&gt;
* bei einem Sensorfehler werden wir auf den Sensorfehler aufmerksam gemacht &amp;quot;Sensorfehler&amp;quot;&lt;br /&gt;
* bricht die Netzwerkverbindung ab, steht automatisch &amp;quot;offline&amp;quot; in dem Topic&lt;br /&gt;
* bei einer erfolgreichen Messung mit Datenübertragung steht wieder &amp;quot;online&amp;quot; im Topic&lt;br /&gt;
Auf diese Art und Weise haben wir eine aussagekräftige Zustandsmeldung in unserem Topic. Diese können wir bequem mit FHEM überwachen, um bei einem Fehler weitere Maßnahmen einzuleiten. Ein Vergleich des Alters der Sensorwerte wird überflüssig.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== MQTT an sich ===&lt;br /&gt;
Wer keinen eigenen Broker hat und (für diesen einen Test) keinen aufsetzen will, kann testweise auch einen öffentlichen Broker benutzen: test.mosquitto.org stellt so einen bereit. Bitte beachten, dass dieser Broker wirklich öffentlich ist. Mit ping test.mosquitto.org bekommt man (unter Windows) die IP Adresse, die man, ich möchte es nochmal betonen, zu Testzwecken, in seinen Sketch schreiben kann.&lt;br /&gt;
&lt;br /&gt;
Wir benötigen für MQTT entsprechende Topics.&lt;br /&gt;
* &amp;quot;zuHause/Arduino_1/Kueche/Kuehlschrank/Luftfeuchte&amp;quot;&lt;br /&gt;
* &amp;quot;zuHause/Arduino_1/Kueche/Kuehlschrank/Temperatur&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Daus ergibt sich letztlich folgender Sketch &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;arduino&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;DHT.h&amp;gt;&lt;br /&gt;
#include &amp;lt;SPI.h&amp;gt;&lt;br /&gt;
#include &amp;lt;Ethernet.h&amp;gt;&lt;br /&gt;
#include &amp;lt;PubSubClient.h&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
#define DHTPIN 9     &lt;br /&gt;
#define DHTTYPE DHT22 //DHT11, DHT21, DHT22&lt;br /&gt;
 &lt;br /&gt;
DHT dht(DHTPIN, DHTTYPE);&lt;br /&gt;
&lt;br /&gt;
byte mac[]    = {  0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; //eine MAC Adresse wählen, darf im eigenen Netz nur 1x vorkommen&lt;br /&gt;
IPAddress ip(192, 168, 5, 220); //eine gültige IP Adresse für das eigene Netz&lt;br /&gt;
IPAddress server(192, 168, 5, 2); //die Adresse wo der eigene MQTT Broker drauf läuft&lt;br /&gt;
&lt;br /&gt;
void callback(char* topic, byte* payload, unsigned int length) {&lt;br /&gt;
  // handle message arrived&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
EthernetClient ethClient;&lt;br /&gt;
PubSubClient client(ethClient);&lt;br /&gt;
&lt;br /&gt;
long lastReconnectAttempt = 0;&lt;br /&gt;
&lt;br /&gt;
boolean reconnect() {&lt;br /&gt;
  if (client.connect(&amp;quot;Arduino_1&amp;quot;, &amp;quot;zuHause/Arduino_1&amp;quot;, 0, true, &amp;quot;offline&amp;quot;)) {&lt;br /&gt;
    // Once connected, publish an announcement...&lt;br /&gt;
    client.publish(&amp;quot;zuHause/Arduino_1&amp;quot;,&amp;quot;online&amp;quot;, true);&lt;br /&gt;
    // ... and resubscribe&lt;br /&gt;
    client.subscribe(&amp;quot;inTopic&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  return client.connected();&lt;br /&gt;
}&lt;br /&gt;
static char humidity[15]; //Speicherbereich reservieren um die Fechtigkeit zu speichern&lt;br /&gt;
static char temperature[15];&lt;br /&gt;
float h = 0.0;&lt;br /&gt;
float h_alt = 0.0;&lt;br /&gt;
float t = 0.0;&lt;br /&gt;
float t_alt = 0.0;&lt;br /&gt;
unsigned long previousMillis = 0; //Zählervariable, zählt Millisekunden seit dem letzten Funktionsaufruf nach oben&lt;br /&gt;
const long interval = 120000; //120000 Millisekunden aka 120 Sekunden, das Interval wie oft der Sensor überhaupt benutzt wird&lt;br /&gt;
&lt;br /&gt;
void setup() &lt;br /&gt;
{&lt;br /&gt;
  client.setServer(server, 1883);&lt;br /&gt;
  client.setCallback(callback);&lt;br /&gt;
&lt;br /&gt;
  Ethernet.begin(mac, ip);&lt;br /&gt;
  delay(1500);&lt;br /&gt;
  lastReconnectAttempt = 0;&lt;br /&gt;
  &lt;br /&gt;
  Serial.begin(9600); &lt;br /&gt;
  Serial.println(&amp;quot;DHT22 - Test!&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  dht.begin();&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
void loop() &lt;br /&gt;
{&lt;br /&gt;
  if (!client.connected()) {&lt;br /&gt;
    long now = millis();&lt;br /&gt;
    if (now - lastReconnectAttempt &amp;gt; 5000) {&lt;br /&gt;
      lastReconnectAttempt = now;&lt;br /&gt;
      // Attempt to reconnect&lt;br /&gt;
      if (reconnect()) {&lt;br /&gt;
        lastReconnectAttempt = 0;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
  } else {&lt;br /&gt;
    // Client connected&lt;br /&gt;
&lt;br /&gt;
    client.loop();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
unsigned long currentMillis = millis();&lt;br /&gt;
&lt;br /&gt;
  if (currentMillis - previousMillis &amp;gt;= interval) {&lt;br /&gt;
    previousMillis = currentMillis;&lt;br /&gt;
    &lt;br /&gt;
    h = dht.readHumidity();     //Luftfeuchte auslesen&lt;br /&gt;
    t = dht.readTemperature();  //Temperatur auslesen&lt;br /&gt;
  }&lt;br /&gt;
    &lt;br /&gt;
  // Prüfen ob eine gültige Zahl zurückgegeben wird. Wenn NaN (not a number) zurückgegeben wird, dann Fehler ausgeben.&lt;br /&gt;
  if (isnan(t) || isnan(h)) &lt;br /&gt;
  {&lt;br /&gt;
    Serial.println(&amp;quot;DHT22 konnte nicht ausgelesen werden&amp;quot;);&lt;br /&gt;
    client.publish(&amp;quot;zuHause/Arduino_1&amp;quot;,&amp;quot;Sensorfehler&amp;quot;,true); //true sendet die Nachricht retained, d.h. die Nachricht bleibt solange auf dem Broker, bis etwas neues kommt&lt;br /&gt;
  }&lt;br /&gt;
  else if (h == h_alt &amp;amp;&amp;amp; t == t_alt)&lt;br /&gt;
  {&lt;br /&gt;
    //nix machen&lt;br /&gt;
  }&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    client.publish(&amp;quot;zuHause/Arduino_1&amp;quot;,&amp;quot;online&amp;quot;, true);&lt;br /&gt;
    dtostrf(h,6, 1, humidity);&lt;br /&gt;
    dtostrf(t,6, 1, temperature);&lt;br /&gt;
    client.publish(&amp;quot;zuHause/Arduino_1/Kueche/Kuehlschrank/Luftfeuchte&amp;quot;,humidity, true);&lt;br /&gt;
    client.publish(&amp;quot;zuHause/Arduino_1/Kueche/Kuehlschrank/Temperatur&amp;quot;,temperature, true);&lt;br /&gt;
    h_alt = h; //den alten Messwert aufheben&lt;br /&gt;
    t_alt = t; //um nur bei Veränderung zu reagieren&lt;br /&gt;
    Serial.print(&amp;quot;Luftfeuchte: &amp;quot;); &lt;br /&gt;
    Serial.print(h);&lt;br /&gt;
    Serial.print(&amp;quot; %\t&amp;quot;);&lt;br /&gt;
    Serial.print(&amp;quot;Temperatur: &amp;quot;); &lt;br /&gt;
    Serial.print(t);&lt;br /&gt;
    Serial.println(&amp;quot; C&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Zusammenfassung ==&lt;br /&gt;
Um aus einem &amp;quot;normalen&amp;quot; Sketch einen MQTT Sketch zu machen muss man also:&lt;br /&gt;
* Netzwerk konfigurieren&lt;br /&gt;
* MQTT einrichten&lt;br /&gt;
Im wesentlichen kann man einfach den MQTT Beispielsketch &amp;quot;mqtt reconnect nonblocking&amp;quot; in seinen Sketch einbauen.&lt;br /&gt;
&lt;br /&gt;
Geringe Änderungen im vorhandenen Code sind nötig, um diversen Typen von Variablen als MQTT Payload verwenden zu können&lt;br /&gt;
&lt;br /&gt;
Als Bonus bekommen wir &amp;quot;vernünftige&amp;quot; Statuswerte für unseren Sensor, die sich einfach in FHEM abfangen und auswerten lassen. Als weiteren Bonus betrachte ich, dass die Netzwerklast sinkt. Zum Vergleich möchte ich hier die Jeelink Sensoren anführen, aber auch viele 433 MHz Sensoren, die einfach im &amp;quot;wenige Sekunden Takt&amp;quot; ihre Werte in der Gegend rumfunken. Von da her kann durch den Einsatz von MQTT-Techniken die Funkbelastung der Umgebung reduziert werden. Einerseits trägt man also weniger zur &amp;quot;Sensorischen Luftverschmutzung&amp;quot; bei, andererseits entlastet man auch sein FHEM vor der Aufgabe, unnötige Werte erst mal zu verwerfen.&lt;br /&gt;
&lt;br /&gt;
== Danke ==&lt;br /&gt;
Hier möchte ich mal Danke sagen. An Beta-User, der seit Teil 1 das Geschreibsel vorab durchliest und immer wertvolle Tipps und Änderungsvorschläge parat hat.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
[http://fluuux.de/2012/10/arduino-temperatur-und-luftfeuchtigkeit-mit-dem-dht22-prufen/ Originales Projekt]&lt;br /&gt;
&lt;br /&gt;
[https://wiki.fhem.de/wiki/MQTT_Einf%C3%BChrung_Teil_1 Teil 1 der MQTT Einführung]&lt;br /&gt;
&lt;br /&gt;
[https://wiki.fhem.de/wiki/MQTT_Einf%C3%BChrung_Teil_2 Teil 2 der MQTT Einführung]&lt;br /&gt;
&lt;br /&gt;
[https://forum.fhem.de/index.php/topic,69954.0.html Diskussionsthread im Forum]&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung_Teil_2&amp;diff=21109</id>
		<title>MQTT Einführung Teil 2</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung_Teil_2&amp;diff=21109"/>
		<updated>2017-04-01T18:35:03Z</updated>

		<summary type="html">&lt;p&gt;Rince: Kategorie Glossary zugeordnet&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= MQTT Teil 2 =&lt;br /&gt;
Konzepte und best practices&lt;br /&gt;
&lt;br /&gt;
== Vorwort ==&lt;br /&gt;
Wer den Teil 1 noch nicht gelesen hat, ist herzlich eingeladen das vorher noch schnell zu machen :)&lt;br /&gt;
&lt;br /&gt;
[https://wiki.fhem.de/wiki/MQTT_Einf%C3%BChrung Hier ist Teil 1]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschreibt, etwas trocken, weiterführend Konzepte und Denkweisen des Übertragungsprotokolls MQTT. Es wird etwas technischer als die Einführung und der ein oder andere Vergleich zu anderen Protokollen wird auch gezogen. Vieles davon kann man auch so nachlesen, wenngleich nicht immer auf deutsch. Ich gehe davon aus, dass der Leser MQTT vornehmlich mit FHEM einsetzen will.&lt;br /&gt;
&lt;br /&gt;
Ein Beispielkurs ist in Planung. Dort werden wir die Konzepte praktisch kennen lernen.&lt;br /&gt;
&lt;br /&gt;
== Retained Messages ==&lt;br /&gt;
=== Szenario ===&lt;br /&gt;
Stellen wir uns vor, wir starten FHEM neu. Wer Homematic Devices kennt weiß, spätestens nach einem Blick ins Logfile, dass nun zunächst ein Statusrequest aller Geräte erfolgt. Schließlich konnte sich zwischen Beenden und Neustart von FHEM etwas geändert haben.&lt;br /&gt;
* Homematic&lt;br /&gt;
* Es wird jedes Gerät angesprochen und abgefragt: &lt;br /&gt;
* &amp;quot;Lieber Lichtschalter, was tust du grade?&amp;quot; &lt;br /&gt;
* &amp;quot;Ich lasse das Licht über dir leuchten mein User.&amp;quot;&lt;br /&gt;
MQTT hat hier ein anderes Konzept. Wenn in ein Topic gepostet wird, kann ein &amp;quot;retained Flag&amp;quot; gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
=== Das bedeutet ===&lt;br /&gt;
Die zuletzt gepostete Nachricht wird vom Broker nicht gelöscht. Publishen wir also den Status unseres Lichts:&lt;br /&gt;
* zuHause/1OG/Kueche/Licht/state &amp;quot;on&amp;quot; oder &amp;quot;off&amp;quot; + retained flag&lt;br /&gt;
Sobald wir dieses Topic auf einem Gerät subscriben, bekommen wir den Status angezeigt. Ein neu startendes FHEM ist so ein Fall.&lt;br /&gt;
&lt;br /&gt;
Was bei Homematic erst über einen (zugegeben automatisierten Request) abläuft, kann MQTT mit den retained Messages auch so.&lt;br /&gt;
&lt;br /&gt;
Trifft am Broker eine neue retained Message ein, so wird die alte Nachricht gelöscht. Zum absichtlichen Löschen einer retained Message, etwa weil man weiß, dass dieses Topic zukünftig nicht mehr benötigt wird, kann man eine leere Message posten.&lt;br /&gt;
&lt;br /&gt;
=== Fazit ===&lt;br /&gt;
Retained Messages sind gut, um jeweils die letzte aktuelle Statusmeldung zu erhalten. Was damit nicht geht, ist z.B. die letzten 30 Messungen eines Temperatursensors zu speichern und auszuliefern! Sobald eine retained Message überschrieben wird, ist der alte Wert futsch.&lt;br /&gt;
&lt;br /&gt;
== Last Will and Testament (LWT) ==&lt;br /&gt;
=== Szenario ===&lt;br /&gt;
Letzter Wille und Testament. &amp;lt;hr&amp;gt;&lt;br /&gt;
Unser batteriebetriebener Sensor hat keinen Strom mehr, das billige 5V Netzteil stellt seinen Dienst ein, ein netter Nachbar eröffnet ein neues WLAN Netz welches unser Bestehendes gnadenlos stört, unsere süßen kleinen Miezekatzen finden Patchkabel so spannend, dass sie es für erfolgreiche Beißübungen verwenden…&lt;br /&gt;
Gründe für einen Sensorausfall gibt es durchaus.&lt;br /&gt;
Was passiert in FHEM?&lt;br /&gt;
Der letzte Sensorwert bleibt im Reading stehen. Blöd wenn man erst abends feststellt, dass der Kühlschrank offen stand oder der Schaltbefehl zum Heizung einschalten nicht angekommen ist. Ersteres sorgt für aufgetautes Essen, letzteres für kalte Füße.&lt;br /&gt;
Wie fängt man das ab?&lt;br /&gt;
FHEM-seitig könnte man einen Watchdog oder ein DOIF einrichten. Es muss geprüft werden, ob sich das entsprechende Reading in einer bestimmten Zeit verändert hat. &amp;lt;hr&amp;gt;&lt;br /&gt;
Möglich.&lt;br /&gt;
&lt;br /&gt;
=== MQTT Lösung ===&lt;br /&gt;
Der Letzte Wille, das Testament (LWT)&lt;br /&gt;
&lt;br /&gt;
Beim Anmelden an einen Broker kann ein Last Will - Topic angegeben werden. Ebenso eine Payload. Wenn das Gerät verschwindet ohne sich sauber abgemeldet zu haben, wird der Broker die gewünschte Nachricht auf dem hinterlegten Topic publishen. Das retained Flag kann auch gesetzt werden.&lt;br /&gt;
Was bedeutet das für uns?&lt;br /&gt;
&lt;br /&gt;
Zusätzlich zu:&lt;br /&gt;
*zuHause/1_OG/Kueche/Licht/state&lt;br /&gt;
*zuHause/1_OG/Kueche/Licht/set&lt;br /&gt;
&lt;br /&gt;
könnten wir zusätzlich&lt;br /&gt;
* zuHause/1_OG/Kueche/Licht/status&lt;br /&gt;
definieren.&lt;br /&gt;
&lt;br /&gt;
Beim Anmelden an den Broker schicken wir (mit retained flag) ein &amp;quot;online&amp;quot;&lt;br /&gt;
Als LWT geben wir das gleiche Topic an, aber mit &amp;quot;offline&amp;quot; und retained flag. Meldet sich unser Device sauber ab (disconnect), wird das LWT nicht verwendet. Es dient nur dazu, einen Fehler deutlich zu machen.&lt;br /&gt;
&lt;br /&gt;
==== Vorsicht ====&lt;br /&gt;
LWT bezieht sich auf die Client ID. Was das schon wieder?&lt;br /&gt;
Jedes angemeldete Gerät hat eine einzige Client ID, unabhängig davon wie viele Topics es published und subscribed hat.&lt;br /&gt;
LWT auf ein Topic zu beziehen macht wenig Sinn, wenn es mehrere Topics auf dem Gerät gibt. Obiges Beispiel ist also gut, wenn an dem MC genau dieses eine Licht hängt!&lt;br /&gt;
* zuHause/1OG/Arduino_1&lt;br /&gt;
Ist der bessere Weg! Jetzt können wir in FHEM auf online / offline reagieren und den davon abhängigen Geräten eine Fehlerbehandlung spendieren. Da ist unser DOIF wieder :)&lt;br /&gt;
&lt;br /&gt;
==== Noch eine Falle ====&lt;br /&gt;
Wer denkt, er wirft alle Geräte in ein einziges retained last will Topic, sieht immer nur die letzte Meldung!&lt;br /&gt;
&lt;br /&gt;
Böse:&lt;br /&gt;
&lt;br /&gt;
zuHause/MQTT/Status (&amp;lt;= nicht nachmachen)&lt;br /&gt;
&lt;br /&gt;
=== Fazit ===&lt;br /&gt;
MQTT kann einen eleganten Weg bieten, über das Ende eines Gerätes zu informieren. Genau wie bei Homematic aber auch, muss man diese Meldungen auswerten um was sinnvolles damit anzufangen!&lt;br /&gt;
Im Fall eines einfachen Sensors ist es recht easy, bei einem Arduino Mega mit 30 Sensoren wird es dann aufwendig (außer man liest weiter bei den Filtern)&lt;br /&gt;
&lt;br /&gt;
== Organisation der Topics ==&lt;br /&gt;
=== Basics, erlaubte Zeichen ===&lt;br /&gt;
MQTT erlaubt prinzipiell den kompletten UTF8 Zeichensatz.&lt;br /&gt;
&lt;br /&gt;
Außer:&lt;br /&gt;
* U+0001..U+001F control characters&lt;br /&gt;
* U+007F..U+009F control characters&lt;br /&gt;
&lt;br /&gt;
Theoretisch gehen also Umlaute, Leerzeichen etc. Praktisch kann es passieren, dass ein Endgerät mit Umlauten einfach nix anfangen kann. Leerzeichen sind auch ein Problem, weil UTF 8 davon doch recht viele Möglichkeiten bietet. Ich würde daher empfehlen, Topicbezeichnungen eher wie Gerätenamen in FHEM zu betrachten: Unterstriche statt Leerzeichen, Umlaute ausschreiben (=&amp;gt; ü =&amp;gt; ue...)&lt;br /&gt;
&lt;br /&gt;
Groß- und Kleinschreibung muss beachtet werden. Ein Topic muss mindestens ein Zeichen haben, um gültig zu sein. Oh, und $ gehen auch gar nicht. Die verwendet der Broker nämlich für Interna...&lt;br /&gt;
&lt;br /&gt;
Schlechtes Beispiel:&lt;br /&gt;
* /zuHause/&lt;br /&gt;
* nicht ganz falsch, aber der / am Anfang ist nur zusätzlicher Overhead, daher weglassen&lt;br /&gt;
&lt;br /&gt;
Wirklich falsch:&lt;br /&gt;
* zuHause//1_OG&lt;br /&gt;
* Hier wird ein leeres Topic definiert. Das ist ungültig.&lt;br /&gt;
&lt;br /&gt;
=== Basics, Strukturierung ===&lt;br /&gt;
MQTT kennt publishen und subscriben.&lt;br /&gt;
&lt;br /&gt;
FHEM kennt für jedes Gerät einen &amp;quot;state&amp;quot; und ein &amp;quot;set&amp;quot; Kommando. Das ist bei MQTT nicht nötig, aber durchaus sehr sinnvoll.&lt;br /&gt;
&lt;br /&gt;
Nehmen wir wieder unseren Lichtschalter: Ein Taster an einem Arduino mit einem Relais nebst Lampe daran.&lt;br /&gt;
&lt;br /&gt;
Unglücklich:&lt;br /&gt;
* zuHause/1_OG/Kueche/Lichtschalter&lt;br /&gt;
Wenn da ein &amp;quot;on&amp;quot; steht, woher will man wissen ob es sich um einen Befehl oder um eine Statusmeldung handelt? Daher bauen wir die FHEM übliche Logik einfach nach:&lt;br /&gt;
&lt;br /&gt;
Etwas glücklicher (kann man machen, man kann es aber schwer filtern)&lt;br /&gt;
* zuHause/1_OG/Kueche/Lichtschalter/set&lt;br /&gt;
* zuHause/1_OG/Kueche/Lichtschalter/state&lt;br /&gt;
&lt;br /&gt;
Richtig schlau (warum, kommt bei den Filtern)&lt;br /&gt;
* set/zuHause/1_OG/Kueche/Lichtschalter&lt;br /&gt;
* state/zuHause/1_OG/Kueche/Lichtschalter/state&lt;br /&gt;
&lt;br /&gt;
Jetzt wird es einfach:&lt;br /&gt;
&lt;br /&gt;
auf dem set-Topic publishen wir immer Schaltbefehle. Mit oder ohne retained flag, darüber kann man streiten. Unser Arduino muss also dieses Topic abhören und auswerten.&lt;br /&gt;
&lt;br /&gt;
Das state-Topic nehmen wir um darauf zu publishen (hier ist retained einfeutig praktisch), wie der Zustand unserer Lampe gerade ist. Unser Arduino muss dieses Topic nur schreiben, niemals selber lesen.&lt;br /&gt;
&lt;br /&gt;
Damit haben wir eine saubere Trennung von Befehl und Status erreicht.&lt;br /&gt;
&lt;br /&gt;
=== Aufbau eines Topics ===&lt;br /&gt;
Wie bereits geschrieben, kann man die Topics recht frei einfach selbst erfinden. Sinnvoll ist es jedoch, jedem gewünschten Wert ein eigenes Topic zu spendieren.&lt;br /&gt;
&lt;br /&gt;
Ungünstig:&lt;br /&gt;
* zuHause/state/1_OG/Kueche &lt;br /&gt;
* =&amp;gt; In diesem Topic Licht, Temperatur, Luftfeuchte, Bewegungsmelder etc zu publishen ist eine nicht schlaue Idee; das Problem beginnt damit, dass man erst mal selber rausfinden muss, welchen Wert man gerade hat. Viel Programmcode für quasi umsonst; &amp;quot;on 20.3 66 motion&amp;quot; ist nun nicht wirklich toll.&lt;br /&gt;
&lt;br /&gt;
Besser:&lt;br /&gt;
* zuHause/state/1_OG/Kueche/Licht &lt;br /&gt;
* zuHause/state/1_OG/Kueche/Raumtemperatur &lt;br /&gt;
* zuHause/state/1_OG/Kueche/Luftfeuchte&lt;br /&gt;
* zuHause/state/1_OG/Kueche/Bewegungsmelder&lt;br /&gt;
=&amp;gt; Auf diese Weise weiß man vorher, welche (Zahlen)werte in einem Topic stehen und was sie bedeuten. Das hat man automatisch durch die geschickte Topic Wahl festgelegt.&lt;br /&gt;
&lt;br /&gt;
=== Filter ===&lt;br /&gt;
Eine witzige Sache von MQTT sind Filter. Das ist in etwa wie in FHEM eine readingsGroup für Arme. Wir möchten schnell einen Überblick haben, welchen Status bestimmte Devices haben.&lt;br /&gt;
&lt;br /&gt;
Es gibt zwei Arten von Filtern:&lt;br /&gt;
* Single Level Filter: +&lt;br /&gt;
* Multi Level Filter: #&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiele:&lt;br /&gt;
* zuHause/state/1_OG/Kueche/Temperatur&lt;br /&gt;
* zuHause/state/1_OG/Kueche/Kuehlschrank/Temperatur&lt;br /&gt;
* zuHause/state/1_OG/Kueche/Licht&lt;br /&gt;
* zuHause/state/1_OG/Wohnzimmer/Licht&lt;br /&gt;
* zuHause/state/1_OG/Schlafzimmer/Licht&lt;br /&gt;
&lt;br /&gt;
Jetzt filtern wir:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;#&amp;quot; =&amp;gt; muss immer der letzte Filter sein (es gibt Broker, die die # auch als Platzhalter innerhalb eines Topics erlauben, aber Standard ist das nicht)&lt;br /&gt;
&lt;br /&gt;
* zuHause/state/# =&amp;gt; gibt uns alle oben genannten Beispiel-Topics zurück&lt;br /&gt;
* zuHause/state/1_OG/+/Licht =&amp;gt; gibt uns das Licht der Küche, des Wohn- und des Schlafzimmers&lt;br /&gt;
* zuHause/state/1_OG/+/Temperatur =&amp;gt; gibt nur die Küchentemperatur (+ steht für genau 1 Topic, der Kühlschrank fällt also nicht in das Muster)&lt;br /&gt;
&lt;br /&gt;
=== Diskussionspunkt, Devicenamen ===&lt;br /&gt;
Manchmal liest man auch den Tip, eine eindeutige Gerätebezeichnung in das Topic mit aufzunehmen.&lt;br /&gt;
* Arduino_1/state/Zimmer_1/Licht&lt;br /&gt;
* Arduino_1/state/Zimmer_1/Temperatur&lt;br /&gt;
* Arduino_1/state/Zimmer_2/Licht&lt;br /&gt;
* Arduino_2/state/Zimmer_3/Licht&lt;br /&gt;
&lt;br /&gt;
Hat im wesentlichen folgenden Vorteil:&lt;br /&gt;
&lt;br /&gt;
Wenn ich mir nur ansehen will, was ein bestimmter Mikrocontroller published, kann ich ihn sehr einfach filtern.&lt;br /&gt;
* Arduino_1/# =&amp;gt; perfekt um alle Werte des Arduino_1 zu lesen und sonst nichts&lt;br /&gt;
&lt;br /&gt;
Nachteilig:&lt;br /&gt;
&lt;br /&gt;
Tauscht man später den Controller aus, muss man ihn wieder so nennen. Fasst man später Arduino_1 und Arduino_2 auf einem Arduino Mega zusammen, stimmen die Topics schlicht nicht mehr und man muss seine ganzen Devicenamen anpassen.&lt;br /&gt;
&lt;br /&gt;
== Der Artikel hast &amp;quot;Best Practices&amp;quot; versprochen - wo sind sie? ==&lt;br /&gt;
Schwierig. Was die Benennung der Topics betrifft, so vom Zeichensatz her, gibt es Regeln und best practices, die stehen oben.&lt;br /&gt;
&lt;br /&gt;
Ob man jetzt eindeutige Gerätenamen vorne weg schreibt, oder ob man state und set weiter vorne im Topic Tree unterbringt oder hinten, ich fürchte da gibt es keine allgemein gültigen Regeln. MQTT lässt einem hier alle Freiheiten.&lt;br /&gt;
&lt;br /&gt;
Das eine sieht eher nach FHEM aus (set und state am Ende), das andere lässt sich besser filtern.&lt;br /&gt;
Hardcoreuser könnten auch auf die Idee kommen, einfach beide Varianten gleichzeitig zu nutzen. Für FHEM alleine ist das sicherlich nicht hilfreich (aber auch nicht störend).&lt;br /&gt;
&lt;br /&gt;
== Schlusswort ==&lt;br /&gt;
Hier endet vorübergehend unser kleiner Exkurs zu MQTT.&lt;br /&gt;
&lt;br /&gt;
Wer Fragen der Anregungen hat, bitte im [https://forum.fhem.de/index.php/topic,69701.0.html Diskussionsthread dieses Artikels] stellen.&lt;br /&gt;
&lt;br /&gt;
Weiterhin haben wir ganz neu [https://forum.fhem.de/index.php/board,94.0.html einen eigenen Forumsbereich für MQTT].&lt;br /&gt;
&lt;br /&gt;
Je nachdem wie gut die Artikelserie ankommt, werde ich einen Teil 3 auflegen. Dieser ist dann zum &amp;quot;get your hands dirty&amp;quot;, zum Hände dreckig machen. Darin könnte ein kleiner Programmierkurs in der Arduino IDE kommen. Mir schwebt vor, einen kleinen Sketch zu nehmen, diesen mit MQTT auszurüsten und nach und nach die Dinge wie LWT, retained messages etc. einzubauen. Das ist im wesentlichen mit wenigen Änderungen möglich. Also durchaus anfängertauglich. &lt;br /&gt;
&lt;br /&gt;
Ich werde einen Arduino Uno oder Mega nehmen, sowie ein Ethernetshield mit W5100 Chip benutzen. Die Dinger kosten keine 6 € auf eBay. Die ENC28J60 (oder ähnliche) Chips werden explizit NICHT unterstützt werden! Wer lieber einen ESP8266 nimmt, der sei an dieser Stelle auf das Template von Pf@nne verwiesen [https://forum.fhem.de/index.php/topic,50238.0.html hier zu finden].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Glossary]]&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung_Teil_2&amp;diff=21051</id>
		<title>MQTT Einführung Teil 2</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung_Teil_2&amp;diff=21051"/>
		<updated>2017-03-27T18:19:50Z</updated>

		<summary type="html">&lt;p&gt;Rince: fertig&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= MQTT Teil 2 =&lt;br /&gt;
Konzepte und best practices&lt;br /&gt;
&lt;br /&gt;
== Vorwort ==&lt;br /&gt;
Wer den Teil 1 noch nicht gelesen hat, ist herzlich eingeladen das vorher noch schnell zu machen :)&lt;br /&gt;
&lt;br /&gt;
[https://wiki.fhem.de/wiki/MQTT_Einf%C3%BChrung Hier ist Teil 1]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschreibt, etwas trocken, weiterführend Konzepte und Denkweisen des Übertragungsprotokolls MQTT. Es wird etwas technischer als die Einführung und der ein oder andere Vergleich zu anderen Protokollen wird auch gezogen. Vieles davon kann man auch so nachlesen, wenngleich nicht immer auf deutsch. Ich gehe davon aus, dass der Leser MQTT vornehmlich mit FHEM einsetzen will.&lt;br /&gt;
&lt;br /&gt;
Ein Beispielkurs ist in Planung. Dort werden wir die Konzepte praktisch kennen lernen.&lt;br /&gt;
&lt;br /&gt;
== Retained Messages ==&lt;br /&gt;
=== Szenario ===&lt;br /&gt;
Stellen wir uns vor, wir starten FHEM neu. Wer Homematic Devices kennt weiß, spätestens nach einem Blick ins Logfile, dass nun zunächst ein Statusrequest aller Geräte erfolgt. Schließlich konnte sich zwischen Beenden und Neustart von FHEM etwas geändert haben.&lt;br /&gt;
* Homematic&lt;br /&gt;
* Es wird jedes Gerät angesprochen und abgefragt: &lt;br /&gt;
* &amp;quot;Lieber Lichtschalter, was tust du grade?&amp;quot; &lt;br /&gt;
* &amp;quot;Ich lasse das Licht über dir leuchten mein User.&amp;quot;&lt;br /&gt;
MQTT hat hier ein anderes Konzept. Wenn in ein Topic gepostet wird, kann ein &amp;quot;retained Flag&amp;quot; gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
=== Das bedeutet ===&lt;br /&gt;
Die zuletzt gepostete Nachricht wird vom Broker nicht gelöscht. Publishen wir also den Status unseres Lichts:&lt;br /&gt;
* zuHause/1OG/Kueche/Licht/state &amp;quot;on&amp;quot; oder &amp;quot;off&amp;quot; + retained flag&lt;br /&gt;
Sobald wir dieses Topic auf einem Gerät subscriben, bekommen wir den Status angezeigt. Ein neu startendes FHEM ist so ein Fall.&lt;br /&gt;
&lt;br /&gt;
Was bei Homematic erst über einen (zugegeben automatisierten Request) abläuft, kann MQTT mit den retained Messages auch so.&lt;br /&gt;
&lt;br /&gt;
Trifft am Broker eine neue retained Message ein, so wird die alte Nachricht gelöscht. Zum absichtlichen Löschen einer retained Message, etwa weil man weiß, dass dieses Topic zukünftig nicht mehr benötigt wird, kann man eine leere Message posten.&lt;br /&gt;
&lt;br /&gt;
=== Fazit ===&lt;br /&gt;
Retained Messages sind gut, um jeweils die letzte aktuelle Statusmeldung zu erhalten. Was damit nicht geht, ist z.B. die letzten 30 Messungen eines Temperatursensors zu speichern und auszuliefern! Sobald eine retained Message überschrieben wird, ist der alte Wert futsch.&lt;br /&gt;
&lt;br /&gt;
== Last Will and Testament (LWT) ==&lt;br /&gt;
=== Szenario ===&lt;br /&gt;
Letzter Wille und Testament. &amp;lt;hr&amp;gt;&lt;br /&gt;
Unser batteriebetriebener Sensor hat keinen Strom mehr, das billige 5V Netzteil stellt seinen Dienst ein, ein netter Nachbar eröffnet ein neues WLAN Netz welches unser Bestehendes gnadenlos stört, unsere süßen kleinen Miezekatzen finden Patchkabel so spannend, dass sie es für erfolgreiche Beißübungen verwenden…&lt;br /&gt;
Gründe für einen Sensorausfall gibt es durchaus.&lt;br /&gt;
Was passiert in FHEM?&lt;br /&gt;
Der letzte Sensorwert bleibt im Reading stehen. Blöd wenn man erst abends feststellt, dass der Kühlschrank offen stand oder der Schaltbefehl zum Heizung einschalten nicht angekommen ist. Ersteres sorgt für aufgetautes Essen, letzteres für kalte Füße.&lt;br /&gt;
Wie fängt man das ab?&lt;br /&gt;
FHEM-seitig könnte man einen Watchdog oder ein DOIF einrichten. Es muss geprüft werden, ob sich das entsprechende Reading in einer bestimmten Zeit verändert hat. &amp;lt;hr&amp;gt;&lt;br /&gt;
Möglich.&lt;br /&gt;
&lt;br /&gt;
=== MQTT Lösung ===&lt;br /&gt;
Der Letzte Wille, das Testament (LWT)&lt;br /&gt;
&lt;br /&gt;
Beim Anmelden an einen Broker kann ein Last Will - Topic angegeben werden. Ebenso eine Payload. Wenn das Gerät verschwindet ohne sich sauber abgemeldet zu haben, wird der Broker die gewünschte Nachricht auf dem hinterlegten Topic publishen. Das retained Flag kann auch gesetzt werden.&lt;br /&gt;
Was bedeutet das für uns?&lt;br /&gt;
&lt;br /&gt;
Zusätzlich zu:&lt;br /&gt;
*zuHause/1_OG/Kueche/Licht/state&lt;br /&gt;
*zuHause/1_OG/Kueche/Licht/set&lt;br /&gt;
&lt;br /&gt;
könnten wir zusätzlich&lt;br /&gt;
* zuHause/1_OG/Kueche/Licht/status&lt;br /&gt;
definieren.&lt;br /&gt;
&lt;br /&gt;
Beim Anmelden an den Broker schicken wir (mit retained flag) ein &amp;quot;online&amp;quot;&lt;br /&gt;
Als LWT geben wir das gleiche Topic an, aber mit &amp;quot;offline&amp;quot; und retained flag. Meldet sich unser Device sauber ab (disconnect), wird das LWT nicht verwendet. Es dient nur dazu, einen Fehler deutlich zu machen.&lt;br /&gt;
&lt;br /&gt;
==== Vorsicht ====&lt;br /&gt;
LWT bezieht sich auf die Client ID. Was das schon wieder?&lt;br /&gt;
Jedes angemeldete Gerät hat eine einzige Client ID, unabhängig davon wie viele Topics es published und subscribed hat.&lt;br /&gt;
LWT auf ein Topic zu beziehen macht wenig Sinn, wenn es mehrere Topics auf dem Gerät gibt. Obiges Beispiel ist also gut, wenn an dem MC genau dieses eine Licht hängt!&lt;br /&gt;
* zuHause/1OG/Arduino_1&lt;br /&gt;
Ist der bessere Weg! Jetzt können wir in FHEM auf online / offline reagieren und den davon abhängigen Geräten eine Fehlerbehandlung spendieren. Da ist unser DOIF wieder :)&lt;br /&gt;
&lt;br /&gt;
==== Noch eine Falle ====&lt;br /&gt;
Wer denkt, er wirft alle Geräte in ein einziges retained last will Topic, sieht immer nur die letzte Meldung!&lt;br /&gt;
&lt;br /&gt;
Böse:&lt;br /&gt;
&lt;br /&gt;
zuHause/MQTT/Status (&amp;lt;= nicht nachmachen)&lt;br /&gt;
&lt;br /&gt;
=== Fazit ===&lt;br /&gt;
MQTT kann einen eleganten Weg bieten, über das Ende eines Gerätes zu informieren. Genau wie bei Homematic aber auch, muss man diese Meldungen auswerten um was sinnvolles damit anzufangen!&lt;br /&gt;
Im Fall eines einfachen Sensors ist es recht easy, bei einem Arduino Mega mit 30 Sensoren wird es dann aufwendig (außer man liest weiter bei den Filtern)&lt;br /&gt;
&lt;br /&gt;
== Organisation der Topics ==&lt;br /&gt;
=== Basics, erlaubte Zeichen ===&lt;br /&gt;
MQTT erlaubt prinzipiell den kompletten UTF8 Zeichensatz.&lt;br /&gt;
&lt;br /&gt;
Außer:&lt;br /&gt;
* U+0001..U+001F control characters&lt;br /&gt;
* U+007F..U+009F control characters&lt;br /&gt;
&lt;br /&gt;
Theoretisch gehen also Umlaute, Leerzeichen etc. Praktisch kann es passieren, dass ein Endgerät mit Umlauten einfach nix anfangen kann. Leerzeichen sind auch ein Problem, weil UTF 8 davon doch recht viele Möglichkeiten bietet. Ich würde daher empfehlen, Topicbezeichnungen eher wie Gerätenamen in FHEM zu betrachten: Unterstriche statt Leerzeichen, Umlaute ausschreiben (=&amp;gt; ü =&amp;gt; ue...)&lt;br /&gt;
&lt;br /&gt;
Groß- und Kleinschreibung muss beachtet werden. Ein Topic muss mindestens ein Zeichen haben, um gültig zu sein. Oh, und $ gehen auch gar nicht. Die verwendet der Broker nämlich für Interna...&lt;br /&gt;
&lt;br /&gt;
Schlechtes Beispiel:&lt;br /&gt;
* /zuHause/&lt;br /&gt;
* nicht ganz falsch, aber der / am Anfang ist nur zusätzlicher Overhead, daher weglassen&lt;br /&gt;
&lt;br /&gt;
Wirklich falsch:&lt;br /&gt;
* zuHause//1_OG&lt;br /&gt;
* Hier wird ein leeres Topic definiert. Das ist ungültig.&lt;br /&gt;
&lt;br /&gt;
=== Basics, Strukturierung ===&lt;br /&gt;
MQTT kennt publishen und subscriben.&lt;br /&gt;
&lt;br /&gt;
FHEM kennt für jedes Gerät einen &amp;quot;state&amp;quot; und ein &amp;quot;set&amp;quot; Kommando. Das ist bei MQTT nicht nötig, aber durchaus sehr sinnvoll.&lt;br /&gt;
&lt;br /&gt;
Nehmen wir wieder unseren Lichtschalter: Ein Taster an einem Arduino mit einem Relais nebst Lampe daran.&lt;br /&gt;
&lt;br /&gt;
Unglücklich:&lt;br /&gt;
* zuHause/1_OG/Kueche/Lichtschalter&lt;br /&gt;
Wenn da ein &amp;quot;on&amp;quot; steht, woher will man wissen ob es sich um einen Befehl oder um eine Statusmeldung handelt? Daher bauen wir die FHEM übliche Logik einfach nach:&lt;br /&gt;
&lt;br /&gt;
Etwas glücklicher (kann man machen, man kann es aber schwer filtern)&lt;br /&gt;
* zuHause/1_OG/Kueche/Lichtschalter/set&lt;br /&gt;
* zuHause/1_OG/Kueche/Lichtschalter/state&lt;br /&gt;
&lt;br /&gt;
Richtig schlau (warum, kommt bei den Filtern)&lt;br /&gt;
* set/zuHause/1_OG/Kueche/Lichtschalter&lt;br /&gt;
* state/zuHause/1_OG/Kueche/Lichtschalter/state&lt;br /&gt;
&lt;br /&gt;
Jetzt wird es einfach:&lt;br /&gt;
&lt;br /&gt;
auf dem set-Topic publishen wir immer Schaltbefehle. Mit oder ohne retained flag, darüber kann man streiten. Unser Arduino muss also dieses Topic abhören und auswerten.&lt;br /&gt;
&lt;br /&gt;
Das state-Topic nehmen wir um darauf zu publishen (hier ist retained einfeutig praktisch), wie der Zustand unserer Lampe gerade ist. Unser Arduino muss dieses Topic nur schreiben, niemals selber lesen.&lt;br /&gt;
&lt;br /&gt;
Damit haben wir eine saubere Trennung von Befehl und Status erreicht.&lt;br /&gt;
&lt;br /&gt;
=== Aufbau eines Topics ===&lt;br /&gt;
Wie bereits geschrieben, kann man die Topics recht frei einfach selbst erfinden. Sinnvoll ist es jedoch, jedem gewünschten Wert ein eigenes Topic zu spendieren.&lt;br /&gt;
&lt;br /&gt;
Ungünstig:&lt;br /&gt;
* zuHause/state/1_OG/Kueche &lt;br /&gt;
* =&amp;gt; In diesem Topic Licht, Temperatur, Luftfeuchte, Bewegungsmelder etc zu publishen ist eine nicht schlaue Idee; das Problem beginnt damit, dass man erst mal selber rausfinden muss, welchen Wert man gerade hat. Viel Programmcode für quasi umsonst; &amp;quot;on 20.3 66 motion&amp;quot; ist nun nicht wirklich toll.&lt;br /&gt;
&lt;br /&gt;
Besser:&lt;br /&gt;
* zuHause/state/1_OG/Kueche/Licht &lt;br /&gt;
* zuHause/state/1_OG/Kueche/Raumtemperatur &lt;br /&gt;
* zuHause/state/1_OG/Kueche/Luftfeuchte&lt;br /&gt;
* zuHause/state/1_OG/Kueche/Bewegungsmelder&lt;br /&gt;
=&amp;gt; Auf diese Weise weiß man vorher, welche (Zahlen)werte in einem Topic stehen und was sie bedeuten. Das hat man automatisch durch die geschickte Topic Wahl festgelegt.&lt;br /&gt;
&lt;br /&gt;
=== Filter ===&lt;br /&gt;
Eine witzige Sache von MQTT sind Filter. Das ist in etwa wie in FHEM eine readingsGroup für Arme. Wir möchten schnell einen Überblick haben, welchen Status bestimmte Devices haben.&lt;br /&gt;
&lt;br /&gt;
Es gibt zwei Arten von Filtern:&lt;br /&gt;
* Single Level Filter: +&lt;br /&gt;
* Multi Level Filter: #&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiele:&lt;br /&gt;
* zuHause/state/1_OG/Kueche/Temperatur&lt;br /&gt;
* zuHause/state/1_OG/Kueche/Kuehlschrank/Temperatur&lt;br /&gt;
* zuHause/state/1_OG/Kueche/Licht&lt;br /&gt;
* zuHause/state/1_OG/Wohnzimmer/Licht&lt;br /&gt;
* zuHause/state/1_OG/Schlafzimmer/Licht&lt;br /&gt;
&lt;br /&gt;
Jetzt filtern wir:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;#&amp;quot; =&amp;gt; muss immer der letzte Filter sein (es gibt Broker, die die # auch als Platzhalter innerhalb eines Topics erlauben, aber Standard ist das nicht)&lt;br /&gt;
&lt;br /&gt;
* zuHause/state/# =&amp;gt; gibt uns alle oben genannten Beispiel-Topics zurück&lt;br /&gt;
* zuHause/state/1_OG/+/Licht =&amp;gt; gibt uns das Licht der Küche, des Wohn- und des Schlafzimmers&lt;br /&gt;
* zuHause/state/1_OG/+/Temperatur =&amp;gt; gibt nur die Küchentemperatur (+ steht für genau 1 Topic, der Kühlschrank fällt also nicht in das Muster)&lt;br /&gt;
&lt;br /&gt;
=== Diskussionspunkt, Devicenamen ===&lt;br /&gt;
Manchmal liest man auch den Tip, eine eindeutige Gerätebezeichnung in das Topic mit aufzunehmen.&lt;br /&gt;
* Arduino_1/state/Zimmer_1/Licht&lt;br /&gt;
* Arduino_1/state/Zimmer_1/Temperatur&lt;br /&gt;
* Arduino_1/state/Zimmer_2/Licht&lt;br /&gt;
* Arduino_2/state/Zimmer_3/Licht&lt;br /&gt;
&lt;br /&gt;
Hat im wesentlichen folgenden Vorteil:&lt;br /&gt;
&lt;br /&gt;
Wenn ich mir nur ansehen will, was ein bestimmter Mikrocontroller published, kann ich ihn sehr einfach filtern.&lt;br /&gt;
* Arduino_1/# =&amp;gt; perfekt um alle Werte des Arduino_1 zu lesen und sonst nichts&lt;br /&gt;
&lt;br /&gt;
Nachteilig:&lt;br /&gt;
&lt;br /&gt;
Tauscht man später den Controller aus, muss man ihn wieder so nennen. Fasst man später Arduino_1 und Arduino_2 auf einem Arduino Mega zusammen, stimmen die Topics schlicht nicht mehr und man muss seine ganzen Devicenamen anpassen.&lt;br /&gt;
&lt;br /&gt;
== Der Artikel hast &amp;quot;Best Practices&amp;quot; versprochen - wo sind sie? ==&lt;br /&gt;
Schwierig. Was die Benennung der Topics betrifft, so vom Zeichensatz her, gibt es Regeln und best practices, die stehen oben.&lt;br /&gt;
&lt;br /&gt;
Ob man jetzt eindeutige Gerätenamen vorne weg schreibt, oder ob man state und set weiter vorne im Topic Tree unterbringt oder hinten, ich fürchte da gibt es keine allgemein gültigen Regeln. MQTT lässt einem hier alle Freiheiten.&lt;br /&gt;
&lt;br /&gt;
Das eine sieht eher nach FHEM aus (set und state am Ende), das andere lässt sich besser filtern.&lt;br /&gt;
Hardcoreuser könnten auch auf die Idee kommen, einfach beide Varianten gleichzeitig zu nutzen. Für FHEM alleine ist das sicherlich nicht hilfreich (aber auch nicht störend).&lt;br /&gt;
&lt;br /&gt;
== Schlusswort ==&lt;br /&gt;
Hier endet vorübergehend unser kleiner Exkurs zu MQTT.&lt;br /&gt;
&lt;br /&gt;
Wer Fragen der Anregungen hat, bitte im [https://forum.fhem.de/index.php/topic,69701.0.html Diskussionsthread dieses Artikels] stellen.&lt;br /&gt;
&lt;br /&gt;
Weiterhin haben wir ganz neu [https://forum.fhem.de/index.php/board,94.0.html einen eigenen Forumsbereich für MQTT].&lt;br /&gt;
&lt;br /&gt;
Je nachdem wie gut die Artikelserie ankommt, werde ich einen Teil 3 auflegen. Dieser ist dann zum &amp;quot;get your hands dirty&amp;quot;, zum Hände dreckig machen. Darin könnte ein kleiner Programmierkurs in der Arduino IDE kommen. Mir schwebt vor, einen kleinen Sketch zu nehmen, diesen mit MQTT auszurüsten und nach und nach die Dinge wie LWT, retained messages etc. einzubauen. Das ist im wesentlichen mit wenigen Änderungen möglich. Also durchaus anfängertauglich. &lt;br /&gt;
&lt;br /&gt;
Ich werde einen Arduino Uno oder Mega nehmen, sowie ein Ethernetshield mit W5100 Chip benutzen. Die Dinger kosten keine 6 € auf eBay. Die ENC28J60 (oder ähnliche) Chips werden explizit NICHT unterstützt werden! Wer lieber einen ESP8266 nimmt, der sei an dieser Stelle auf das Template von Pf@nne verwiesen [https://forum.fhem.de/index.php/topic,50238.0.html hier zu finden].&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung_Teil_2&amp;diff=21050</id>
		<title>MQTT Einführung Teil 2</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung_Teil_2&amp;diff=21050"/>
		<updated>2017-03-27T17:26:06Z</updated>

		<summary type="html">&lt;p&gt;Rince: /* Filter */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= MQTT Teil 2 =&lt;br /&gt;
Konzepte und best practices&lt;br /&gt;
&lt;br /&gt;
== Vorwort ==&lt;br /&gt;
Wer den Teil 1 noch nicht gelesen hat, ist herzlich eingeladen das vorher noch schnell zu machen :)&lt;br /&gt;
&lt;br /&gt;
[https://wiki.fhem.de/wiki/MQTT_Einf%C3%BChrung Hier ist Teil 1]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschreibt, etwas trocken, weiterführend Konzepte und Denkweisen des Übertragungsprotokolls MQTT. Es wird etwas technischer als die Einführung und der ein oder andere Vergleich zu anderen Protokollen wird auch gezogen. Vieles davon kann man auch so nachlesen, wenngleich nicht immer auf deutsch. Ich gehe davon aus, dass der Leser MQTT vornehmlich mit FHEM einsetzen will.&lt;br /&gt;
&lt;br /&gt;
Ein Beispielkurs ist in Planung. Dort werden wir die Konzepte praktisch kennen lernen.&lt;br /&gt;
&lt;br /&gt;
== Retained Messages ==&lt;br /&gt;
=== Szenario ===&lt;br /&gt;
Stellen wir uns vor, wir starten FHEM neu. Wer Homematic Devices kennt weiß, spätestens nach einem Blick ins Logfile, dass nun zunächst ein Statusrequest aller Geräte erfolgt. Schließlich konnte sich zwischen Beenden und Neustart von FHEM etwas geändert haben.&lt;br /&gt;
* Homematic&lt;br /&gt;
* Es wird jedes Gerät angesprochen und abgefragt: &lt;br /&gt;
* &amp;quot;Lieber Lichtschalter, was tust du grade?&amp;quot; &lt;br /&gt;
* &amp;quot;Ich lasse das Licht über dir leuchten mein User.&amp;quot;&lt;br /&gt;
MQTT hat hier ein anderes Konzept. Wenn in ein Topic gepostet wird, kann ein &amp;quot;retained Flag&amp;quot; gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
=== Das bedeutet ===&lt;br /&gt;
Die zuletzt gepostete Nachricht wird vom Broker nicht gelöscht. Publishen wir also den Status unseres Lichts:&lt;br /&gt;
* zuHause/1OG/Kueche/Licht/state &amp;quot;on&amp;quot; oder &amp;quot;off&amp;quot; + retained flag&lt;br /&gt;
Sobald wir dieses Topic auf einem Gerät subscriben, bekommen wir den Status angezeigt. Ein neu startendes FHEM ist so ein Fall.&lt;br /&gt;
&lt;br /&gt;
Was bei Homematic erst über einen (zugegeben automatisierten Request) abläuft, kann MQTT mit den retained Messages auch so.&lt;br /&gt;
&lt;br /&gt;
Trifft am Broker eine neue retained Message ein, so wird die alte Nachricht gelöscht. Zum absichtlichen Löschen einer retained Message, etwa weil man weiß, dass dieses Topic zukünftig nicht mehr benötigt wird, kann man eine leere Message posten.&lt;br /&gt;
&lt;br /&gt;
=== Fazit ===&lt;br /&gt;
Retained Messages sind gut, um jeweils die letzte aktuelle Statusmeldung zu erhalten. Was damit nicht geht, ist z.B. die letzten 30 Messungen eines Temperatursensors zu speichern und auszuliefern! Sobald eine retained Message überschrieben wird, ist der alte Wert futsch.&lt;br /&gt;
&lt;br /&gt;
== Last Will and Testament (LWT) ==&lt;br /&gt;
=== Szenario ===&lt;br /&gt;
Letzter Wille und Testament. &amp;lt;hr&amp;gt;&lt;br /&gt;
Unser batteriebetriebener Sensor hat keinen Strom mehr, das billige 5V Netzteil stellt seinen Dienst ein, ein netter Nachbar eröffnet ein neues WLAN Netz welches unser Bestehendes gnadenlos stört, unsere süßen kleinen Miezekatzen finden Patchkabel so spannend, dass sie es für erfolgreiche Beißübungen verwenden…&lt;br /&gt;
Gründe für einen Sensorausfall gibt es durchaus.&lt;br /&gt;
Was passiert in FHEM?&lt;br /&gt;
Der letzte Sensorwert bleibt im Reading stehen. Blöd wenn man erst abends feststellt, dass der Kühlschrank offen stand oder der Schaltbefehl zum Heizung einschalten nicht angekommen ist. Ersteres sorgt für aufgetautes Essen, letzteres für kalte Füße.&lt;br /&gt;
Wie fängt man das ab?&lt;br /&gt;
FHEM-seitig könnte man einen Watchdog oder ein DOIF einrichten. Es muss geprüft werden, ob sich das entsprechende Reading in einer bestimmten Zeit verändert hat. &amp;lt;hr&amp;gt;&lt;br /&gt;
Möglich.&lt;br /&gt;
&lt;br /&gt;
=== MQTT Lösung ===&lt;br /&gt;
Der Letzte Wille, das Testament (LWT)&lt;br /&gt;
&lt;br /&gt;
Beim Anmelden an einen Broker kann ein Last Will - Topic angegeben werden. Ebenso eine Payload. Wenn das Gerät verschwindet ohne sich sauber abgemeldet zu haben, wird der Broker die gewünschte Nachricht auf dem hinterlegten Topic publishen. Das retained Flag kann auch gesetzt werden.&lt;br /&gt;
Was bedeutet das für uns?&lt;br /&gt;
&lt;br /&gt;
Zusätzlich zu:&lt;br /&gt;
*zuHause/1_OG/Kueche/Licht/state&lt;br /&gt;
*zuHause/1_OG/Kueche/Licht/set&lt;br /&gt;
&lt;br /&gt;
könnten wir zusätzlich&lt;br /&gt;
* zuHause/1_OG/Kueche/Licht/status&lt;br /&gt;
definieren.&lt;br /&gt;
&lt;br /&gt;
Beim Anmelden an den Broker schicken wir (mit retained flag) ein &amp;quot;online&amp;quot;&lt;br /&gt;
Als LWT geben wir das gleiche Topic an, aber mit &amp;quot;offline&amp;quot; und retained flag. Meldet sich unser Device sauber ab (disconnect), wird das LWT nicht verwendet. Es dient nur dazu, einen Fehler deutlich zu machen.&lt;br /&gt;
&lt;br /&gt;
==== Vorsicht ====&lt;br /&gt;
LWT bezieht sich auf die Client ID. Was das schon wieder?&lt;br /&gt;
Jedes angemeldete Gerät hat eine einzige Client ID, unabhängig davon wie viele Topics es published und subscribed hat.&lt;br /&gt;
LWT auf ein Topic zu beziehen macht wenig Sinn, wenn es mehrere Topics auf dem Gerät gibt. Obiges Beispiel ist also gut, wenn an dem MC genau dieses eine Licht hängt!&lt;br /&gt;
* zuHause/1OG/Arduino_1&lt;br /&gt;
Ist der bessere Weg! Jetzt können wir in FHEM auf online / offline reagieren und den davon abhängigen Geräten eine Fehlerbehandlung spendieren. Da ist unser DOIF wieder :)&lt;br /&gt;
&lt;br /&gt;
==== Noch eine Falle ====&lt;br /&gt;
Wer denkt, er wirft alle Geräte in ein einziges retained last will Topic, sieht immer nur die letzte Meldung!&lt;br /&gt;
&lt;br /&gt;
Böse:&lt;br /&gt;
&lt;br /&gt;
zuHause/MQTT/Status (&amp;lt;= nicht nachmachen)&lt;br /&gt;
&lt;br /&gt;
=== Fazit ===&lt;br /&gt;
MQTT kann einen eleganten Weg bieten, über das Ende eines Gerätes zu informieren. Genau wie bei Homematic aber auch, muss man diese Meldungen auswerten um was sinnvolles damit anzufangen!&lt;br /&gt;
Im Fall eines einfachen Sensors ist es recht easy, bei einem Arduino Mega mit 30 Sensoren wird es dann aufwendig (außer man liest weiter bei den Filtern)&lt;br /&gt;
&lt;br /&gt;
== Organisation der Topics ==&lt;br /&gt;
=== Basics, erlaubte Zeichen ===&lt;br /&gt;
MQTT erlaubt prinzipiell den kompletten UTF8 Zeichensatz.&lt;br /&gt;
&lt;br /&gt;
Außer:&lt;br /&gt;
* U+0001..U+001F control characters&lt;br /&gt;
* U+007F..U+009F control characters&lt;br /&gt;
&lt;br /&gt;
Theoretisch gehen also Umlaute, Leerzeichen etc. Praktisch kann es passieren, dass ein Endgerät mit Umlauten einfach nix anfangen kann. Leerzeichen sind auch ein Problem, weil UTF 8 davon doch recht viele Möglichkeiten bietet. Ich würde daher empfehlen, Topicbezeichnungen eher wie Gerätenamen in FHEM zu betrachten: Unterstriche statt Leerzeichen, Umlaute ausschreiben (=&amp;gt; ü =&amp;gt; ue...)&lt;br /&gt;
&lt;br /&gt;
Groß- und Kleinschreibung muss beachtet werden. Ein Topic muss mindestens ein Zeichen haben, um gültig zu sein.&lt;br /&gt;
&lt;br /&gt;
Schlechte Beispiele:&lt;br /&gt;
*/zuHause/&lt;br /&gt;
nicht ganz falsch, aber der / am Anfang ist nur zusätzlicher Overhead, daher weglassen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*zuHause//1_OG&lt;br /&gt;
Hier wird ein leeres Topic definiert. Das ist ungültig.&lt;br /&gt;
&lt;br /&gt;
=== Basics, Strukturierung ===&lt;br /&gt;
MQTT kennt publishen und subscriben.&lt;br /&gt;
&lt;br /&gt;
FHEM kennt für jedes Gerät einen &amp;quot;state&amp;quot; und ein &amp;quot;set&amp;quot; Kommando. Das ist bei MQTT nicht nötig, aber durchaus sehr sinnvoll.&lt;br /&gt;
&lt;br /&gt;
Nehmen wir wieder unseren Lichtschalter: Ein Taster an einem Arduino mit einem Relais nebst Lampe daran.&lt;br /&gt;
&lt;br /&gt;
Unglücklich:&lt;br /&gt;
* zuHause/1_OG/Kueche/Lichtschalter&lt;br /&gt;
Wenn da ein &amp;quot;on&amp;quot; steht, woher will man wissen ob es sich um einen Befehl oder um eine Statusmeldung handelt? Daher bauen wir die FHEM übliche Logik einfach nach:&lt;br /&gt;
&lt;br /&gt;
Etwas glücklicher (kann man machen, sollte man aber nicht)&lt;br /&gt;
* zuHause/1_OG/Kueche/Lichtschalter/set&lt;br /&gt;
* zuHause/1_OG/Kueche/Lichtschalter/state&lt;br /&gt;
&lt;br /&gt;
Richtig schlau (warum, kommt bei den Filtern)&lt;br /&gt;
* set/zuHause/1_OG/Kueche/Lichtschalter&lt;br /&gt;
* state/zuHause/1_OG/Kueche/Lichtschalter/state&lt;br /&gt;
&lt;br /&gt;
Jetzt wird es einfach:&lt;br /&gt;
&lt;br /&gt;
auf dem set-Topic publishen wir immer Schaltbefehle. Mit oder ohne retained flag, darüber kann man streiten. Unser Arduino muss also dieses Topic abhören und auswerten.&lt;br /&gt;
&lt;br /&gt;
Das state-Topic nehmen wir um darauf zu publishen, wie der Zustand unserer Lampe gerade ist. Unser Arduino muss dieses Topic nur schreiben, niemals selber lesen.&lt;br /&gt;
&lt;br /&gt;
Damit haben wir eine saubere Trennung von Befehl und Status erreicht.&lt;br /&gt;
&lt;br /&gt;
=== Aufbau eines Topics ===&lt;br /&gt;
Wie bereits geschrieben, kann man die Topics recht frei einfach selbst erfinden. Sinnvoll ist es jedoch, jedem gewünschten Wert ein eigenes Topic zu spendieren.&lt;br /&gt;
&lt;br /&gt;
Ungünstig:&lt;br /&gt;
* zuHause/state/1_OG/Kueche &lt;br /&gt;
=&amp;gt; In diesem Topic Licht, Temperatur, Luftfeuchte, Bewegungsmelder etc zu publishen ist eine nicht schlaue Idee; das Problem beginnt damit, dass man erst mal selber rausfinden muss, welchen Wert man gerade hat. Viel Programmcode für quasi umsonst.&lt;br /&gt;
&lt;br /&gt;
Besser:&lt;br /&gt;
* zuHause/state/1_OG/Kueche/Licht &lt;br /&gt;
* zuHause/state/1_OG/Kueche/Raumtemperatur &lt;br /&gt;
* zuHause/state/1_OG/Kueche/Luftfeuchte&lt;br /&gt;
* zuHause/state/1_OG/Kueche/Bewegungsmelder&lt;br /&gt;
=&amp;gt; Auf diese Weise weiß man vorher, welche Zahlenwerte in einem Topic stehen und was sie bedeuten. Das hat man automatisch durch die geschickte Topic Wahl festgelegt.&lt;br /&gt;
&lt;br /&gt;
=== Filter ===&lt;br /&gt;
Eine witzige Sache von MQTT sind Filter. Das ist in etwa wie in FHEM eine readingsGroup für Arme. Wir möchten schnell einen Überblick haben, welchen Status bestimmte Devices haben.&lt;br /&gt;
&lt;br /&gt;
Es gibt zwei Arten von Filtern:&lt;br /&gt;
* Single Level Filter: +&lt;br /&gt;
* Multi Level Filter: #&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiele:&lt;br /&gt;
* zuHause/state/1_OG/Kueche/Temperatur&lt;br /&gt;
* zuHause/state/1_OG/Kueche/Kuehlschrank/Temperatur&lt;br /&gt;
* zuHause/state/1_OG/Kueche/Licht&lt;br /&gt;
* zuHause/state/1_OG/Wohnzimmer/Licht&lt;br /&gt;
* zuHause/state/1_OG/Schlafzimmer/Licht&lt;br /&gt;
&lt;br /&gt;
Jetzt filtern wir:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;#&amp;quot; =&amp;gt; muss immer der letzte Filter sein (es gibt Broker, die die # auch als Platzhalter innerhalb eines Topics erlauben, aber Standard ist das nicht)&lt;br /&gt;
&lt;br /&gt;
* zuHause/state/# =&amp;gt; gibt uns alle oben genannten Topics zurück&lt;br /&gt;
* zuHause/state/1_OG/+/Licht =&amp;gt; gibt uns das Licht der Küche, des Wohn- und des Schlafzimmers&lt;br /&gt;
* zuHause/state/1_OG/+/Temperatur =&amp;gt; gibt nur die Küchentemperatur (+ steht für genau 1 Topic)&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung_Teil_2&amp;diff=21049</id>
		<title>MQTT Einführung Teil 2</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung_Teil_2&amp;diff=21049"/>
		<updated>2017-03-27T16:11:47Z</updated>

		<summary type="html">&lt;p&gt;Rince: /* MQTT Teil 2 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= MQTT Teil 2 =&lt;br /&gt;
Konzepte und best practices&lt;br /&gt;
&lt;br /&gt;
== Vorwort ==&lt;br /&gt;
Wer den Teil 1 noch nicht gelesen hat, ist herzlich eingeladen das vorher noch schnell zu machen :)&lt;br /&gt;
&lt;br /&gt;
[https://wiki.fhem.de/wiki/MQTT_Einf%C3%BChrung Hier ist Teil 1]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschreibt, etwas trocken, weiterführend Konzepte und Denkweisen des Übertragungsprotokolls MQTT. Es wird etwas technischer als die Einführung und der ein oder andere Vergleich zu anderen Protokollen wird auch gezogen. Vieles davon kann man auch so nachlesen, wenngleich nicht immer auf deutsch. Ich gehe davon aus, dass der Leser MQTT vornehmlich mit FHEM einsetzen will.&lt;br /&gt;
&lt;br /&gt;
Ein Beispielkurs ist in Planung. Dort werden wir die Konzepte praktisch kennen lernen.&lt;br /&gt;
&lt;br /&gt;
== Retained Messages ==&lt;br /&gt;
=== Szenario ===&lt;br /&gt;
Stellen wir uns vor, wir starten FHEM neu. Wer Homematic Devices kennt weiß, spätestens nach einem Blick ins Logfile, dass nun zunächst ein Statusrequest aller Geräte erfolgt. Schließlich konnte sich zwischen Beenden und Neustart von FHEM etwas geändert haben.&lt;br /&gt;
* Homematic&lt;br /&gt;
* Es wird jedes Gerät angesprochen und abgefragt: &lt;br /&gt;
* &amp;quot;Lieber Lichtschalter, was tust du grade?&amp;quot; &lt;br /&gt;
* &amp;quot;Ich lasse das Licht über dir leuchten mein User.&amp;quot;&lt;br /&gt;
MQTT hat hier ein anderes Konzept. Wenn in ein Topic gepostet wird, kann ein &amp;quot;retained Flag&amp;quot; gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
=== Das bedeutet ===&lt;br /&gt;
Die zuletzt gepostete Nachricht wird vom Broker nicht gelöscht. Publishen wir also den Status unseres Lichts:&lt;br /&gt;
* zuHause/1OG/Kueche/Licht/state &amp;quot;on&amp;quot; oder &amp;quot;off&amp;quot; + retained flag&lt;br /&gt;
Sobald wir dieses Topic auf einem Gerät subscriben, bekommen wir den Status angezeigt. Ein neu startendes FHEM ist so ein Fall.&lt;br /&gt;
&lt;br /&gt;
Was bei Homematic erst über einen (zugegeben automatisierten Request) abläuft, kann MQTT mit den retained Messages auch so.&lt;br /&gt;
&lt;br /&gt;
Trifft am Broker eine neue retained Message ein, so wird die alte Nachricht gelöscht. Zum absichtlichen Löschen einer retained Message, etwa weil man weiß, dass dieses Topic zukünftig nicht mehr benötigt wird, kann man eine leere Message posten.&lt;br /&gt;
&lt;br /&gt;
=== Fazit ===&lt;br /&gt;
Retained Messages sind gut, um jeweils die letzte aktuelle Statusmeldung zu erhalten. Was damit nicht geht, ist z.B. die letzten 30 Messungen eines Temperatursensors zu speichern und auszuliefern! Sobald eine retained Message überschrieben wird, ist der alte Wert futsch.&lt;br /&gt;
&lt;br /&gt;
== Last Will and Testament (LWT) ==&lt;br /&gt;
=== Szenario ===&lt;br /&gt;
Letzter Wille und Testament. &amp;lt;hr&amp;gt;&lt;br /&gt;
Unser batteriebetriebener Sensor hat keinen Strom mehr, das billige 5V Netzteil stellt seinen Dienst ein, ein netter Nachbar eröffnet ein neues WLAN Netz welches unser Bestehendes gnadenlos stört, unsere süßen kleinen Miezekatzen finden Patchkabel so spannend, dass sie es für erfolgreiche Beißübungen verwenden…&lt;br /&gt;
Gründe für einen Sensorausfall gibt es durchaus.&lt;br /&gt;
Was passiert in FHEM?&lt;br /&gt;
Der letzte Sensorwert bleibt im Reading stehen. Blöd wenn man erst abends feststellt, dass der Kühlschrank offen stand oder der Schaltbefehl zum Heizung einschalten nicht angekommen ist. Ersteres sorgt für aufgetautes Essen, letzteres für kalte Füße.&lt;br /&gt;
Wie fängt man das ab?&lt;br /&gt;
FHEM-seitig könnte man einen Watchdog oder ein DOIF einrichten. Es muss geprüft werden, ob sich das entsprechende Reading in einer bestimmten Zeit verändert hat. &amp;lt;hr&amp;gt;&lt;br /&gt;
Möglich.&lt;br /&gt;
&lt;br /&gt;
=== MQTT Lösung ===&lt;br /&gt;
Der Letzte Wille, das Testament (LWT)&lt;br /&gt;
&lt;br /&gt;
Beim Anmelden an einen Broker kann ein Last Will - Topic angegeben werden. Ebenso eine Payload. Wenn das Gerät verschwindet ohne sich sauber abgemeldet zu haben, wird der Broker die gewünschte Nachricht auf dem hinterlegten Topic publishen. Das retained Flag kann auch gesetzt werden.&lt;br /&gt;
Was bedeutet das für uns?&lt;br /&gt;
&lt;br /&gt;
Zusätzlich zu:&lt;br /&gt;
*zuHause/1_OG/Kueche/Licht/state&lt;br /&gt;
*zuHause/1_OG/Kueche/Licht/set&lt;br /&gt;
&lt;br /&gt;
könnten wir zusätzlich&lt;br /&gt;
* zuHause/1_OG/Kueche/Licht/status&lt;br /&gt;
definieren.&lt;br /&gt;
&lt;br /&gt;
Beim Anmelden an den Broker schicken wir (mit retained flag) ein &amp;quot;online&amp;quot;&lt;br /&gt;
Als LWT geben wir das gleiche Topic an, aber mit &amp;quot;offline&amp;quot; und retained flag. Meldet sich unser Device sauber ab (disconnect), wird das LWT nicht verwendet. Es dient nur dazu, einen Fehler deutlich zu machen.&lt;br /&gt;
&lt;br /&gt;
==== Vorsicht ====&lt;br /&gt;
LWT bezieht sich auf die Client ID. Was das schon wieder?&lt;br /&gt;
Jedes angemeldete Gerät hat eine einzige Client ID, unabhängig davon wie viele Topics es published und subscribed hat.&lt;br /&gt;
LWT auf ein Topic zu beziehen macht wenig Sinn, wenn es mehrere Topics auf dem Gerät gibt. Obiges Beispiel ist also gut, wenn an dem MC genau dieses eine Licht hängt!&lt;br /&gt;
* zuHause/1OG/Arduino_1&lt;br /&gt;
Ist der bessere Weg! Jetzt können wir in FHEM auf online / offline reagieren und den davon abhängigen Geräten eine Fehlerbehandlung spendieren. Da ist unser DOIF wieder :)&lt;br /&gt;
&lt;br /&gt;
==== Noch eine Falle ====&lt;br /&gt;
Wer denkt, er wirft alle Geräte in ein einziges retained last will Topic, sieht immer nur die letzte Meldung!&lt;br /&gt;
&lt;br /&gt;
Böse:&lt;br /&gt;
&lt;br /&gt;
zuHause/MQTT/Status (&amp;lt;= nicht nachmachen)&lt;br /&gt;
&lt;br /&gt;
=== Fazit ===&lt;br /&gt;
MQTT kann einen eleganten Weg bieten, über das Ende eines Gerätes zu informieren. Genau wie bei Homematic aber auch, muss man diese Meldungen auswerten um was sinnvolles damit anzufangen!&lt;br /&gt;
Im Fall eines einfachen Sensors ist es recht easy, bei einem Arduino Mega mit 30 Sensoren wird es dann aufwendig (außer man liest weiter bei den Filtern)&lt;br /&gt;
&lt;br /&gt;
== Organisation der Topics ==&lt;br /&gt;
=== Basics, erlaubte Zeichen ===&lt;br /&gt;
MQTT erlaubt prinzipiell den kompletten UTF8 Zeichensatz.&lt;br /&gt;
&lt;br /&gt;
Außer:&lt;br /&gt;
* U+0001..U+001F control characters&lt;br /&gt;
* U+007F..U+009F control characters&lt;br /&gt;
&lt;br /&gt;
Theoretisch gehen also Umlaute, Leerzeichen etc. Praktisch kann es passieren, dass ein Endgerät mit Umlauten einfach nix anfangen kann. Leerzeichen sind auch ein Problem, weil UTF 8 davon doch recht viele Möglichkeiten bietet. Ich würde daher empfehlen, Topicbezeichnungen eher wie Gerätenamen in FHEM zu betrachten: Unterstriche statt Leerzeichen, Umlaute ausschreiben (=&amp;gt; ü =&amp;gt; ue...)&lt;br /&gt;
&lt;br /&gt;
Groß- und Kleinschreibung muss beachtet werden. Ein Topic muss mindestens ein Zeichen haben, um gültig zu sein.&lt;br /&gt;
&lt;br /&gt;
Schlechte Beispiele:&lt;br /&gt;
*/zuHause/&lt;br /&gt;
nicht ganz falsch, aber der / am Anfang ist nur zusätzlicher Overhead, daher weglassen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*zuHause//1_OG&lt;br /&gt;
Hier wird ein leeres Topic definiert. Das ist ungültig.&lt;br /&gt;
&lt;br /&gt;
=== Basics, Strukturierung ===&lt;br /&gt;
MQTT kennt publishen und subscriben.&lt;br /&gt;
&lt;br /&gt;
FHEM kennt für jedes Gerät einen &amp;quot;state&amp;quot; und ein &amp;quot;set&amp;quot; Kommando. Das ist bei MQTT nicht nötig, aber durchaus sehr sinnvoll.&lt;br /&gt;
&lt;br /&gt;
Nehmen wir wieder unseren Lichtschalter: Ein Taster an einem Arduino mit einem Relais nebst Lampe daran.&lt;br /&gt;
&lt;br /&gt;
Unglücklich:&lt;br /&gt;
* zuHause/1_OG/Kueche/Lichtschalter&lt;br /&gt;
Wenn da ein &amp;quot;on&amp;quot; steht, woher will man wissen ob es sich um einen Befehl oder um eine Statusmeldung handelt? Daher bauen wir die FHEM übliche Logik einfach nach:&lt;br /&gt;
&lt;br /&gt;
Etwas glücklicher (kann man machen, sollte man aber nicht)&lt;br /&gt;
* zuHause/1_OG/Kueche/Lichtschalter/set&lt;br /&gt;
* zuHause/1_OG/Kueche/Lichtschalter/state&lt;br /&gt;
&lt;br /&gt;
Richtig schlau (warum, kommt bei den Filtern)&lt;br /&gt;
* set/zuHause/1_OG/Kueche/Lichtschalter&lt;br /&gt;
* state/zuHause/1_OG/Kueche/Lichtschalter/state&lt;br /&gt;
&lt;br /&gt;
Jetzt wird es einfach:&lt;br /&gt;
&lt;br /&gt;
auf dem set-Topic publishen wir immer Schaltbefehle. Mit oder ohne retained flag, darüber kann man streiten. Unser Arduino muss also dieses Topic abhören und auswerten.&lt;br /&gt;
&lt;br /&gt;
Das state-Topic nehmen wir um darauf zu publishen, wie der Zustand unserer Lampe gerade ist. Unser Arduino muss dieses Topic nur schreiben, niemals selber lesen.&lt;br /&gt;
&lt;br /&gt;
Damit haben wir eine saubere Trennung von Befehl und Status erreicht.&lt;br /&gt;
&lt;br /&gt;
=== Aufbau eines Topics ===&lt;br /&gt;
Wie bereits geschrieben, kann man die Topics recht frei einfach selbst erfinden. Sinnvoll ist es jedoch, jedem gewünschten Wert ein eigenes Topic zu spendieren.&lt;br /&gt;
&lt;br /&gt;
Ungünstig:&lt;br /&gt;
* zuHause/state/1_OG/Kueche &lt;br /&gt;
=&amp;gt; In diesem Topic Licht, Temperatur, Luftfeuchte, Bewegungsmelder etc zu publishen ist eine nicht schlaue Idee; das Problem beginnt damit, dass man erst mal selber rausfinden muss, welchen Wert man gerade hat. Viel Programmcode für quasi umsonst.&lt;br /&gt;
&lt;br /&gt;
Besser:&lt;br /&gt;
* zuHause/state/1_OG/Kueche/Licht &lt;br /&gt;
* zuHause/state/1_OG/Kueche/Raumtemperatur &lt;br /&gt;
* zuHause/state/1_OG/Kueche/Luftfeuchte&lt;br /&gt;
* zuHause/state/1_OG/Kueche/Bewegungsmelder&lt;br /&gt;
=&amp;gt; Auf diese Weise weiß man vorher, welche Zahlenwerte in einem Topic stehen und was sie bedeuten. Das hat man automatisch durch die geschickte Topic Wahl festgelegt.&lt;br /&gt;
&lt;br /&gt;
=== Filter ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
AB HIER NOCH NICHT FERTIG&lt;br /&gt;
&lt;br /&gt;
Eine witzige Sache von MQTT sind Filter. Das ist in etwa wie in FHEM eine readingsGroup für Arme. &lt;br /&gt;
&lt;br /&gt;
Es gibt zwei Arten von Filtern:&lt;br /&gt;
* Single Level Filter: +&lt;br /&gt;
* Multi Level Filter: #&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiele:&lt;br /&gt;
* zuHause/state/1_OG/Kueche/Temperatur&lt;br /&gt;
* zuHause/state/1_OG/Kueche/Kuehlschrank/Temperatur&lt;br /&gt;
* zuHause/state/1_OG/Kueche/Licht&lt;br /&gt;
* zuHause/state/1_OG/Wohnzimmer/Licht&lt;br /&gt;
* zuHause/state/1_OG/Schlafzimmer/Licht&lt;br /&gt;
&lt;br /&gt;
Jetzt filtern wir:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;#&amp;quot; =&amp;gt; muss immer der letzte Filter sein&lt;br /&gt;
&lt;br /&gt;
* zuHause/state/# gibt uns alle oben genannten Topics zurück&lt;br /&gt;
* zuHause/state/1_OG/+/Licht&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung_Teil_2&amp;diff=21048</id>
		<title>MQTT Einführung Teil 2</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung_Teil_2&amp;diff=21048"/>
		<updated>2017-03-27T16:08:24Z</updated>

		<summary type="html">&lt;p&gt;Rince: /* Basics, erlaubte Zeichen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= MQTT Teil 2 =&lt;br /&gt;
Konzepte und best practices&lt;br /&gt;
&lt;br /&gt;
== Vorwort ==&lt;br /&gt;
Dieser Artikel beschreibt, etwas trocken, weiterführend Konzepte und Denkweisen des Übertragungsprotokolls MQTT. Es wird etwas technischer als die Einführung und der ein oder andere Vergleich zu anderen Protokollen wird auch gezogen. Vieles davon kann man auch so nachlesen, wenngleich nicht immer auf deutsch. Ich gehe davon aus, dass der Leser MQTT vornehmlich mit FHEM einsetzen will.&lt;br /&gt;
&lt;br /&gt;
Ein Beispielkurs ist in Planung. Dort werden wir die Konzepte praktisch kennen lernen.&lt;br /&gt;
&lt;br /&gt;
== Retained Messages ==&lt;br /&gt;
=== Szenario ===&lt;br /&gt;
Stellen wir uns vor, wir starten FHEM neu. Wer Homematic Devices kennt weiß, spätestens nach einem Blick ins Logfile, dass nun zunächst ein Statusrequest aller Geräte erfolgt. Schließlich konnte sich zwischen Beenden und Neustart von FHEM etwas geändert haben.&lt;br /&gt;
* Homematic&lt;br /&gt;
* Es wird jedes Gerät angesprochen und abgefragt: &lt;br /&gt;
* &amp;quot;Lieber Lichtschalter, was tust du grade?&amp;quot; &lt;br /&gt;
* &amp;quot;Ich lasse das Licht über dir leuchten mein User.&amp;quot;&lt;br /&gt;
MQTT hat hier ein anderes Konzept. Wenn in ein Topic gepostet wird, kann ein &amp;quot;retained Flag&amp;quot; gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
=== Das bedeutet ===&lt;br /&gt;
Die zuletzt gepostete Nachricht wird vom Broker nicht gelöscht. Publishen wir also den Status unseres Lichts:&lt;br /&gt;
* zuHause/1OG/Kueche/Licht/state &amp;quot;on&amp;quot; oder &amp;quot;off&amp;quot; + retained flag&lt;br /&gt;
Sobald wir dieses Topic auf einem Gerät subscriben, bekommen wir den Status angezeigt. Ein neu startendes FHEM ist so ein Fall.&lt;br /&gt;
&lt;br /&gt;
Was bei Homematic erst über einen (zugegeben automatisierten Request) abläuft, kann MQTT mit den retained Messages auch so.&lt;br /&gt;
&lt;br /&gt;
Trifft am Broker eine neue retained Message ein, so wird die alte Nachricht gelöscht. Zum absichtlichen Löschen einer retained Message, etwa weil man weiß, dass dieses Topic zukünftig nicht mehr benötigt wird, kann man eine leere Message posten.&lt;br /&gt;
&lt;br /&gt;
=== Fazit ===&lt;br /&gt;
Retained Messages sind gut, um jeweils die letzte aktuelle Statusmeldung zu erhalten. Was damit nicht geht, ist z.B. die letzten 30 Messungen eines Temperatursensors zu speichern und auszuliefern! Sobald eine retained Message überschrieben wird, ist der alte Wert futsch.&lt;br /&gt;
&lt;br /&gt;
== Last Will and Testament (LWT) ==&lt;br /&gt;
=== Szenario ===&lt;br /&gt;
Letzter Wille und Testament. &amp;lt;hr&amp;gt;&lt;br /&gt;
Unser batteriebetriebener Sensor hat keinen Strom mehr, das billige 5V Netzteil stellt seinen Dienst ein, ein netter Nachbar eröffnet ein neues WLAN Netz welches unser Bestehendes gnadenlos stört, unsere süßen kleinen Miezekatzen finden Patchkabel so spannend, dass sie es für erfolgreiche Beißübungen verwenden…&lt;br /&gt;
Gründe für einen Sensorausfall gibt es durchaus.&lt;br /&gt;
Was passiert in FHEM?&lt;br /&gt;
Der letzte Sensorwert bleibt im Reading stehen. Blöd wenn man erst abends feststellt, dass der Kühlschrank offen stand oder der Schaltbefehl zum Heizung einschalten nicht angekommen ist. Ersteres sorgt für aufgetautes Essen, letzteres für kalte Füße.&lt;br /&gt;
Wie fängt man das ab?&lt;br /&gt;
FHEM-seitig könnte man einen Watchdog oder ein DOIF einrichten. Es muss geprüft werden, ob sich das entsprechende Reading in einer bestimmten Zeit verändert hat. &amp;lt;hr&amp;gt;&lt;br /&gt;
Möglich.&lt;br /&gt;
&lt;br /&gt;
=== MQTT Lösung ===&lt;br /&gt;
Der Letzte Wille, das Testament (LWT)&lt;br /&gt;
&lt;br /&gt;
Beim Anmelden an einen Broker kann ein Last Will - Topic angegeben werden. Ebenso eine Payload. Wenn das Gerät verschwindet ohne sich sauber abgemeldet zu haben, wird der Broker die gewünschte Nachricht auf dem hinterlegten Topic publishen. Das retained Flag kann auch gesetzt werden.&lt;br /&gt;
Was bedeutet das für uns?&lt;br /&gt;
&lt;br /&gt;
Zusätzlich zu:&lt;br /&gt;
*zuHause/1_OG/Kueche/Licht/state&lt;br /&gt;
*zuHause/1_OG/Kueche/Licht/set&lt;br /&gt;
&lt;br /&gt;
könnten wir zusätzlich&lt;br /&gt;
* zuHause/1_OG/Kueche/Licht/status&lt;br /&gt;
definieren.&lt;br /&gt;
&lt;br /&gt;
Beim Anmelden an den Broker schicken wir (mit retained flag) ein &amp;quot;online&amp;quot;&lt;br /&gt;
Als LWT geben wir das gleiche Topic an, aber mit &amp;quot;offline&amp;quot; und retained flag. Meldet sich unser Device sauber ab (disconnect), wird das LWT nicht verwendet. Es dient nur dazu, einen Fehler deutlich zu machen.&lt;br /&gt;
&lt;br /&gt;
==== Vorsicht ====&lt;br /&gt;
LWT bezieht sich auf die Client ID. Was das schon wieder?&lt;br /&gt;
Jedes angemeldete Gerät hat eine einzige Client ID, unabhängig davon wie viele Topics es published und subscribed hat.&lt;br /&gt;
LWT auf ein Topic zu beziehen macht wenig Sinn, wenn es mehrere Topics auf dem Gerät gibt. Obiges Beispiel ist also gut, wenn an dem MC genau dieses eine Licht hängt!&lt;br /&gt;
* zuHause/1OG/Arduino_1&lt;br /&gt;
Ist der bessere Weg! Jetzt können wir in FHEM auf online / offline reagieren und den davon abhängigen Geräten eine Fehlerbehandlung spendieren. Da ist unser DOIF wieder :)&lt;br /&gt;
&lt;br /&gt;
==== Noch eine Falle ====&lt;br /&gt;
Wer denkt, er wirft alle Geräte in ein einziges retained last will Topic, sieht immer nur die letzte Meldung!&lt;br /&gt;
&lt;br /&gt;
Böse:&lt;br /&gt;
&lt;br /&gt;
zuHause/MQTT/Status (&amp;lt;= nicht nachmachen)&lt;br /&gt;
&lt;br /&gt;
=== Fazit ===&lt;br /&gt;
MQTT kann einen eleganten Weg bieten, über das Ende eines Gerätes zu informieren. Genau wie bei Homematic aber auch, muss man diese Meldungen auswerten um was sinnvolles damit anzufangen!&lt;br /&gt;
Im Fall eines einfachen Sensors ist es recht easy, bei einem Arduino Mega mit 30 Sensoren wird es dann aufwendig (außer man liest weiter bei den Filtern)&lt;br /&gt;
&lt;br /&gt;
== Organisation der Topics ==&lt;br /&gt;
=== Basics, erlaubte Zeichen ===&lt;br /&gt;
MQTT erlaubt prinzipiell den kompletten UTF8 Zeichensatz.&lt;br /&gt;
&lt;br /&gt;
Außer:&lt;br /&gt;
* U+0001..U+001F control characters&lt;br /&gt;
* U+007F..U+009F control characters&lt;br /&gt;
&lt;br /&gt;
Theoretisch gehen also Umlaute, Leerzeichen etc. Praktisch kann es passieren, dass ein Endgerät mit Umlauten einfach nix anfangen kann. Leerzeichen sind auch ein Problem, weil UTF 8 davon doch recht viele Möglichkeiten bietet. Ich würde daher empfehlen, Topicbezeichnungen eher wie Gerätenamen in FHEM zu betrachten: Unterstriche statt Leerzeichen, Umlaute ausschreiben (=&amp;gt; ü =&amp;gt; ue...)&lt;br /&gt;
&lt;br /&gt;
Groß- und Kleinschreibung muss beachtet werden. Ein Topic muss mindestens ein Zeichen haben, um gültig zu sein.&lt;br /&gt;
&lt;br /&gt;
Schlechte Beispiele:&lt;br /&gt;
*/zuHause/&lt;br /&gt;
nicht ganz falsch, aber der / am Anfang ist nur zusätzlicher Overhead, daher weglassen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*zuHause//1_OG&lt;br /&gt;
Hier wird ein leeres Topic definiert. Das ist ungültig.&lt;br /&gt;
&lt;br /&gt;
=== Basics, Strukturierung ===&lt;br /&gt;
MQTT kennt publishen und subscriben.&lt;br /&gt;
&lt;br /&gt;
FHEM kennt für jedes Gerät einen &amp;quot;state&amp;quot; und ein &amp;quot;set&amp;quot; Kommando. Das ist bei MQTT nicht nötig, aber durchaus sehr sinnvoll.&lt;br /&gt;
&lt;br /&gt;
Nehmen wir wieder unseren Lichtschalter: Ein Taster an einem Arduino mit einem Relais nebst Lampe daran.&lt;br /&gt;
&lt;br /&gt;
Unglücklich:&lt;br /&gt;
* zuHause/1_OG/Kueche/Lichtschalter&lt;br /&gt;
Wenn da ein &amp;quot;on&amp;quot; steht, woher will man wissen ob es sich um einen Befehl oder um eine Statusmeldung handelt? Daher bauen wir die FHEM übliche Logik einfach nach:&lt;br /&gt;
&lt;br /&gt;
Etwas glücklicher (kann man machen, sollte man aber nicht)&lt;br /&gt;
* zuHause/1_OG/Kueche/Lichtschalter/set&lt;br /&gt;
* zuHause/1_OG/Kueche/Lichtschalter/state&lt;br /&gt;
&lt;br /&gt;
Richtig schlau (warum, kommt bei den Filtern)&lt;br /&gt;
* set/zuHause/1_OG/Kueche/Lichtschalter&lt;br /&gt;
* state/zuHause/1_OG/Kueche/Lichtschalter/state&lt;br /&gt;
&lt;br /&gt;
Jetzt wird es einfach:&lt;br /&gt;
&lt;br /&gt;
auf dem set-Topic publishen wir immer Schaltbefehle. Mit oder ohne retained flag, darüber kann man streiten. Unser Arduino muss also dieses Topic abhören und auswerten.&lt;br /&gt;
&lt;br /&gt;
Das state-Topic nehmen wir um darauf zu publishen, wie der Zustand unserer Lampe gerade ist. Unser Arduino muss dieses Topic nur schreiben, niemals selber lesen.&lt;br /&gt;
&lt;br /&gt;
Damit haben wir eine saubere Trennung von Befehl und Status erreicht.&lt;br /&gt;
&lt;br /&gt;
=== Aufbau eines Topics ===&lt;br /&gt;
Wie bereits geschrieben, kann man die Topics recht frei einfach selbst erfinden. Sinnvoll ist es jedoch, jedem gewünschten Wert ein eigenes Topic zu spendieren.&lt;br /&gt;
&lt;br /&gt;
Ungünstig:&lt;br /&gt;
* zuHause/state/1_OG/Kueche &lt;br /&gt;
=&amp;gt; In diesem Topic Licht, Temperatur, Luftfeuchte, Bewegungsmelder etc zu publishen ist eine nicht schlaue Idee; das Problem beginnt damit, dass man erst mal selber rausfinden muss, welchen Wert man gerade hat. Viel Programmcode für quasi umsonst.&lt;br /&gt;
&lt;br /&gt;
Besser:&lt;br /&gt;
* zuHause/state/1_OG/Kueche/Licht &lt;br /&gt;
* zuHause/state/1_OG/Kueche/Raumtemperatur &lt;br /&gt;
* zuHause/state/1_OG/Kueche/Luftfeuchte&lt;br /&gt;
* zuHause/state/1_OG/Kueche/Bewegungsmelder&lt;br /&gt;
=&amp;gt; Auf diese Weise weiß man vorher, welche Zahlenwerte in einem Topic stehen und was sie bedeuten. Das hat man automatisch durch die geschickte Topic Wahl festgelegt.&lt;br /&gt;
&lt;br /&gt;
=== Filter ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
AB HIER NOCH NICHT FERTIG&lt;br /&gt;
&lt;br /&gt;
Eine witzige Sache von MQTT sind Filter. Das ist in etwa wie in FHEM eine readingsGroup für Arme. &lt;br /&gt;
&lt;br /&gt;
Es gibt zwei Arten von Filtern:&lt;br /&gt;
* Single Level Filter: +&lt;br /&gt;
* Multi Level Filter: #&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiele:&lt;br /&gt;
* zuHause/state/1_OG/Kueche/Temperatur&lt;br /&gt;
* zuHause/state/1_OG/Kueche/Kuehlschrank/Temperatur&lt;br /&gt;
* zuHause/state/1_OG/Kueche/Licht&lt;br /&gt;
* zuHause/state/1_OG/Wohnzimmer/Licht&lt;br /&gt;
* zuHause/state/1_OG/Schlafzimmer/Licht&lt;br /&gt;
&lt;br /&gt;
Jetzt filtern wir:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;#&amp;quot; =&amp;gt; muss immer der letzte Filter sein&lt;br /&gt;
&lt;br /&gt;
* zuHause/state/# gibt uns alle oben genannten Topics zurück&lt;br /&gt;
* zuHause/state/1_OG/+/Licht&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung_Teil_2&amp;diff=21047</id>
		<title>MQTT Einführung Teil 2</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung_Teil_2&amp;diff=21047"/>
		<updated>2017-03-27T10:30:22Z</updated>

		<summary type="html">&lt;p&gt;Rince: /* Filter */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= MQTT Teil 2 =&lt;br /&gt;
Konzepte und best practices&lt;br /&gt;
&lt;br /&gt;
== Vorwort ==&lt;br /&gt;
Dieser Artikel beschreibt, etwas trocken, weiterführend Konzepte und Denkweisen des Übertragungsprotokolls MQTT. Es wird etwas technischer als die Einführung und der ein oder andere Vergleich zu anderen Protokollen wird auch gezogen. Vieles davon kann man auch so nachlesen, wenngleich nicht immer auf deutsch. Ich gehe davon aus, dass der Leser MQTT vornehmlich mit FHEM einsetzen will.&lt;br /&gt;
&lt;br /&gt;
Ein Beispielkurs ist in Planung. Dort werden wir die Konzepte praktisch kennen lernen.&lt;br /&gt;
&lt;br /&gt;
== Retained Messages ==&lt;br /&gt;
=== Szenario ===&lt;br /&gt;
Stellen wir uns vor, wir starten FHEM neu. Wer Homematic Devices kennt weiß, spätestens nach einem Blick ins Logfile, dass nun zunächst ein Statusrequest aller Geräte erfolgt. Schließlich konnte sich zwischen Beenden und Neustart von FHEM etwas geändert haben.&lt;br /&gt;
* Homematic&lt;br /&gt;
* Es wird jedes Gerät angesprochen und abgefragt: &lt;br /&gt;
* &amp;quot;Lieber Lichtschalter, was tust du grade?&amp;quot; &lt;br /&gt;
* &amp;quot;Ich lasse das Licht über dir leuchten mein User.&amp;quot;&lt;br /&gt;
MQTT hat hier ein anderes Konzept. Wenn in ein Topic gepostet wird, kann ein &amp;quot;retained Flag&amp;quot; gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
=== Das bedeutet ===&lt;br /&gt;
Die zuletzt gepostete Nachricht wird vom Broker nicht gelöscht. Publishen wir also den Status unseres Lichts:&lt;br /&gt;
* zuHause/1OG/Kueche/Licht/state &amp;quot;on&amp;quot; oder &amp;quot;off&amp;quot; + retained flag&lt;br /&gt;
Sobald wir dieses Topic auf einem Gerät subscriben, bekommen wir den Status angezeigt. Ein neu startendes FHEM ist so ein Fall.&lt;br /&gt;
&lt;br /&gt;
Was bei Homematic erst über einen (zugegeben automatisierten Request) abläuft, kann MQTT mit den retained Messages auch so.&lt;br /&gt;
&lt;br /&gt;
Trifft am Broker eine neue retained Message ein, so wird die alte Nachricht gelöscht. Zum absichtlichen Löschen einer retained Message, etwa weil man weiß, dass dieses Topic zukünftig nicht mehr benötigt wird, kann man eine leere Message posten.&lt;br /&gt;
&lt;br /&gt;
=== Fazit ===&lt;br /&gt;
Retained Messages sind gut, um jeweils die letzte aktuelle Statusmeldung zu erhalten. Was damit nicht geht, ist z.B. die letzten 30 Messungen eines Temperatursensors zu speichern und auszuliefern! Sobald eine retained Message überschrieben wird, ist der alte Wert futsch.&lt;br /&gt;
&lt;br /&gt;
== Last Will and Testament (LWT) ==&lt;br /&gt;
=== Szenario ===&lt;br /&gt;
Letzter Wille und Testament. &amp;lt;hr&amp;gt;&lt;br /&gt;
Unser batteriebetriebener Sensor hat keinen Strom mehr, das billige 5V Netzteil stellt seinen Dienst ein, ein netter Nachbar eröffnet ein neues WLAN Netz welches unser Bestehendes gnadenlos stört, unsere süßen kleinen Miezekatzen finden Patchkabel so spannend, dass sie es für erfolgreiche Beißübungen verwenden…&lt;br /&gt;
Gründe für einen Sensorausfall gibt es durchaus.&lt;br /&gt;
Was passiert in FHEM?&lt;br /&gt;
Der letzte Sensorwert bleibt im Reading stehen. Blöd wenn man erst abends feststellt, dass der Kühlschrank offen stand oder der Schaltbefehl zum Heizung einschalten nicht angekommen ist. Ersteres sorgt für aufgetautes Essen, letzteres für kalte Füße.&lt;br /&gt;
Wie fängt man das ab?&lt;br /&gt;
FHEM-seitig könnte man einen Watchdog oder ein DOIF einrichten. Es muss geprüft werden, ob sich das entsprechende Reading in einer bestimmten Zeit verändert hat. &amp;lt;hr&amp;gt;&lt;br /&gt;
Möglich.&lt;br /&gt;
&lt;br /&gt;
=== MQTT Lösung ===&lt;br /&gt;
Der Letzte Wille, das Testament (LWT)&lt;br /&gt;
&lt;br /&gt;
Beim Anmelden an einen Broker kann ein Last Will - Topic angegeben werden. Ebenso eine Payload. Wenn das Gerät verschwindet ohne sich sauber abgemeldet zu haben, wird der Broker die gewünschte Nachricht auf dem hinterlegten Topic publishen. Das retained Flag kann auch gesetzt werden.&lt;br /&gt;
Was bedeutet das für uns?&lt;br /&gt;
&lt;br /&gt;
Zusätzlich zu:&lt;br /&gt;
*zuHause/1_OG/Kueche/Licht/state&lt;br /&gt;
*zuHause/1_OG/Kueche/Licht/set&lt;br /&gt;
&lt;br /&gt;
könnten wir zusätzlich&lt;br /&gt;
* zuHause/1_OG/Kueche/Licht/status&lt;br /&gt;
definieren.&lt;br /&gt;
&lt;br /&gt;
Beim Anmelden an den Broker schicken wir (mit retained flag) ein &amp;quot;online&amp;quot;&lt;br /&gt;
Als LWT geben wir das gleiche Topic an, aber mit &amp;quot;offline&amp;quot; und retained flag. Meldet sich unser Device sauber ab (disconnect), wird das LWT nicht verwendet. Es dient nur dazu, einen Fehler deutlich zu machen.&lt;br /&gt;
&lt;br /&gt;
==== Vorsicht ====&lt;br /&gt;
LWT bezieht sich auf die Client ID. Was das schon wieder?&lt;br /&gt;
Jedes angemeldete Gerät hat eine einzige Client ID, unabhängig davon wie viele Topics es published und subscribed hat.&lt;br /&gt;
LWT auf ein Topic zu beziehen macht wenig Sinn, wenn es mehrere Topics auf dem Gerät gibt. Obiges Beispiel ist also gut, wenn an dem MC genau dieses eine Licht hängt!&lt;br /&gt;
* zuHause/1OG/Arduino_1&lt;br /&gt;
Ist der bessere Weg! Jetzt können wir in FHEM auf online / offline reagieren und den davon abhängigen Geräten eine Fehlerbehandlung spendieren. Da ist unser DOIF wieder :)&lt;br /&gt;
&lt;br /&gt;
==== Noch eine Falle ====&lt;br /&gt;
Wer denkt, er wirft alle Geräte in ein einziges retained last will Topic, sieht immer nur die letzte Meldung!&lt;br /&gt;
&lt;br /&gt;
Böse:&lt;br /&gt;
&lt;br /&gt;
zuHause/MQTT/Status (&amp;lt;= nicht nachmachen)&lt;br /&gt;
&lt;br /&gt;
=== Fazit ===&lt;br /&gt;
MQTT kann einen eleganten Weg bieten, über das Ende eines Gerätes zu informieren. Genau wie bei Homematic aber auch, muss man diese Meldungen auswerten um was sinnvolles damit anzufangen!&lt;br /&gt;
Im Fall eines einfachen Sensors ist es recht easy, bei einem Arduino Mega mit 30 Sensoren wird es dann aufwendig (außer man liest weiter bei den Filtern)&lt;br /&gt;
&lt;br /&gt;
== Organisation der Topics ==&lt;br /&gt;
=== Basics, erlaubte Zeichen ===&lt;br /&gt;
MQTT erlaubt prinzipiell den kompletten UTF8 Zeichensatz.&lt;br /&gt;
&lt;br /&gt;
Außer:&lt;br /&gt;
* U+0001..U+001F control characters&lt;br /&gt;
* U+007F..U+009F control characters&lt;br /&gt;
&lt;br /&gt;
Theoretisch gehen also Umlaute, Leerzeichen etc. Praktisch kann es passieren, dass ein Endgerät mit Umlauten einfach nix anfangen kann. Leerzeichen sind auch ein Problem, weil UTF 8 davon doch recht viele Möglichkeiten bietet. Ich würde daher empfehlen, Topicbezeichnungen eher wie Gerätenamen in FHEM zu betrachten: Unterstriche statt Leerzeichen, Umlaute ausschreiben (=&amp;gt; ü =&amp;gt; ue...)&lt;br /&gt;
&lt;br /&gt;
Groß- und Kleinschreibung muss beachtet werden. Ein Topic muss mindestens ein Zeichen haben, um gültig zu sein.&lt;br /&gt;
&lt;br /&gt;
Falsch:&lt;br /&gt;
*/zuHause/&lt;br /&gt;
nicht ganz falsch, aber der / am Anfang ist nur zusätzlicher Overhead, daher weglassen&lt;br /&gt;
*zuHause//1_OG&lt;br /&gt;
Hier wird ein leeres Topic definiert. Das ist ungültig.&lt;br /&gt;
&lt;br /&gt;
=== Basics, Strukturierung ===&lt;br /&gt;
MQTT kennt publishen und subscriben.&lt;br /&gt;
&lt;br /&gt;
FHEM kennt für jedes Gerät einen &amp;quot;state&amp;quot; und ein &amp;quot;set&amp;quot; Kommando. Das ist bei MQTT nicht nötig, aber durchaus sehr sinnvoll.&lt;br /&gt;
&lt;br /&gt;
Nehmen wir wieder unseren Lichtschalter: Ein Taster an einem Arduino mit einem Relais nebst Lampe daran.&lt;br /&gt;
&lt;br /&gt;
Unglücklich:&lt;br /&gt;
* zuHause/1_OG/Kueche/Lichtschalter&lt;br /&gt;
Wenn da ein &amp;quot;on&amp;quot; steht, woher will man wissen ob es sich um einen Befehl oder um eine Statusmeldung handelt? Daher bauen wir die FHEM übliche Logik einfach nach:&lt;br /&gt;
&lt;br /&gt;
Etwas glücklicher (kann man machen, sollte man aber nicht)&lt;br /&gt;
* zuHause/1_OG/Kueche/Lichtschalter/set&lt;br /&gt;
* zuHause/1_OG/Kueche/Lichtschalter/state&lt;br /&gt;
&lt;br /&gt;
Richtig schlau (warum, kommt bei den Filtern)&lt;br /&gt;
* set/zuHause/1_OG/Kueche/Lichtschalter&lt;br /&gt;
* state/zuHause/1_OG/Kueche/Lichtschalter/state&lt;br /&gt;
&lt;br /&gt;
Jetzt wird es einfach:&lt;br /&gt;
&lt;br /&gt;
auf dem set-Topic publishen wir immer Schaltbefehle. Mit oder ohne retained flag, darüber kann man streiten. Unser Arduino muss also dieses Topic abhören und auswerten.&lt;br /&gt;
&lt;br /&gt;
Das state-Topic nehmen wir um darauf zu publishen, wie der Zustand unserer Lampe gerade ist. Unser Arduino muss dieses Topic nur schreiben, niemals selber lesen.&lt;br /&gt;
&lt;br /&gt;
Damit haben wir eine saubere Trennung von Befehl und Status erreicht.&lt;br /&gt;
&lt;br /&gt;
=== Aufbau eines Topics ===&lt;br /&gt;
Wie bereits geschrieben, kann man die Topics recht frei einfach selbst erfinden. Sinnvoll ist es jedoch, jedem gewünschten Wert ein eigenes Topic zu spendieren.&lt;br /&gt;
&lt;br /&gt;
Ungünstig:&lt;br /&gt;
* zuHause/state/1_OG/Kueche &lt;br /&gt;
=&amp;gt; In diesem Topic Licht, Temperatur, Luftfeuchte, Bewegungsmelder etc zu publishen ist eine nicht schlaue Idee; das Problem beginnt damit, dass man erst mal selber rausfinden muss, welchen Wert man gerade hat. Viel Programmcode für quasi umsonst.&lt;br /&gt;
&lt;br /&gt;
Besser:&lt;br /&gt;
* zuHause/state/1_OG/Kueche/Licht &lt;br /&gt;
* zuHause/state/1_OG/Kueche/Raumtemperatur &lt;br /&gt;
* zuHause/state/1_OG/Kueche/Luftfeuchte&lt;br /&gt;
* zuHause/state/1_OG/Kueche/Bewegungsmelder&lt;br /&gt;
=&amp;gt; Auf diese Weise weiß man vorher, welche Zahlenwerte in einem Topic stehen und was sie bedeuten. Das hat man automatisch durch die geschickte Topic Wahl festgelegt.&lt;br /&gt;
&lt;br /&gt;
=== Filter ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
AB HIER NOCH NICHT FERTIG&lt;br /&gt;
&lt;br /&gt;
Eine witzige Sache von MQTT sind Filter. Das ist in etwa wie in FHEM eine readingsGroup für Arme. &lt;br /&gt;
&lt;br /&gt;
Es gibt zwei Arten von Filtern:&lt;br /&gt;
* Single Level Filter: +&lt;br /&gt;
* Multi Level Filter: #&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiele:&lt;br /&gt;
* zuHause/state/1_OG/Kueche/Temperatur&lt;br /&gt;
* zuHause/state/1_OG/Kueche/Kuehlschrank/Temperatur&lt;br /&gt;
* zuHause/state/1_OG/Kueche/Licht&lt;br /&gt;
* zuHause/state/1_OG/Wohnzimmer/Licht&lt;br /&gt;
* zuHause/state/1_OG/Schlafzimmer/Licht&lt;br /&gt;
&lt;br /&gt;
Jetzt filtern wir:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;#&amp;quot; =&amp;gt; muss immer der letzte Filter sein&lt;br /&gt;
&lt;br /&gt;
* zuHause/state/# gibt uns alle oben genannten Topics zurück&lt;br /&gt;
* zuHause/state/1_OG/+/Licht&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung_Teil_2&amp;diff=21046</id>
		<title>MQTT Einführung Teil 2</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung_Teil_2&amp;diff=21046"/>
		<updated>2017-03-27T10:15:44Z</updated>

		<summary type="html">&lt;p&gt;Rince: /* Aufbau eines Topics */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= MQTT Teil 2 =&lt;br /&gt;
Konzepte und best practices&lt;br /&gt;
&lt;br /&gt;
== Vorwort ==&lt;br /&gt;
Dieser Artikel beschreibt, etwas trocken, weiterführend Konzepte und Denkweisen des Übertragungsprotokolls MQTT. Es wird etwas technischer als die Einführung und der ein oder andere Vergleich zu anderen Protokollen wird auch gezogen. Vieles davon kann man auch so nachlesen, wenngleich nicht immer auf deutsch. Ich gehe davon aus, dass der Leser MQTT vornehmlich mit FHEM einsetzen will.&lt;br /&gt;
&lt;br /&gt;
Ein Beispielkurs ist in Planung. Dort werden wir die Konzepte praktisch kennen lernen.&lt;br /&gt;
&lt;br /&gt;
== Retained Messages ==&lt;br /&gt;
=== Szenario ===&lt;br /&gt;
Stellen wir uns vor, wir starten FHEM neu. Wer Homematic Devices kennt weiß, spätestens nach einem Blick ins Logfile, dass nun zunächst ein Statusrequest aller Geräte erfolgt. Schließlich konnte sich zwischen Beenden und Neustart von FHEM etwas geändert haben.&lt;br /&gt;
* Homematic&lt;br /&gt;
* Es wird jedes Gerät angesprochen und abgefragt: &lt;br /&gt;
* &amp;quot;Lieber Lichtschalter, was tust du grade?&amp;quot; &lt;br /&gt;
* &amp;quot;Ich lasse das Licht über dir leuchten mein User.&amp;quot;&lt;br /&gt;
MQTT hat hier ein anderes Konzept. Wenn in ein Topic gepostet wird, kann ein &amp;quot;retained Flag&amp;quot; gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
=== Das bedeutet ===&lt;br /&gt;
Die zuletzt gepostete Nachricht wird vom Broker nicht gelöscht. Publishen wir also den Status unseres Lichts:&lt;br /&gt;
* zuHause/1OG/Kueche/Licht/state &amp;quot;on&amp;quot; oder &amp;quot;off&amp;quot; + retained flag&lt;br /&gt;
Sobald wir dieses Topic auf einem Gerät subscriben, bekommen wir den Status angezeigt. Ein neu startendes FHEM ist so ein Fall.&lt;br /&gt;
&lt;br /&gt;
Was bei Homematic erst über einen (zugegeben automatisierten Request) abläuft, kann MQTT mit den retained Messages auch so.&lt;br /&gt;
&lt;br /&gt;
Trifft am Broker eine neue retained Message ein, so wird die alte Nachricht gelöscht. Zum absichtlichen Löschen einer retained Message, etwa weil man weiß, dass dieses Topic zukünftig nicht mehr benötigt wird, kann man eine leere Message posten.&lt;br /&gt;
&lt;br /&gt;
=== Fazit ===&lt;br /&gt;
Retained Messages sind gut, um jeweils die letzte aktuelle Statusmeldung zu erhalten. Was damit nicht geht, ist z.B. die letzten 30 Messungen eines Temperatursensors zu speichern und auszuliefern! Sobald eine retained Message überschrieben wird, ist der alte Wert futsch.&lt;br /&gt;
&lt;br /&gt;
== Last Will and Testament (LWT) ==&lt;br /&gt;
=== Szenario ===&lt;br /&gt;
Letzter Wille und Testament. &amp;lt;hr&amp;gt;&lt;br /&gt;
Unser batteriebetriebener Sensor hat keinen Strom mehr, das billige 5V Netzteil stellt seinen Dienst ein, ein netter Nachbar eröffnet ein neues WLAN Netz welches unser Bestehendes gnadenlos stört, unsere süßen kleinen Miezekatzen finden Patchkabel so spannend, dass sie es für erfolgreiche Beißübungen verwenden…&lt;br /&gt;
Gründe für einen Sensorausfall gibt es durchaus.&lt;br /&gt;
Was passiert in FHEM?&lt;br /&gt;
Der letzte Sensorwert bleibt im Reading stehen. Blöd wenn man erst abends feststellt, dass der Kühlschrank offen stand oder der Schaltbefehl zum Heizung einschalten nicht angekommen ist. Ersteres sorgt für aufgetautes Essen, letzteres für kalte Füße.&lt;br /&gt;
Wie fängt man das ab?&lt;br /&gt;
FHEM-seitig könnte man einen Watchdog oder ein DOIF einrichten. Es muss geprüft werden, ob sich das entsprechende Reading in einer bestimmten Zeit verändert hat. &amp;lt;hr&amp;gt;&lt;br /&gt;
Möglich.&lt;br /&gt;
&lt;br /&gt;
=== MQTT Lösung ===&lt;br /&gt;
Der Letzte Wille, das Testament (LWT)&lt;br /&gt;
&lt;br /&gt;
Beim Anmelden an einen Broker kann ein Last Will - Topic angegeben werden. Ebenso eine Payload. Wenn das Gerät verschwindet ohne sich sauber abgemeldet zu haben, wird der Broker die gewünschte Nachricht auf dem hinterlegten Topic publishen. Das retained Flag kann auch gesetzt werden.&lt;br /&gt;
Was bedeutet das für uns?&lt;br /&gt;
&lt;br /&gt;
Zusätzlich zu:&lt;br /&gt;
*zuHause/1_OG/Kueche/Licht/state&lt;br /&gt;
*zuHause/1_OG/Kueche/Licht/set&lt;br /&gt;
&lt;br /&gt;
könnten wir zusätzlich&lt;br /&gt;
* zuHause/1_OG/Kueche/Licht/status&lt;br /&gt;
definieren.&lt;br /&gt;
&lt;br /&gt;
Beim Anmelden an den Broker schicken wir (mit retained flag) ein &amp;quot;online&amp;quot;&lt;br /&gt;
Als LWT geben wir das gleiche Topic an, aber mit &amp;quot;offline&amp;quot; und retained flag. Meldet sich unser Device sauber ab (disconnect), wird das LWT nicht verwendet. Es dient nur dazu, einen Fehler deutlich zu machen.&lt;br /&gt;
&lt;br /&gt;
==== Vorsicht ====&lt;br /&gt;
LWT bezieht sich auf die Client ID. Was das schon wieder?&lt;br /&gt;
Jedes angemeldete Gerät hat eine einzige Client ID, unabhängig davon wie viele Topics es published und subscribed hat.&lt;br /&gt;
LWT auf ein Topic zu beziehen macht wenig Sinn, wenn es mehrere Topics auf dem Gerät gibt. Obiges Beispiel ist also gut, wenn an dem MC genau dieses eine Licht hängt!&lt;br /&gt;
* zuHause/1OG/Arduino_1&lt;br /&gt;
Ist der bessere Weg! Jetzt können wir in FHEM auf online / offline reagieren und den davon abhängigen Geräten eine Fehlerbehandlung spendieren. Da ist unser DOIF wieder :)&lt;br /&gt;
&lt;br /&gt;
==== Noch eine Falle ====&lt;br /&gt;
Wer denkt, er wirft alle Geräte in ein einziges retained last will Topic, sieht immer nur die letzte Meldung!&lt;br /&gt;
&lt;br /&gt;
Böse:&lt;br /&gt;
&lt;br /&gt;
zuHause/MQTT/Status (&amp;lt;= nicht nachmachen)&lt;br /&gt;
&lt;br /&gt;
=== Fazit ===&lt;br /&gt;
MQTT kann einen eleganten Weg bieten, über das Ende eines Gerätes zu informieren. Genau wie bei Homematic aber auch, muss man diese Meldungen auswerten um was sinnvolles damit anzufangen!&lt;br /&gt;
Im Fall eines einfachen Sensors ist es recht easy, bei einem Arduino Mega mit 30 Sensoren wird es dann aufwendig (außer man liest weiter bei den Filtern)&lt;br /&gt;
&lt;br /&gt;
== Organisation der Topics ==&lt;br /&gt;
=== Basics, erlaubte Zeichen ===&lt;br /&gt;
MQTT erlaubt prinzipiell den kompletten UTF8 Zeichensatz.&lt;br /&gt;
&lt;br /&gt;
Außer:&lt;br /&gt;
* U+0001..U+001F control characters&lt;br /&gt;
* U+007F..U+009F control characters&lt;br /&gt;
&lt;br /&gt;
Theoretisch gehen also Umlaute, Leerzeichen etc. Praktisch kann es passieren, dass ein Endgerät mit Umlauten einfach nix anfangen kann. Leerzeichen sind auch ein Problem, weil UTF 8 davon doch recht viele Möglichkeiten bietet. Ich würde daher empfehlen, Topicbezeichnungen eher wie Gerätenamen in FHEM zu betrachten: Unterstriche statt Leerzeichen, Umlaute ausschreiben (=&amp;gt; ü =&amp;gt; ue...)&lt;br /&gt;
&lt;br /&gt;
Groß- und Kleinschreibung muss beachtet werden. Ein Topic muss mindestens ein Zeichen haben, um gültig zu sein.&lt;br /&gt;
&lt;br /&gt;
Falsch:&lt;br /&gt;
*/zuHause/&lt;br /&gt;
nicht ganz falsch, aber der / am Anfang ist nur zusätzlicher Overhead, daher weglassen&lt;br /&gt;
*zuHause//1_OG&lt;br /&gt;
Hier wird ein leeres Topic definiert. Das ist ungültig.&lt;br /&gt;
&lt;br /&gt;
=== Basics, Strukturierung ===&lt;br /&gt;
MQTT kennt publishen und subscriben.&lt;br /&gt;
&lt;br /&gt;
FHEM kennt für jedes Gerät einen &amp;quot;state&amp;quot; und ein &amp;quot;set&amp;quot; Kommando. Das ist bei MQTT nicht nötig, aber durchaus sehr sinnvoll.&lt;br /&gt;
&lt;br /&gt;
Nehmen wir wieder unseren Lichtschalter: Ein Taster an einem Arduino mit einem Relais nebst Lampe daran.&lt;br /&gt;
&lt;br /&gt;
Unglücklich:&lt;br /&gt;
* zuHause/1_OG/Kueche/Lichtschalter&lt;br /&gt;
Wenn da ein &amp;quot;on&amp;quot; steht, woher will man wissen ob es sich um einen Befehl oder um eine Statusmeldung handelt? Daher bauen wir die FHEM übliche Logik einfach nach:&lt;br /&gt;
&lt;br /&gt;
Etwas glücklicher (kann man machen, sollte man aber nicht)&lt;br /&gt;
* zuHause/1_OG/Kueche/Lichtschalter/set&lt;br /&gt;
* zuHause/1_OG/Kueche/Lichtschalter/state&lt;br /&gt;
&lt;br /&gt;
Richtig schlau (warum, kommt bei den Filtern)&lt;br /&gt;
* set/zuHause/1_OG/Kueche/Lichtschalter&lt;br /&gt;
* state/zuHause/1_OG/Kueche/Lichtschalter/state&lt;br /&gt;
&lt;br /&gt;
Jetzt wird es einfach:&lt;br /&gt;
&lt;br /&gt;
auf dem set-Topic publishen wir immer Schaltbefehle. Mit oder ohne retained flag, darüber kann man streiten. Unser Arduino muss also dieses Topic abhören und auswerten.&lt;br /&gt;
&lt;br /&gt;
Das state-Topic nehmen wir um darauf zu publishen, wie der Zustand unserer Lampe gerade ist. Unser Arduino muss dieses Topic nur schreiben, niemals selber lesen.&lt;br /&gt;
&lt;br /&gt;
Damit haben wir eine saubere Trennung von Befehl und Status erreicht.&lt;br /&gt;
&lt;br /&gt;
=== Aufbau eines Topics ===&lt;br /&gt;
Wie bereits geschrieben, kann man die Topics recht frei einfach selbst erfinden. Sinnvoll ist es jedoch, jedem gewünschten Wert ein eigenes Topic zu spendieren.&lt;br /&gt;
&lt;br /&gt;
Ungünstig:&lt;br /&gt;
* zuHause/state/1_OG/Kueche &lt;br /&gt;
=&amp;gt; In diesem Topic Licht, Temperatur, Luftfeuchte, Bewegungsmelder etc zu publishen ist eine nicht schlaue Idee; das Problem beginnt damit, dass man erst mal selber rausfinden muss, welchen Wert man gerade hat. Viel Programmcode für quasi umsonst.&lt;br /&gt;
&lt;br /&gt;
Besser:&lt;br /&gt;
* zuHause/state/1_OG/Kueche/Licht &lt;br /&gt;
* zuHause/state/1_OG/Kueche/Raumtemperatur &lt;br /&gt;
* zuHause/state/1_OG/Kueche/Luftfeuchte&lt;br /&gt;
* zuHause/state/1_OG/Kueche/Bewegungsmelder&lt;br /&gt;
=&amp;gt; Auf diese Weise weiß man vorher, welche Zahlenwerte in einem Topic stehen und was sie bedeuten. Das hat man automatisch durch die geschickte Topic Wahl festgelegt.&lt;br /&gt;
&lt;br /&gt;
=== Filter ===&lt;br /&gt;
Eine witzige Sache von MQTT sind Filter. Das ist in etwa wie in FHEM eine readingsGroup für Arme. &lt;br /&gt;
&lt;br /&gt;
WIRD FORTGESETZT&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung&amp;diff=21045</id>
		<title>MQTT Einführung</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung&amp;diff=21045"/>
		<updated>2017-03-27T10:07:58Z</updated>

		<summary type="html">&lt;p&gt;Rince: Link zu Teil 2 eingefügt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
= MQTT =&lt;br /&gt;
&lt;br /&gt;
Message Queue Telemetry Transport&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Was ist das? ==&lt;br /&gt;
&lt;br /&gt;
Es handelt sich um ein Protokoll um Daten unter verschiedenen Geräten zu übermitteln. MQTT funktioniert z.B. über eine TCP/IP Verbindung. &lt;br /&gt;
(Für die, die etwas verbal posen wollen: Man nennt das M2M, Machine to Machine; im Übrigen handelt es sich bei MQTT um ein Transportprotokoll.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau ==&lt;br /&gt;
&lt;br /&gt;
Herzstück des eigenen MQTT Netzes ist ein Broker. Die mit dem Broker verbundenen Geräte nennen wir der Einfachheit halber mal Clients. (stimmt nicht ganz, aber später lernen wir das genauer kennen)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== So tickt MQTT ==&lt;br /&gt;
&lt;br /&gt;
Wir schreiben/schicken einfach eine Nachricht an den Broker. Wer wann die Nachricht abholt und liest, interessiert an dieser Stelle überhaupt nicht. Das ist einer der großen Vorteile.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ordnung in das Chaos ==&lt;br /&gt;
&lt;br /&gt;
Worin liegt nun der Vorteil? Und wie kann nun jemand eine Nachricht lesen?&lt;br /&gt;
Hier beginnt das raffinierte Konzept von MQTT:&lt;br /&gt;
Wir stellen nicht einfach nur Daten dem Broker zur Verfügung. Wir organisieren sie auch selbst. Das Zauberwort hierfür nennt sich &amp;quot;Topic&amp;quot;. &lt;br /&gt;
Kann man sich so ähnlich vorstellen wie einen Verzeichnisbaum unter Windows, oder wie eine Datei auf einem Webserver.&lt;br /&gt;
Ein anderes Bild für einen &amp;quot;Topic&amp;quot; wäre eine Art schwarzes Brett.&lt;br /&gt;
&lt;br /&gt;
Ein Topic könnte so lauten:&lt;br /&gt;
&#039;&#039;&#039;zuHause/1OG/Kueche/Licht/state&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Dieses Topic böte sich geradezu an, den Zustand des Küchenlichts im 1. Stock reinzuschreiben.&lt;br /&gt;
&lt;br /&gt;
Unser kleiner schlauer Lichtschalter könnte in diesem Topic immer den aktuellen Zustand des Lichts notieren. In &amp;quot;MQTT-Sprechweise&amp;quot; würde man sagen, unser Client ist ein Publisher. Er veröffentlicht Informationen.&lt;br /&gt;
&lt;br /&gt;
Nehmen wir im folgenden einen Sensor:&lt;br /&gt;
&#039;&#039;&#039;zuHause/1OG/Kueche/Kuehlschrank/Temperatur/state&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Das ergäbe ein hübsches Topic für einen im Kühlschrank befindlichen Temperatursensor.&lt;br /&gt;
Auch hier hätten wir es mit einem Publisher zu tun.&lt;br /&gt;
&lt;br /&gt;
Wichtig ist hierbei, dass wir uns nicht um die Technik kümmern müssen. Auch bei der Organisation der Topics haben wir ziemlich freie Hand.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Was kann man jetzt damit anfangen? ==&lt;br /&gt;
&lt;br /&gt;
Nun wollen wir die Kühlschranktemperatur auf einem Display sehen. Vielleicht lagern wir ja empfindliche Medikamente im Kühlschrank und haben Kinder, die gerne die Kühlschranktür offen lassen?&lt;br /&gt;
&lt;br /&gt;
Wir nehmen also ein Display und klemmen das auch an unseren Broker. Jetzt möchten wir aber nicht die Temperatur publishen, das macht ja der Sensor. Wir wollen sie lesen. Also melden wir uns mit dem Display beim Broker an und &amp;quot;subscriben&amp;quot; das Topic. Wir teilen dem Broker mit, dass uns diese Information interessiert.&lt;br /&gt;
&lt;br /&gt;
Unser Display abonniert also die Temperatur. Zukünftig wird der Broker immer versuchen, unserem Display die Temperatur zu übermitteln.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ah ja. Und was ist daran toll? ==&lt;br /&gt;
&lt;br /&gt;
Nun, wie wir das Thermometer programmiert haben, wussten wir nichts von dem Display. Wir müssen auch am Thermometer gar nichts mehr verändern. Das bleibt so wie es ist.&lt;br /&gt;
&lt;br /&gt;
Wenn wir nun ein weiteres Display haben wollen, bauen wir uns eben ein zweites Display und subscriben das Topic ebenfalls beim Broker.&lt;br /&gt;
Zukünftig wird er an beide Displays die Information schicken.&lt;br /&gt;
&lt;br /&gt;
Wenn wir eine grafische Auswertung des Temperaturverlaufs wollen, dann könnten wir das Topic beim Broker zusätzlich mit FHEM subscriben. Temperatur bekommen, in Logfile schreiben, Plot, fertig.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Immer noch: warum ist das so toll? ==&lt;br /&gt;
&lt;br /&gt;
Nun, bei der Konzeption von MQTT hat man Wert darauf gelegt, dass es ohne große Ressourcen auskommt. Das bedeutet für uns, dass es für viele &amp;quot;Bastelhardware&amp;quot; (Arduino etc.) fertige Libraries gibt. Ich zeige das später. Auch wer gerne mit Javascript, Java, Perl, Python programmiert, findet gut funktionierende Bibliotheken. &lt;br /&gt;
Für den &amp;quot;ambitionierten Bastler&amp;quot; bedeutet dies:&lt;br /&gt;
Wir können Geräte bauen und programmieren, die sich selbstständig miteinander unterhalten. Ein Taster der Licht an einem entfernten Aktor einschaltet, ist kein Problem. Und zwar ohne FHEM hiermit zu belasten oder es auch nur zu brauchen.&lt;br /&gt;
Wir können also sehr schnell unsere Kühlschranktemperatur mit diversen Programmiersprachen auf einer Unzahl von Geräten lesen und auswerten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Cool, was braucht man? ==&lt;br /&gt;
&lt;br /&gt;
Einen MQTT Broker; z.B. Mosquitto.&lt;br /&gt;
Für den Mikrocontroller der eigenen Wahl eine passende Library. Für Arduinos böte sich der PubSubClient an&lt;br /&gt;
Ggfs. ein Analyse-Tool wie MQTT.fx&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Nachteile ==&lt;br /&gt;
&lt;br /&gt;
=== Single Point of Failure ===&lt;br /&gt;
&lt;br /&gt;
Wo Licht ist, ist bekanntermaßen auch Schatten. Für uns, da wir FHEM zur Haussteuerung einsetzen, stellt sich die erste Frage, warum man seine Geräte nicht einfach gleich an FHEM anbindet, sondern erst noch einen MQTT Broker (letztlich noch ein Stück Software) extra davor setzt.&lt;br /&gt;
Möglicher Grund:&lt;br /&gt;
MQTT ist besser ausgereift als jedes selbst gestricke Protokoll. Es ist sogar ISO Standard. Es gibt viele Tools und Hilfestellungen dafür; eigene Intelligenz den Geräten beizubringen ist auch recht einfach.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Sicherheit ===&lt;br /&gt;
&lt;br /&gt;
Prinzipiell ist MQTT ebenso sicher wie eine Postkarte. Solange man es nicht extra absichert, kann jeder der im eigenen LAN ist (und die Adresse vom Broker kennt) alle Topics mitlesen.&lt;br /&gt;
meinHaus/Flur/Haustuer:open / close&lt;br /&gt;
Ist da nicht wirklich schlau! &lt;br /&gt;
Abhilfe:&lt;br /&gt;
==== Username / Passwort ====&lt;br /&gt;
Zunächst kann man erst mal einen Username / Passwort vergeben. Da ist zwar auch noch lange nicht sicher, aber zumindest steigert es den Aufwand schon mal. Jetzt muss man zumindest schon mal Pakete sniffen und verstehen, um unbefugt zu lesen oder gar zu publishen.&lt;br /&gt;
&lt;br /&gt;
==== TLS ====&lt;br /&gt;
Um wirklich sicher zu werden, führt kein Weg an TLS vorbei. Leider kann z.B. ein Arduino das schlicht nicht mehr. Irgendwo machen sich der Speicher und die Rechenleistung dann doch bemerkbar.&lt;br /&gt;
&lt;br /&gt;
=== Änderung der Topic Hierarchie ===&lt;br /&gt;
Ja, das ist ein Problem. Wenn man die Hierarchie der Topics ändern will, wird man in den seltensten Fällen drum rum kommen, seinen Programmcode (Arduino..,) anzupassen, neu zu kompilieren und wieder hoch zu laden.&lt;br /&gt;
Gleiches gilt, wenn sich z.B. die IP Adresse des Brokers ändert.&lt;br /&gt;
&lt;br /&gt;
=== Netzwerktraffic ===&lt;br /&gt;
Eine weitere Frage, die man sich stellen kann ist eine grundsätzliche:&lt;br /&gt;
Welchen Sinn hat es, sein Netzwerk (insbesondere WLAN) mit so Dingen wie Sensordaten zuzukleistern. Das ist nicht völlig unberechtigt. MySensors ist für viele kleine batteriebetriebenen Sensoren vermutlich eine deutlich bessere Wahl. Sensoren mit Akku in ein WLAN einzubinden, ist technisch eine echte Herausforderung. De große Vorteil ist aber, dass man sein WLAN im Fall des Reichweitenendes einfach erweitern kann. WLAN-Repeater, Sache gut.&lt;br /&gt;
&lt;br /&gt;
== Ausblick ==&lt;br /&gt;
Hier endet erst mal der kurze Überblick. Wer neugierig geworden ist, darf sich auf viele weitere spannenden Themen freuen:&lt;br /&gt;
&lt;br /&gt;
=== QoS ===&lt;br /&gt;
Ein weiteres Feature sind die QoS Level von MQTT.&lt;br /&gt;
 * QoS Level 0: ist eine Art fire and forget. Ob die Daten ankommen, wird nicht weiter geprüft&lt;br /&gt;
 * QoS Level 1: garantiert die Zustellung der Nachricht; es kann aber auch passieren, dass eine Nachricht öfter zugestellt und empfangen wird&lt;br /&gt;
 * QoS Level 3: Hier wird garantiert, dass jede Nachricht &#039;&#039;&#039;genau 1x&#039;&#039;&#039; bei den Empfängern ankommt&lt;br /&gt;
&lt;br /&gt;
=== Retained Messages ===&lt;br /&gt;
Auch eine lustige Sache, lernen wir später kennen. Aber ein Beispiel möchte ich dennoch schon schildern: Wir basteln uns später den oben angesprochenen Temperatursensor und das zugehörige Display. Das erweitern wir um eine blinkende LED, wenn eine bestimmte Temperatur überschritten wird. Quizfrage: woher kennt das Display den gewünschten Schwellenwert? Freilich könnte man ihn im Programmcode hinterlegen. Aber dann ist er fest verdrahtet. Wenn wir ihn einfach nur normal publishen würden, würde das Display ihn erst kennen, wenn der Schwellwert gepublished würde nachdem das Display mit dem Broker verbunden war... Hier kommen retained Messages. Diese werden auch beim Verbinden eines Subscribers gesendet, obwohl es da keine Änderung gab.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
* [http://mqtt.org Offizielle Homepage von MQTT, englisch]&lt;br /&gt;
* [http://www.hivemq.com/blog/mqtt-essentials-part-1-introducing-mqtt Sehr gute Einführung, englisch, sind 5 lesenswerte Teile]&lt;br /&gt;
* [https://www.heise.de/developer/artikel/MQTT-Protokoll-fuer-das-Internet-der-Dinge-2168152.html Ein Exkurs von Heise mit Beispielen, deusch, sehr lesenswert]&lt;br /&gt;
* [http://www.mqttfx.org/ MQTT FX - ein sehr praktisches Analysetool]&lt;br /&gt;
* {{Link2Forum|Topic=69230|LinkText=Diskussionsthread im Forum}}&lt;br /&gt;
* [https://wiki.fhem.de/wiki/MQTT_Einf%C3%BChrung_Teil_2 Teil 2 der Einführung, schwerere Kost]&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung_Teil_2&amp;diff=21044</id>
		<title>MQTT Einführung Teil 2</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung_Teil_2&amp;diff=21044"/>
		<updated>2017-03-27T09:39:32Z</updated>

		<summary type="html">&lt;p&gt;Rince: Die Seite wurde neu angelegt: „= MQTT Teil 2 = Konzepte und best practices  == Vorwort == Dieser Artikel beschreibt, etwas trocken, weiterführend Konzepte und Denkweisen des Übertragungspr…“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= MQTT Teil 2 =&lt;br /&gt;
Konzepte und best practices&lt;br /&gt;
&lt;br /&gt;
== Vorwort ==&lt;br /&gt;
Dieser Artikel beschreibt, etwas trocken, weiterführend Konzepte und Denkweisen des Übertragungsprotokolls MQTT. Es wird etwas technischer als die Einführung und der ein oder andere Vergleich zu anderen Protokollen wird auch gezogen. Vieles davon kann man auch so nachlesen, wenngleich nicht immer auf deutsch. Ich gehe davon aus, dass der Leser MQTT vornehmlich mit FHEM einsetzen will.&lt;br /&gt;
&lt;br /&gt;
Ein Beispielkurs ist in Planung. Dort werden wir die Konzepte praktisch kennen lernen.&lt;br /&gt;
&lt;br /&gt;
== Retained Messages ==&lt;br /&gt;
=== Szenario ===&lt;br /&gt;
Stellen wir uns vor, wir starten FHEM neu. Wer Homematic Devices kennt weiß, spätestens nach einem Blick ins Logfile, dass nun zunächst ein Statusrequest aller Geräte erfolgt. Schließlich konnte sich zwischen Beenden und Neustart von FHEM etwas geändert haben.&lt;br /&gt;
* Homematic&lt;br /&gt;
* Es wird jedes Gerät angesprochen und abgefragt: &lt;br /&gt;
* &amp;quot;Lieber Lichtschalter, was tust du grade?&amp;quot; &lt;br /&gt;
* &amp;quot;Ich lasse das Licht über dir leuchten mein User.&amp;quot;&lt;br /&gt;
MQTT hat hier ein anderes Konzept. Wenn in ein Topic gepostet wird, kann ein &amp;quot;retained Flag&amp;quot; gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
=== Das bedeutet ===&lt;br /&gt;
Die zuletzt gepostete Nachricht wird vom Broker nicht gelöscht. Publishen wir also den Status unseres Lichts:&lt;br /&gt;
* zuHause/1OG/Kueche/Licht/state &amp;quot;on&amp;quot; oder &amp;quot;off&amp;quot; + retained flag&lt;br /&gt;
Sobald wir dieses Topic auf einem Gerät subscriben, bekommen wir den Status angezeigt. Ein neu startendes FHEM ist so ein Fall.&lt;br /&gt;
&lt;br /&gt;
Was bei Homematic erst über einen (zugegeben automatisierten Request) abläuft, kann MQTT mit den retained Messages auch so.&lt;br /&gt;
&lt;br /&gt;
Trifft am Broker eine neue retained Message ein, so wird die alte Nachricht gelöscht. Zum absichtlichen Löschen einer retained Message, etwa weil man weiß, dass dieses Topic zukünftig nicht mehr benötigt wird, kann man eine leere Message posten.&lt;br /&gt;
&lt;br /&gt;
=== Fazit ===&lt;br /&gt;
Retained Messages sind gut, um jeweils die letzte aktuelle Statusmeldung zu erhalten. Was damit nicht geht, ist z.B. die letzten 30 Messungen eines Temperatursensors zu speichern und auszuliefern! Sobald eine retained Message überschrieben wird, ist der alte Wert futsch.&lt;br /&gt;
&lt;br /&gt;
== Last Will and Testament (LWT) ==&lt;br /&gt;
=== Szenario ===&lt;br /&gt;
Letzter Wille und Testament. &amp;lt;hr&amp;gt;&lt;br /&gt;
Unser batteriebetriebener Sensor hat keinen Strom mehr, das billige 5V Netzteil stellt seinen Dienst ein, ein netter Nachbar eröffnet ein neues WLAN Netz welches unser Bestehendes gnadenlos stört, unsere süßen kleinen Miezekatzen finden Patchkabel so spannend, dass sie es für erfolgreiche Beißübungen verwenden…&lt;br /&gt;
Gründe für einen Sensorausfall gibt es durchaus.&lt;br /&gt;
Was passiert in FHEM?&lt;br /&gt;
Der letzte Sensorwert bleibt im Reading stehen. Blöd wenn man erst abends feststellt, dass der Kühlschrank offen stand oder der Schaltbefehl zum Heizung einschalten nicht angekommen ist. Ersteres sorgt für aufgetautes Essen, letzteres für kalte Füße.&lt;br /&gt;
Wie fängt man das ab?&lt;br /&gt;
FHEM-seitig könnte man einen Watchdog oder ein DOIF einrichten. Es muss geprüft werden, ob sich das entsprechende Reading in einer bestimmten Zeit verändert hat. &amp;lt;hr&amp;gt;&lt;br /&gt;
Möglich.&lt;br /&gt;
&lt;br /&gt;
=== MQTT Lösung ===&lt;br /&gt;
Der Letzte Wille, das Testament (LWT)&lt;br /&gt;
&lt;br /&gt;
Beim Anmelden an einen Broker kann ein Last Will - Topic angegeben werden. Ebenso eine Payload. Wenn das Gerät verschwindet ohne sich sauber abgemeldet zu haben, wird der Broker die gewünschte Nachricht auf dem hinterlegten Topic publishen. Das retained Flag kann auch gesetzt werden.&lt;br /&gt;
Was bedeutet das für uns?&lt;br /&gt;
&lt;br /&gt;
Zusätzlich zu:&lt;br /&gt;
*zuHause/1_OG/Kueche/Licht/state&lt;br /&gt;
*zuHause/1_OG/Kueche/Licht/set&lt;br /&gt;
&lt;br /&gt;
könnten wir zusätzlich&lt;br /&gt;
* zuHause/1_OG/Kueche/Licht/status&lt;br /&gt;
definieren.&lt;br /&gt;
&lt;br /&gt;
Beim Anmelden an den Broker schicken wir (mit retained flag) ein &amp;quot;online&amp;quot;&lt;br /&gt;
Als LWT geben wir das gleiche Topic an, aber mit &amp;quot;offline&amp;quot; und retained flag. Meldet sich unser Device sauber ab (disconnect), wird das LWT nicht verwendet. Es dient nur dazu, einen Fehler deutlich zu machen.&lt;br /&gt;
&lt;br /&gt;
==== Vorsicht ====&lt;br /&gt;
LWT bezieht sich auf die Client ID. Was das schon wieder?&lt;br /&gt;
Jedes angemeldete Gerät hat eine einzige Client ID, unabhängig davon wie viele Topics es published und subscribed hat.&lt;br /&gt;
LWT auf ein Topic zu beziehen macht wenig Sinn, wenn es mehrere Topics auf dem Gerät gibt. Obiges Beispiel ist also gut, wenn an dem MC genau dieses eine Licht hängt!&lt;br /&gt;
* zuHause/1OG/Arduino_1&lt;br /&gt;
Ist der bessere Weg! Jetzt können wir in FHEM auf online / offline reagieren und den davon abhängigen Geräten eine Fehlerbehandlung spendieren. Da ist unser DOIF wieder :)&lt;br /&gt;
&lt;br /&gt;
==== Noch eine Falle ====&lt;br /&gt;
Wer denkt, er wirft alle Geräte in ein einziges retained last will Topic, sieht immer nur die letzte Meldung!&lt;br /&gt;
&lt;br /&gt;
Böse:&lt;br /&gt;
&lt;br /&gt;
zuHause/MQTT/Status (&amp;lt;= nicht nachmachen)&lt;br /&gt;
&lt;br /&gt;
=== Fazit ===&lt;br /&gt;
MQTT kann einen eleganten Weg bieten, über das Ende eines Gerätes zu informieren. Genau wie bei Homematic aber auch, muss man diese Meldungen auswerten um was sinnvolles damit anzufangen!&lt;br /&gt;
Im Fall eines einfachen Sensors ist es recht easy, bei einem Arduino Mega mit 30 Sensoren wird es dann aufwendig (außer man liest weiter bei den Filtern)&lt;br /&gt;
&lt;br /&gt;
== Organisation der Topics ==&lt;br /&gt;
=== Basics, erlaubte Zeichen ===&lt;br /&gt;
MQTT erlaubt prinzipiell den kompletten UTF8 Zeichensatz.&lt;br /&gt;
&lt;br /&gt;
Außer:&lt;br /&gt;
* U+0001..U+001F control characters&lt;br /&gt;
* U+007F..U+009F control characters&lt;br /&gt;
&lt;br /&gt;
Theoretisch gehen also Umlaute, Leerzeichen etc. Praktisch kann es passieren, dass ein Endgerät mit Umlauten einfach nix anfangen kann. Leerzeichen sind auch ein Problem, weil UTF 8 davon doch recht viele Möglichkeiten bietet. Ich würde daher empfehlen, Topicbezeichnungen eher wie Gerätenamen in FHEM zu betrachten: Unterstriche statt Leerzeichen, Umlaute ausschreiben (=&amp;gt; ü =&amp;gt; ue...)&lt;br /&gt;
&lt;br /&gt;
Groß- und Kleinschreibung muss beachtet werden. Ein Topic muss mindestens ein Zeichen haben, um gültig zu sein.&lt;br /&gt;
&lt;br /&gt;
Falsch:&lt;br /&gt;
*/zuHause/&lt;br /&gt;
nicht ganz falsch, aber der / am Anfang ist nur zusätzlicher Overhead, daher weglassen&lt;br /&gt;
*zuHause//1_OG&lt;br /&gt;
Hier wird ein leeres Topic definiert. Das ist ungültig.&lt;br /&gt;
&lt;br /&gt;
=== Basics, Strukturierung ===&lt;br /&gt;
MQTT kennt publishen und subscriben.&lt;br /&gt;
&lt;br /&gt;
FHEM kennt für jedes Gerät einen &amp;quot;state&amp;quot; und ein &amp;quot;set&amp;quot; Kommando. Das ist bei MQTT nicht nötig, aber durchaus sehr sinnvoll.&lt;br /&gt;
&lt;br /&gt;
Nehmen wir wieder unseren Lichtschalter: Ein Taster an einem Arduino mit einem Relais nebst Lampe daran.&lt;br /&gt;
&lt;br /&gt;
Unglücklich:&lt;br /&gt;
* zuHause/1_OG/Kueche/Lichtschalter&lt;br /&gt;
Wenn da ein &amp;quot;on&amp;quot; steht, woher will man wissen ob es sich um einen Befehl oder um eine Statusmeldung handelt? Daher bauen wir die FHEM übliche Logik einfach nach:&lt;br /&gt;
&lt;br /&gt;
Etwas glücklicher (kann man machen, sollte man aber nicht)&lt;br /&gt;
* zuHause/1_OG/Kueche/Lichtschalter/set&lt;br /&gt;
* zuHause/1_OG/Kueche/Lichtschalter/state&lt;br /&gt;
&lt;br /&gt;
Richtig schlau (warum, kommt bei den Filtern)&lt;br /&gt;
* set/zuHause/1_OG/Kueche/Lichtschalter&lt;br /&gt;
* state/zuHause/1_OG/Kueche/Lichtschalter/state&lt;br /&gt;
&lt;br /&gt;
Jetzt wird es einfach:&lt;br /&gt;
&lt;br /&gt;
auf dem set-Topic publishen wir immer Schaltbefehle. Mit oder ohne retained flag, darüber kann man streiten. Unser Arduino muss also dieses Topic abhören und auswerten.&lt;br /&gt;
&lt;br /&gt;
Das state-Topic nehmen wir um darauf zu publishen, wie der Zustand unserer Lampe gerade ist. Unser Arduino muss dieses Topic nur schreiben, niemals selber lesen.&lt;br /&gt;
&lt;br /&gt;
Damit haben wir eine saubere Trennung von Befehl und Status erreicht.&lt;br /&gt;
&lt;br /&gt;
=== Aufbau eines Topics ===&lt;br /&gt;
Wie bereits geschrieben, kann man die Topics recht frei einfach selbst erfinden. Sinnvoll ist es jedoch, jedem gewünschten Wert ein eigenes Topic zu spendieren.&lt;br /&gt;
&lt;br /&gt;
Ungünstig:&lt;br /&gt;
* zuHause/state/1_OG/Kueche &lt;br /&gt;
=&amp;gt; darein Licht, Temperatur, Luftfeuchte, Bewegungsmelder etc zu publishen ist eine nicht schlaue Idee; das Problem beginnt damit, dass man erst mal selber suchen muss, welchen Wert man gerade hat. Viel Programmcode für quasi umsonst.&lt;br /&gt;
&lt;br /&gt;
Besser:&lt;br /&gt;
* zuHause/state/1_OG/Kueche/Licht &lt;br /&gt;
* zuHause/state/1_OG/Kueche/Raumtemperatur &lt;br /&gt;
* zuHause/state/1_OG/Kueche/Luftfeuchte&lt;br /&gt;
* zuHause/state/1_OG/Kueche/Bewegungsmelder&lt;br /&gt;
=&amp;gt; Auf dieser Weise weiß man vorher, welche Zahlenwerte in einem Topic stehen und was sie bedeuten. Das hat man automatisch durch die geschickte Topic Wahl festgelegt.&lt;br /&gt;
&lt;br /&gt;
=== Filter ===&lt;br /&gt;
Eine witzige Sache von MQTT sind Filter. Das ist in etwa wie in FHEM eine readingsGroup für Arme. &lt;br /&gt;
&lt;br /&gt;
WIRD FORTGESETZT&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Diskussion:MQTT_Einf%C3%BChrung&amp;diff=21043</id>
		<title>Diskussion:MQTT Einführung</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Diskussion:MQTT_Einf%C3%BChrung&amp;diff=21043"/>
		<updated>2017-03-27T08:39:26Z</updated>

		<summary type="html">&lt;p&gt;Rince: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Kategorisierung Artikel ==&lt;br /&gt;
In welche Kategorie gehört das? Kann es bitte wer in passende Kategorien einsortieren? [[Benutzer:Rince|Rince]] ([[Benutzer Diskussion:Rince|Diskussion]]) 10:19, 22. Mär. 2017 (CET)&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
:Bist Du denn mit dem Artikel fertig oder wird der noch fortgesetzt? Bisher würde ich den Artikel in Glossary einordnen, da allgemeine Begriffserklärung und keine direkten Angaben zu MQTT in FHEM. Gruß, --[[Benutzer:Krikan|Christian]] ([[Benutzer Diskussion:Krikan|Diskussion]]) 13:41, 24. Mär. 2017 (CET)&lt;br /&gt;
&amp;lt;hr&amp;gt;&lt;br /&gt;
:Dieser ist denke ich soweit fertig, außer es finden sich Fehler darin, oder es beschließt jemand ihn völlig anders zu schreiben. Glossary gefällt mir denke ich gut. Es folgt noch ein weiterer Artikel, der sich etwas genauer mit MQTT Dingen beschäftigt. Diese werden nach und nach mehr Bezug zu FHEM bekommen. [[Benutzer:Rince|Rince]] ([[Benutzer Diskussion:Rince|Diskussion]]) 10:39, 27. Mär. 2017 (CEST)&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung&amp;diff=21016</id>
		<title>MQTT Einführung</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung&amp;diff=21016"/>
		<updated>2017-03-23T21:03:57Z</updated>

		<summary type="html">&lt;p&gt;Rince: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
= MQTT =&lt;br /&gt;
&lt;br /&gt;
Message Queue Telemetry Transport&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Was ist das? ==&lt;br /&gt;
&lt;br /&gt;
Es handelt sich um ein Protokoll um Daten unter verschiedenen Geräten zu übermitteln. MQTT funktioniert z.B. über eine TCP/IP Verbindung. &lt;br /&gt;
(Für die, die etwas verbal posen wollen: Man nennt das M2M, Machine to Machine; im Übrigen handelt es sich bei MQTT um ein Transportprotokoll.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau ==&lt;br /&gt;
&lt;br /&gt;
Herzstück des eigenen MQTT Netzes ist ein Broker. Die mit dem Broker verbundenen Geräte nennen wir der Einfachheit halber mal Clients. (stimmt nicht ganz, aber später lernen wir das genauer kennen)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== So tickt MQTT ==&lt;br /&gt;
&lt;br /&gt;
Wir schreiben/schicken einfach eine Nachricht an den Broker. Wer wann die Nachricht abholt und liest, interessiert an dieser Stelle überhaupt nicht. Das ist einer der großen Vorteile.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ordnung in das Chaos ==&lt;br /&gt;
&lt;br /&gt;
Worin liegt nun der Vorteil? Und wie kann nun jemand eine Nachricht lesen?&lt;br /&gt;
Hier beginnt das raffinierte Konzept von MQTT:&lt;br /&gt;
Wir stellen nicht einfach nur Daten dem Broker zur Verfügung. Wir organisieren sie auch selbst. Das Zauberwort hierfür nennt sich &amp;quot;Topic&amp;quot;. &lt;br /&gt;
Kann man sich so ähnlich vorstellen wie einen Verzeichnisbaum unter Windows, oder wie eine Datei auf einem Webserver.&lt;br /&gt;
Ein anderes Bild für einen &amp;quot;Topic&amp;quot; wäre eine Art schwarzes Brett.&lt;br /&gt;
&lt;br /&gt;
Ein Topic könnte so lauten:&lt;br /&gt;
&#039;&#039;&#039;zuHause/1OG/Kueche/Licht/state&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Dieses Topic böte sich geradezu an, den Zustand des Küchenlichts im 1. Stock reinzuschreiben.&lt;br /&gt;
&lt;br /&gt;
Unser kleiner schlauer Lichtschalter könnte in diesem Topic immer den aktuellen Zustand des Lichts notieren. In &amp;quot;MQTT-Sprechweise&amp;quot; würde man sagen, unser Client ist ein Publisher. Er veröffentlicht Informationen.&lt;br /&gt;
&lt;br /&gt;
Nehmen wir im folgenden einen Sensor:&lt;br /&gt;
&#039;&#039;&#039;zuHause/1OG/Kueche/Kuehlschrank/Temperatur/state&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Das ergäbe ein hübsches Topic für einen im Kühlschrank befindlichen Temperatursensor.&lt;br /&gt;
Auch hier hätten wir es mit einem Publisher zu tun.&lt;br /&gt;
&lt;br /&gt;
Wichtig ist hierbei, dass wir uns nicht um die Technik kümmern müssen. Auch bei der Organisation der Topics haben wir ziemlich freie Hand.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Was kann man jetzt damit anfangen? ==&lt;br /&gt;
&lt;br /&gt;
Nun wollen wir die Kühlschranktemperatur auf einem Display sehen. Vielleicht lagern wir ja empfindliche Medikamente im Kühlschrank und haben Kinder, die gerne die Kühlschranktür offen lassen?&lt;br /&gt;
&lt;br /&gt;
Wir nehmen also ein Display und klemmen das auch an unseren Broker. Jetzt möchten wir aber nicht die Temperatur publishen, das macht ja der Sensor. Wir wollen sie lesen. Also melden wir uns mit dem Display beim Broker an und &amp;quot;subscriben&amp;quot; das Topic. Wir teilen dem Broker mit, dass uns diese Information interessiert.&lt;br /&gt;
&lt;br /&gt;
Unser Display abonniert also die Temperatur. Zukünftig wird der Broker immer versuchen, unserem Display die Temperatur zu übermitteln.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ah ja. Und was ist daran toll? ==&lt;br /&gt;
&lt;br /&gt;
Nun, wie wir das Thermometer programmiert haben, wussten wir nichts von dem Display. Wir müssen auch am Thermometer gar nichts mehr verändern. Das bleibt so wie es ist.&lt;br /&gt;
&lt;br /&gt;
Wenn wir nun ein weiteres Display haben wollen, bauen wir uns eben ein zweites Display und subscriben das Topic ebenfalls beim Broker.&lt;br /&gt;
Zukünftig wird er an beide Displays die Information schicken.&lt;br /&gt;
&lt;br /&gt;
Wenn wir eine grafische Auswertung des Temperaturverlaufs wollen, dann könnten wir das Topic beim Broker zusätzlich mit FHEM subscriben. Temperatur bekommen, in Logfile schreiben, Plot, fertig.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Immer noch: warum ist das so toll? ==&lt;br /&gt;
&lt;br /&gt;
Nun, bei der Konzeption von MQTT hat man Wert darauf gelegt, dass es ohne große Ressourcen auskommt. Das bedeutet für uns, dass es für viele &amp;quot;Bastelhardware&amp;quot; (Arduino etc.) fertige Libraries gibt. Ich zeige das später. Auch wer gerne mit Javascript, Java, Perl, Python programmiert, findet gut funktionierende Bibliotheken. &lt;br /&gt;
Für den &amp;quot;ambitionierten Bastler&amp;quot; bedeutet dies:&lt;br /&gt;
Wir können Geräte bauen und programmieren, die sich selbstständig miteinander unterhalten. Ein Taster der Licht an einem entfernten Aktor einschaltet, ist kein Problem. Und zwar ohne FHEM hiermit zu belasten oder es auch nur zu brauchen.&lt;br /&gt;
Wir können also sehr schnell unsere Kühlschranktemperatur mit diversen Programmiersprachen auf einer Unzahl von Geräten lesen und auswerten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Cool, was braucht man? ==&lt;br /&gt;
&lt;br /&gt;
Einen MQTT Broker; z.B. Mosquitto.&lt;br /&gt;
Für den Mikrocontroller der eigenen Wahl eine passende Library. Für Arduinos böte sich der PubSubClient an&lt;br /&gt;
Ggfs. ein Analyse-Tool wie MQTT.fx&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Nachteile ==&lt;br /&gt;
&lt;br /&gt;
=== Single Point of Failure ===&lt;br /&gt;
&lt;br /&gt;
Wo Licht ist, ist bekanntermaßen auch Schatten. Für uns, da wir FHEM zur Haussteuerung einsetzen, stellt sich die erste Frage, warum man seine Geräte nicht einfach gleich an FHEM anbindet, sondern erst noch einen MQTT Broker (letztlich noch ein Stück Software) extra davor setzt.&lt;br /&gt;
Möglicher Grund:&lt;br /&gt;
MQTT ist besser ausgereift als jedes selbst gestricke Protokoll. Es ist sogar ISO Standard. Es gibt viele Tools und Hilfestellungen dafür; eigene Intelligenz den Geräten beizubringen ist auch recht einfach.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Sicherheit ===&lt;br /&gt;
&lt;br /&gt;
Prinzipiell ist MQTT ebenso sicher wie eine Postkarte. Solange man es nicht extra absichert, kann jeder der im eigenen LAN ist (und die Adresse vom Broker kennt) alle Topics mitlesen.&lt;br /&gt;
meinHaus/Flur/Haustuer:open / close&lt;br /&gt;
Ist da nicht wirklich schlau! &lt;br /&gt;
Abhilfe:&lt;br /&gt;
==== Username / Passwort ====&lt;br /&gt;
Zunächst kann man erst mal einen Username / Passwort vergeben. Da ist zwar auch noch lange nicht sicher, aber zumindest steigert es den Aufwand schon mal. Jetzt muss man zumindest schon mal Pakete sniffen und verstehen, um unbefugt zu lesen oder gar zu publishen.&lt;br /&gt;
&lt;br /&gt;
==== TLS ====&lt;br /&gt;
Um wirklich sicher zu werden, führt kein Weg an TLS vorbei. Leider kann z.B. ein Arduino das schlicht nicht mehr. Irgendwo machen sich der Speicher und die Rechenleistung dann doch bemerkbar.&lt;br /&gt;
&lt;br /&gt;
=== Änderung der Topic Hierarchie ===&lt;br /&gt;
Ja, das ist ein Problem. Wenn man die Hierarchie der Topics ändern will, wird man in den seltensten Fällen drum rum kommen, seinen Programmcode (Arduino..,) anzupassen, neu zu kompilieren und wieder hoch zu laden.&lt;br /&gt;
Gleiches gilt, wenn sich z.B. die IP Adresse des Brokers ändert.&lt;br /&gt;
&lt;br /&gt;
=== Netzwerktraffic ===&lt;br /&gt;
Eine weitere Frage, die man sich stellen kann ist eine grundsätzliche:&lt;br /&gt;
Welchen Sinn hat es, sein Netzwerk (insbesondere WLAN) mit so Dingen wie Sensordaten zuzukleistern. Das ist nicht völlig unberechtigt. MySensors ist für viele kleine batteriebetriebenen Sensoren vermutlich eine deutlich bessere Wahl. Sensoren mit Akku in ein WLAN einzubinden, ist technisch eine echte Herausforderung. De große Vorteil ist aber, dass man sein WLAN im Fall des Reichweitenendes einfach erweitern kann. WLAN-Repeater, Sache gut.&lt;br /&gt;
&lt;br /&gt;
== Ausblick ==&lt;br /&gt;
Hier endet erst mal der kurze Überblick. Wer neugierig geworden ist, darf sich auf viele weitere spannenden Themen freuen:&lt;br /&gt;
&lt;br /&gt;
=== QoS ===&lt;br /&gt;
Ein weiteres Feature sind die QoS Level von MQTT.&lt;br /&gt;
 * QoS Level 0: ist eine Art fire and forget. Ob die Daten ankommen, wird nicht weiter geprüft&lt;br /&gt;
 * QoS Level 1: garantiert die Zustellung der Nachricht; es kann aber auch passieren, dass eine Nachricht öfter zugestellt und empfangen wird&lt;br /&gt;
 * QoS Level 3: Hier wird garantiert, dass jede Nachricht &#039;&#039;&#039;genau 1x&#039;&#039;&#039; bei den Empfängern ankommt&lt;br /&gt;
&lt;br /&gt;
=== Retained Messages ===&lt;br /&gt;
Auch eine lustige Sache, lernen wir später kennen. Aber ein Beispiel möchte ich dennoch schon schildern: Wir basteln uns später den oben angesprochenen Temperatursensor und das zugehörige Display. Das erweitern wir um eine blinkende LED, wenn eine bestimmte Temperatur überschritten wird. Quizfrage: woher kennt das Display den gewünschten Schwellenwert? Freilich könnte man ihn im Programmcode hinterlegen. Aber dann ist er fest verdrahtet. Wenn wir ihn einfach nur normal publishen würden, würde das Display ihn erst kennen, wenn der Schwellwert gepublished würde nachdem das Display mit dem Broker verbunden war... Hier kommen retained Messages. Diese werden auch beim Verbinden eines Subscribers gesendet, obwohl es da keine Änderung gab.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
* [http://mqtt.org Offizielle Homepage von MQTT, englisch]&lt;br /&gt;
* [http://www.hivemq.com/blog/mqtt-essentials-part-1-introducing-mqtt Sehr gute Einführung, englisch, sind 5 lesenswerte Teile]&lt;br /&gt;
* [https://www.heise.de/developer/artikel/MQTT-Protokoll-fuer-das-Internet-der-Dinge-2168152.html Ein Exkurs von Heise mit Beispielen, deusch, sehr lesenswert]&lt;br /&gt;
* [http://www.mqttfx.org/ MQTT FX - ein sehr praktisches Analysetool]&lt;br /&gt;
* {{Link2Forum|Topic=69230|LinkText=Diskussionsthread im Forum}}&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Diskussion:MQTT_Einf%C3%BChrung&amp;diff=21002</id>
		<title>Diskussion:MQTT Einführung</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Diskussion:MQTT_Einf%C3%BChrung&amp;diff=21002"/>
		<updated>2017-03-22T09:20:12Z</updated>

		<summary type="html">&lt;p&gt;Rince: Frage nach der Kategorie&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;In welche Kategorie gehört das? Kann es bitte wer in passende Kategorien einsortieren? [[Benutzer:Rince|Rince]] ([[Benutzer Diskussion:Rince|Diskussion]]) 10:19, 22. Mär. 2017 (CET)&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung&amp;diff=20775</id>
		<title>MQTT Einführung</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung&amp;diff=20775"/>
		<updated>2017-03-18T20:23:18Z</updated>

		<summary type="html">&lt;p&gt;Rince: /* Sicherheit */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
= MQTT =&lt;br /&gt;
&lt;br /&gt;
Message Queue Telemetry Transport&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Was ist das? ==&lt;br /&gt;
&lt;br /&gt;
Es handelt sich um ein Protokoll um Daten unter verschiedenen Geräten zu übermitteln. MQTT funktioniert z.B. über eine TCP/IP Verbindung. &lt;br /&gt;
(Für die, die etwas verbal posen wollen: Man nennt das M2M, Machine to Machine; im Übrigen handelt es sich bei MQTT um ein Transportprotokoll.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau ==&lt;br /&gt;
&lt;br /&gt;
Herzstück des eigenen MQTT Netzes ist ein Broker. Die mit dem Broker verbundenen Geräte nennen wir der Einfachheit halber mal Clients. (stimmt nicht ganz, aber später lernen wir das genauer kennen)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== So tickt MQTT ==&lt;br /&gt;
&lt;br /&gt;
Wir schreiben/schicken einfach eine Nachricht an den Broker. Wer wann die Nachricht abholt und liest, interessiert an dieser Stelle überhaupt nicht. Das ist einer der großen Vorteile.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ordnung in das Chaos ==&lt;br /&gt;
&lt;br /&gt;
Worin liegt nun der Vorteil? Und wie kann nun jemand eine Nachricht lesen?&lt;br /&gt;
Hier beginnt das raffinierte Konzept von MQTT:&lt;br /&gt;
Wir stellen nicht einfach nur Daten dem Broker zur Verfügung. Wir organisieren sie auch selbst. Das Zauberwort hierfür nennt sich &amp;quot;Topic&amp;quot;. &lt;br /&gt;
Kann man sich so ähnlich vorstellen wie einen Verzeichnisbaum unter Windows, oder wie eine Datei auf einem Webserver.&lt;br /&gt;
Ein anderes Bild für einen &amp;quot;Topic&amp;quot; wäre eine Art schwarzes Brett.&lt;br /&gt;
&lt;br /&gt;
Ein Topic könnte so lauten:&lt;br /&gt;
&#039;&#039;&#039;zuHause/1OG/Kueche/Licht/state&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Dieses Topic böte sich geradezu an, den Zustand des Küchenlichts im 1. Stock reinzuschreiben.&lt;br /&gt;
&lt;br /&gt;
Unser kleiner schlauer Lichtschalter könnte in diesem Topic immer den aktuellen Zustand des Lichts notieren. In &amp;quot;MQTT-Sprechweise&amp;quot; würde man sagen, unser Client ist ein Publisher. Er veröffentlicht Informationen.&lt;br /&gt;
&lt;br /&gt;
Nehmen wir im folgenden einen Sensor:&lt;br /&gt;
&#039;&#039;&#039;zuHause/1OG/Kueche/Kuehlschrank/Temperatur/state&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Das ergäbe ein hübsches Topic für einen im Kühlschrank befindlichen Temperatursensor.&lt;br /&gt;
Auch hier hätten wir es mit einem Publisher zu tun.&lt;br /&gt;
&lt;br /&gt;
Wichtig ist hierbei, dass wir uns nicht um die Technik kümmern müssen. Auch bei der Organisation der Topics haben wir ziemlich freie Hand.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Was kann man jetzt damit anfangen? ==&lt;br /&gt;
&lt;br /&gt;
Nun wollen wir die Kühlschranktemperatur auf einem Display sehen. Vielleicht lagern wir ja empfindliche Medikamente im Kühlschrank und haben Kinder, die gerne die Kühlschranktür offen lassen?&lt;br /&gt;
&lt;br /&gt;
Wir nehmen also ein Display und klemmen das auch an unseren Broker. Jetzt möchten wir aber nicht die Temperatur publishen, das macht ja der Sensor. Wir wollen sie lesen. Also melden wir uns mit dem Display beim Broker an und &amp;quot;subscriben&amp;quot; das Topic. Wir teilen dem Broker mit, dass uns diese Information interessiert.&lt;br /&gt;
&lt;br /&gt;
Unser Display abonniert also die Temperatur. Zukünftig wird der Broker immer versuchen, unserem Display die Temperatur zu übermitteln.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ah ja. Und was ist daran toll? ==&lt;br /&gt;
&lt;br /&gt;
Nun, wie wir das Thermometer programmiert haben, wussten wir nichts von dem Display. Wir müssen auch am Thermometer gar nichts mehr verändern. Das bleibt so wie es ist.&lt;br /&gt;
&lt;br /&gt;
Wenn wir nun ein weiteres Display haben wollen, bauen wir uns eben ein zweites Display und subscriben das Topic ebenfalls beim Broker.&lt;br /&gt;
Zukünftig wird er an beide Displays die Information schicken.&lt;br /&gt;
&lt;br /&gt;
Wenn wir eine grafische Auswertung des Temperaturverlaufs wollen, dann könnten wir das Topic beim Broker zusätzlich mit FHEM subscriben. Temperatur bekommen, in Logfile schreiben, Plot, fertig.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Immer noch: warum ist das so toll? ==&lt;br /&gt;
&lt;br /&gt;
Nun, bei der Konzeption von MQTT hat man Wert darauf gelegt, dass es ohne große Ressourcen auskommt. Das bedeutet für uns, dass es für viele &amp;quot;Bastelhardware&amp;quot; (Arduino etc.) fertige Libraries gibt. Ich zeige das später. Auch wer gerne mit Javascript, Java, Perl, Python programmiert, findet gut funktionierende Bibliotheken. &lt;br /&gt;
Für den &amp;quot;ambitionierten Bastler&amp;quot; bedeutet dies:&lt;br /&gt;
Wir können Geräte bauen und programmieren, die sich selbstständig miteinander unterhalten. Ein Taster der Licht an einem entfernten Aktor einschaltet, ist kein Problem. Und zwar ohne FHEM hiermit zu belasten oder es auch nur zu brauchen.&lt;br /&gt;
Wir können also sehr schnell unsere Kühlschranktemperatur mit diversen Programmiersprachen auf einer Unzahl von Geräten lesen und auswerten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Cool, was braucht man? ==&lt;br /&gt;
&lt;br /&gt;
Einen MQTT Broker; z.B. Mosquitto.&lt;br /&gt;
Für den Mikrocontroller der eigenen Wahl eine passende Library. Für Arduinos böte sich der PubSubClient an&lt;br /&gt;
Ggfs. ein Analyse-Tool wie MQTT.fx&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Nachteile ==&lt;br /&gt;
&lt;br /&gt;
=== Single Point of Failure ===&lt;br /&gt;
&lt;br /&gt;
Wo Licht ist, ist bekanntermaßen auch Schatten. Für uns, da wir FHEM zur Haussteuerung einsetzen, stellt sich die erste Frage, warum man seine Geräte nicht einfach gleich an FHEM anbindet, sondern erst noch einen MQTT Broker (letztlich noch ein Stück Software) extra davor setzt.&lt;br /&gt;
Möglicher Grund:&lt;br /&gt;
MQTT ist besser ausgereift als jedes selbst gestricke Protokoll. Es ist sogar ISO Standard. Es gibt viele Tools und Hilfestellungen dafür; eigene Intelligenz den Geräten beizubringen ist auch recht einfach.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Sicherheit ===&lt;br /&gt;
&lt;br /&gt;
Prinzipiell ist MQTT ebenso sicher wie eine Postkarte. Solange man es nicht extra absichert, kann jeder der im eigenen LAN ist (und die Adresse vom Broker kennt) alle Topics mitlesen.&lt;br /&gt;
meinHaus/Flur/Haustuer:open / close&lt;br /&gt;
Ist da nicht wirklich schlau! &lt;br /&gt;
Abhilfe:&lt;br /&gt;
==== Username / Passwort ====&lt;br /&gt;
Zunächst kann man erst mal einen Username / Passwort vergeben. Da ist zwar auch noch lange nicht sicher, aber zumindest steigert es den Aufwand schon mal. Jetzt muss man zumindest schon mal Pakete sniffen und verstehen, um unbefugt zu lesen oder gar zu publishen.&lt;br /&gt;
&lt;br /&gt;
==== TLS ====&lt;br /&gt;
Um wirklich sicher zu werden, führt kein Weg an TLS vorbei. Leider kann z.B. ein Arduino das schlicht nicht mehr. Irgendwo machen sich der Speicher und die Rechenleistung dann doch bemerkbar.&lt;br /&gt;
&lt;br /&gt;
=== Änderung der Topic Hierarchie ===&lt;br /&gt;
Ja, das ist ein Problem. Wenn man die Hierarchie der Topics ändern will, wird man in den seltensten Fällen drum rum kommen, seinen Programmcode (Arduino..,) anzupassen, neu zu kompilieren und wieder hoch zu laden.&lt;br /&gt;
Gleiches gilt, wenn sich z.B. die IP Adresse des Brokers ändert.&lt;br /&gt;
&lt;br /&gt;
=== Netzwerktraffic ===&lt;br /&gt;
Eine weitere Frage, die man sich stellen kann ist eine grundsätzliche:&lt;br /&gt;
Welchen Sinn hat es, sein Netzwerk (insbesondere WLAN) mit so Dingen wie Sensordaten zuzukleistern. Das ist nicht völlig unberechtigt. MySensors ist für viele kleine batteriebetriebenen Sensoren vermutlich eine deutlich bessere Wahl. Sensoren mit Akku in ein WLAN einzubinden, ist technisch eine echte Herausforderung. De große Vorteil ist aber, dass man sein WLAN im Fall des Reichweitenendes einfach erweitern kann. WLAN-Repeater, Sache gut.&lt;br /&gt;
&lt;br /&gt;
== Ausblick ==&lt;br /&gt;
Hier endet erst mal der kurze Überblick. Wer neugierig geworden ist, darf sich auf viele weitere spannenden Themen freuen:&lt;br /&gt;
&lt;br /&gt;
=== QoS ===&lt;br /&gt;
Ein weiteres Feature sind die QoS Level von MQTT.&lt;br /&gt;
 * QoS Level 0: ist eine Art fire and forget. Ob die Daten ankommen, wird nicht weiter geprüft&lt;br /&gt;
 * QoS Level 1: garantiert die Zustellung der Nachricht; es kann aber auch passieren, dass eine Nachricht öfter zugestellt und empfangen wird&lt;br /&gt;
 * QoS Level 3: Hier wird garantiert, dass jede Nachricht &#039;&#039;&#039;genau 1x&#039;&#039;&#039; bei den Empfängern ankommt&lt;br /&gt;
&lt;br /&gt;
=== Retained Messages ===&lt;br /&gt;
Auch eine lustige Sache, lernen wir später kennen. Aber ein Beispiel möchte ich dennoch schon schildern: Wir basteln uns später den oben angesprochenen Temperatursensor und das zugehörige Display. Das erweitern wir um eine blinkende LED, wenn eine bestimmte Temperatur überschritten wird. Quizfrage: woher kennt das Display den gewünschten Schwellenwert? Freilich könnte man ihn im Programmcode hinterlegen. Aber dann ist er fest verdrahtet. Wenn wir ihn einfach nur normal publishen würden, würde das Display ihn erst kennen, wenn der Schwellwert gepublished würde nachdem das Display mit dem Broker verbunden war... Hier kommen retained Messages. Diese werden auch beim Verbinden eines Subscribers gesendet, obwohl es da keine Änderung gab.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
* [http://mqtt.org Offizielle Homepage von MQTT, englisch]&lt;br /&gt;
* [http://www.hivemq.com/blog/mqtt-essentials-part-1-introducing-mqtt, Sehr gute Einführung, englisch, sind 5 lesenswerte Teile]&lt;br /&gt;
* [https://www.heise.de/developer/artikel/MQTT-Protokoll-fuer-das-Internet-der-Dinge-2168152.html Ein Exkurs von Heise mit Beispielen, deusch, sehr lesenswert]&lt;br /&gt;
* [https://forum.fhem.de/index.php/topic,69230.0.html Diskussionsthread im Forum]&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung&amp;diff=20774</id>
		<title>MQTT Einführung</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung&amp;diff=20774"/>
		<updated>2017-03-18T20:21:38Z</updated>

		<summary type="html">&lt;p&gt;Rince: /* Ausblik */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
= MQTT =&lt;br /&gt;
&lt;br /&gt;
Message Queue Telemetry Transport&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Was ist das? ==&lt;br /&gt;
&lt;br /&gt;
Es handelt sich um ein Protokoll um Daten unter verschiedenen Geräten zu übermitteln. MQTT funktioniert z.B. über eine TCP/IP Verbindung. &lt;br /&gt;
(Für die, die etwas verbal posen wollen: Man nennt das M2M, Machine to Machine; im Übrigen handelt es sich bei MQTT um ein Transportprotokoll.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau ==&lt;br /&gt;
&lt;br /&gt;
Herzstück des eigenen MQTT Netzes ist ein Broker. Die mit dem Broker verbundenen Geräte nennen wir der Einfachheit halber mal Clients. (stimmt nicht ganz, aber später lernen wir das genauer kennen)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== So tickt MQTT ==&lt;br /&gt;
&lt;br /&gt;
Wir schreiben/schicken einfach eine Nachricht an den Broker. Wer wann die Nachricht abholt und liest, interessiert an dieser Stelle überhaupt nicht. Das ist einer der großen Vorteile.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ordnung in das Chaos ==&lt;br /&gt;
&lt;br /&gt;
Worin liegt nun der Vorteil? Und wie kann nun jemand eine Nachricht lesen?&lt;br /&gt;
Hier beginnt das raffinierte Konzept von MQTT:&lt;br /&gt;
Wir stellen nicht einfach nur Daten dem Broker zur Verfügung. Wir organisieren sie auch selbst. Das Zauberwort hierfür nennt sich &amp;quot;Topic&amp;quot;. &lt;br /&gt;
Kann man sich so ähnlich vorstellen wie einen Verzeichnisbaum unter Windows, oder wie eine Datei auf einem Webserver.&lt;br /&gt;
Ein anderes Bild für einen &amp;quot;Topic&amp;quot; wäre eine Art schwarzes Brett.&lt;br /&gt;
&lt;br /&gt;
Ein Topic könnte so lauten:&lt;br /&gt;
&#039;&#039;&#039;zuHause/1OG/Kueche/Licht/state&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Dieses Topic böte sich geradezu an, den Zustand des Küchenlichts im 1. Stock reinzuschreiben.&lt;br /&gt;
&lt;br /&gt;
Unser kleiner schlauer Lichtschalter könnte in diesem Topic immer den aktuellen Zustand des Lichts notieren. In &amp;quot;MQTT-Sprechweise&amp;quot; würde man sagen, unser Client ist ein Publisher. Er veröffentlicht Informationen.&lt;br /&gt;
&lt;br /&gt;
Nehmen wir im folgenden einen Sensor:&lt;br /&gt;
&#039;&#039;&#039;zuHause/1OG/Kueche/Kuehlschrank/Temperatur/state&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Das ergäbe ein hübsches Topic für einen im Kühlschrank befindlichen Temperatursensor.&lt;br /&gt;
Auch hier hätten wir es mit einem Publisher zu tun.&lt;br /&gt;
&lt;br /&gt;
Wichtig ist hierbei, dass wir uns nicht um die Technik kümmern müssen. Auch bei der Organisation der Topics haben wir ziemlich freie Hand.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Was kann man jetzt damit anfangen? ==&lt;br /&gt;
&lt;br /&gt;
Nun wollen wir die Kühlschranktemperatur auf einem Display sehen. Vielleicht lagern wir ja empfindliche Medikamente im Kühlschrank und haben Kinder, die gerne die Kühlschranktür offen lassen?&lt;br /&gt;
&lt;br /&gt;
Wir nehmen also ein Display und klemmen das auch an unseren Broker. Jetzt möchten wir aber nicht die Temperatur publishen, das macht ja der Sensor. Wir wollen sie lesen. Also melden wir uns mit dem Display beim Broker an und &amp;quot;subscriben&amp;quot; das Topic. Wir teilen dem Broker mit, dass uns diese Information interessiert.&lt;br /&gt;
&lt;br /&gt;
Unser Display abonniert also die Temperatur. Zukünftig wird der Broker immer versuchen, unserem Display die Temperatur zu übermitteln.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ah ja. Und was ist daran toll? ==&lt;br /&gt;
&lt;br /&gt;
Nun, wie wir das Thermometer programmiert haben, wussten wir nichts von dem Display. Wir müssen auch am Thermometer gar nichts mehr verändern. Das bleibt so wie es ist.&lt;br /&gt;
&lt;br /&gt;
Wenn wir nun ein weiteres Display haben wollen, bauen wir uns eben ein zweites Display und subscriben das Topic ebenfalls beim Broker.&lt;br /&gt;
Zukünftig wird er an beide Displays die Information schicken.&lt;br /&gt;
&lt;br /&gt;
Wenn wir eine grafische Auswertung des Temperaturverlaufs wollen, dann könnten wir das Topic beim Broker zusätzlich mit FHEM subscriben. Temperatur bekommen, in Logfile schreiben, Plot, fertig.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Immer noch: warum ist das so toll? ==&lt;br /&gt;
&lt;br /&gt;
Nun, bei der Konzeption von MQTT hat man Wert darauf gelegt, dass es ohne große Ressourcen auskommt. Das bedeutet für uns, dass es für viele &amp;quot;Bastelhardware&amp;quot; (Arduino etc.) fertige Libraries gibt. Ich zeige das später. Auch wer gerne mit Javascript, Java, Perl, Python programmiert, findet gut funktionierende Bibliotheken. &lt;br /&gt;
Für den &amp;quot;ambitionierten Bastler&amp;quot; bedeutet dies:&lt;br /&gt;
Wir können Geräte bauen und programmieren, die sich selbstständig miteinander unterhalten. Ein Taster der Licht an einem entfernten Aktor einschaltet, ist kein Problem. Und zwar ohne FHEM hiermit zu belasten oder es auch nur zu brauchen.&lt;br /&gt;
Wir können also sehr schnell unsere Kühlschranktemperatur mit diversen Programmiersprachen auf einer Unzahl von Geräten lesen und auswerten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Cool, was braucht man? ==&lt;br /&gt;
&lt;br /&gt;
Einen MQTT Broker; z.B. Mosquitto.&lt;br /&gt;
Für den Mikrocontroller der eigenen Wahl eine passende Library. Für Arduinos böte sich der PubSubClient an&lt;br /&gt;
Ggfs. ein Analyse-Tool wie MQTT.fx&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Nachteile ==&lt;br /&gt;
&lt;br /&gt;
=== Single Point of Failure ===&lt;br /&gt;
&lt;br /&gt;
Wo Licht ist, ist bekanntermaßen auch Schatten. Für uns, da wir FHEM zur Haussteuerung einsetzen, stellt sich die erste Frage, warum man seine Geräte nicht einfach gleich an FHEM anbindet, sondern erst noch einen MQTT Broker (letztlich noch ein Stück Software) extra davor setzt.&lt;br /&gt;
Möglicher Grund:&lt;br /&gt;
MQTT ist besser ausgereift als jedes selbst gestricke Protokoll. Es ist sogar ISO Standard. Es gibt viele Tools und Hilfestellungen dafür; eigene Intelligenz den Geräten beizubringen ist auch recht einfach.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Sicherheit ===&lt;br /&gt;
&lt;br /&gt;
Prinzipiell ist MQTT ebenso sicher wie eine Postkarte. Solange man es nicht extra absichert, kann jeder der im eigenen LAN ist (und die Adresse vom Broker kennt) alle Topics mitlesen.&lt;br /&gt;
meinHaus/Flur/Haustuer:open / close&lt;br /&gt;
Ist da nicht wirklich schlau! &lt;br /&gt;
Abhilfe:&lt;br /&gt;
Zunächst kann man erst mal einen Username / Passwort vergeben. Da ist zwar auch noch lange nicht sicher, aber zumindest steigert es den Aufwand schon mal. Jetzt muss man zumindest schon mal Pakete sniffen und verstehen, um unbefugt zu lesen oder gar zu publishen.&lt;br /&gt;
&lt;br /&gt;
TLS&lt;br /&gt;
Um wirklich sicher zu werden, führt kein Weg an TLS vorbei. Leider kann z.B. ein Arduino das schlicht nicht mehr. Irgendwo machen sich der Speicher und die Rechenleistung dann doch bemerkbar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Änderung der Topic Hierarchie ===&lt;br /&gt;
Ja, das ist ein Problem. Wenn man die Hierarchie der Topics ändern will, wird man in den seltensten Fällen drum rum kommen, seinen Programmcode (Arduino..,) anzupassen, neu zu kompilieren und wieder hoch zu laden.&lt;br /&gt;
Gleiches gilt, wenn sich z.B. die IP Adresse des Brokers ändert.&lt;br /&gt;
&lt;br /&gt;
=== Netzwerktraffic ===&lt;br /&gt;
Eine weitere Frage, die man sich stellen kann ist eine grundsätzliche:&lt;br /&gt;
Welchen Sinn hat es, sein Netzwerk (insbesondere WLAN) mit so Dingen wie Sensordaten zuzukleistern. Das ist nicht völlig unberechtigt. MySensors ist für viele kleine batteriebetriebenen Sensoren vermutlich eine deutlich bessere Wahl. Sensoren mit Akku in ein WLAN einzubinden, ist technisch eine echte Herausforderung. De große Vorteil ist aber, dass man sein WLAN im Fall des Reichweitenendes einfach erweitern kann. WLAN-Repeater, Sache gut.&lt;br /&gt;
&lt;br /&gt;
== Ausblick ==&lt;br /&gt;
Hier endet erst mal der kurze Überblick. Wer neugierig geworden ist, darf sich auf viele weitere spannenden Themen freuen:&lt;br /&gt;
&lt;br /&gt;
=== QoS ===&lt;br /&gt;
Ein weiteres Feature sind die QoS Level von MQTT.&lt;br /&gt;
 * QoS Level 0: ist eine Art fire and forget. Ob die Daten ankommen, wird nicht weiter geprüft&lt;br /&gt;
 * QoS Level 1: garantiert die Zustellung der Nachricht; es kann aber auch passieren, dass eine Nachricht öfter zugestellt und empfangen wird&lt;br /&gt;
 * QoS Level 3: Hier wird garantiert, dass jede Nachricht &#039;&#039;&#039;genau 1x&#039;&#039;&#039; bei den Empfängern ankommt&lt;br /&gt;
&lt;br /&gt;
=== Retained Messages ===&lt;br /&gt;
Auch eine lustige Sache, lernen wir später kennen. Aber ein Beispiel möchte ich dennoch schon schildern: Wir basteln uns später den oben angesprochenen Temperatursensor und das zugehörige Display. Das erweitern wir um eine blinkende LED, wenn eine bestimmte Temperatur überschritten wird. Quizfrage: woher kennt das Display den gewünschten Schwellenwert? Freilich könnte man ihn im Programmcode hinterlegen. Aber dann ist er fest verdrahtet. Wenn wir ihn einfach nur normal publishen würden, würde das Display ihn erst kennen, wenn der Schwellwert gepublished würde nachdem das Display mit dem Broker verbunden war... Hier kommen retained Messages. Diese werden auch beim Verbinden eines Subscribers gesendet, obwohl es da keine Änderung gab.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
* [http://mqtt.org Offizielle Homepage von MQTT, englisch]&lt;br /&gt;
* [http://www.hivemq.com/blog/mqtt-essentials-part-1-introducing-mqtt, Sehr gute Einführung, englisch, sind 5 lesenswerte Teile]&lt;br /&gt;
* [https://www.heise.de/developer/artikel/MQTT-Protokoll-fuer-das-Internet-der-Dinge-2168152.html Ein Exkurs von Heise mit Beispielen, deusch, sehr lesenswert]&lt;br /&gt;
* [https://forum.fhem.de/index.php/topic,69230.0.html Diskussionsthread im Forum]&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung&amp;diff=20769</id>
		<title>MQTT Einführung</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung&amp;diff=20769"/>
		<updated>2017-03-18T16:45:01Z</updated>

		<summary type="html">&lt;p&gt;Rince: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
= MQTT =&lt;br /&gt;
&lt;br /&gt;
Message Queue Telemetry Transport&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Was ist das? ==&lt;br /&gt;
&lt;br /&gt;
Es handelt sich um ein Protokoll um Daten unter verschiedenen Geräten zu übermitteln. MQTT funktioniert z.B. über eine TCP/IP Verbindung. &lt;br /&gt;
(Für die, die etwas verbal posen wollen: Man nennt das M2M, Machine to Machine; im Übrigen handelt es sich bei MQTT um ein Transportprotokoll.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau ==&lt;br /&gt;
&lt;br /&gt;
Herzstück des eigenen MQTT Netzes ist ein Broker. Die mit dem Broker verbundenen Geräte nennen wir der Einfachheit halber mal Clients. (stimmt nicht ganz, aber später lernen wir das genauer kennen)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== So tickt MQTT ==&lt;br /&gt;
&lt;br /&gt;
Wir schreiben/schicken einfach eine Nachricht an den Broker. Wer wann die Nachricht abholt und liest, interessiert an dieser Stelle überhaupt nicht. Das ist einer der großen Vorteile.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ordnung in das Chaos ==&lt;br /&gt;
&lt;br /&gt;
Worin liegt nun der Vorteil? Und wie kann nun jemand eine Nachricht lesen?&lt;br /&gt;
Hier beginnt das raffinierte Konzept von MQTT:&lt;br /&gt;
Wir stellen nicht einfach nur Daten dem Broker zur Verfügung. Wir organisieren sie auch selbst. Das Zauberwort hierfür nennt sich &amp;quot;Topic&amp;quot;. &lt;br /&gt;
Kann man sich so ähnlich vorstellen wie einen Verzeichnisbaum unter Windows, oder wie eine Datei auf einem Webserver.&lt;br /&gt;
Ein anderes Bild für einen &amp;quot;Topic&amp;quot; wäre eine Art schwarzes Brett.&lt;br /&gt;
&lt;br /&gt;
Ein Topic könnte so lauten:&lt;br /&gt;
&#039;&#039;&#039;zuHause/1OG/Kueche/Licht/state&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Dieses Topic böte sich geradezu an, den Zustand des Küchenlichts im 1. Stock reinzuschreiben.&lt;br /&gt;
&lt;br /&gt;
Unser kleiner schlauer Lichtschalter könnte in diesem Topic immer den aktuellen Zustand des Lichts notieren. In &amp;quot;MQTT-Sprechweise&amp;quot; würde man sagen, unser Client ist ein Publisher. Er veröffentlicht Informationen.&lt;br /&gt;
&lt;br /&gt;
Nehmen wir im folgenden einen Sensor:&lt;br /&gt;
&#039;&#039;&#039;zuHause/1OG/Kueche/Kuehlschrank/Temperatur/state&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Das ergäbe ein hübsches Topic für einen im Kühlschrank befindlichen Temperatursensor.&lt;br /&gt;
Auch hier hätten wir es mit einem Publisher zu tun.&lt;br /&gt;
&lt;br /&gt;
Wichtig ist hierbei, dass wir uns nicht um die Technik kümmern müssen. Auch bei der Organisation der Topics haben wir ziemlich freie Hand.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Was kann man jetzt damit anfangen? ==&lt;br /&gt;
&lt;br /&gt;
Nun wollen wir die Kühlschranktemperatur auf einem Display sehen. Vielleicht lagern wir ja empfindliche Medikamente im Kühlschrank und haben Kinder, die gerne die Kühlschranktür offen lassen?&lt;br /&gt;
&lt;br /&gt;
Wir nehmen also ein Display und klemmen das auch an unseren Broker. Jetzt möchten wir aber nicht die Temperatur publishen, das macht ja der Sensor. Wir wollen sie lesen. Also melden wir uns mit dem Display beim Broker an und &amp;quot;subscriben&amp;quot; das Topic. Wir teilen dem Broker mit, dass uns diese Information interessiert.&lt;br /&gt;
&lt;br /&gt;
Unser Display abonniert also die Temperatur. Zukünftig wird der Broker immer versuchen, unserem Display die Temperatur zu übermitteln.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ah ja. Und was ist daran toll? ==&lt;br /&gt;
&lt;br /&gt;
Nun, wie wir das Thermometer programmiert haben, wussten wir nichts von dem Display. Wir müssen auch am Thermometer gar nichts mehr verändern. Das bleibt so wie es ist.&lt;br /&gt;
&lt;br /&gt;
Wenn wir nun ein weiteres Display haben wollen, bauen wir uns eben ein zweites Display und subscriben das Topic ebenfalls beim Broker.&lt;br /&gt;
Zukünftig wird er an beide Displays die Information schicken.&lt;br /&gt;
&lt;br /&gt;
Wenn wir eine grafische Auswertung des Temperaturverlaufs wollen, dann könnten wir das Topic beim Broker zusätzlich mit FHEM subscriben. Temperatur bekommen, in Logfile schreiben, Plot, fertig.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Immer noch: warum ist das so toll? ==&lt;br /&gt;
&lt;br /&gt;
Nun, bei der Konzeption von MQTT hat man Wert darauf gelegt, dass es ohne große Ressourcen auskommt. Das bedeutet für uns, dass es für viele &amp;quot;Bastelhardware&amp;quot; (Arduino etc.) fertige Libraries gibt. Ich zeige das später. Auch wer gerne mit Javascript, Java, Perl, Python programmiert, findet gut funktionierende Bibliotheken. &lt;br /&gt;
Für den &amp;quot;ambitionierten Bastler&amp;quot; bedeutet dies:&lt;br /&gt;
Wir können Geräte bauen und programmieren, die sich selbstständig miteinander unterhalten. Ein Taster der Licht an einem entfernten Aktor einschaltet, ist kein Problem. Und zwar ohne FHEM hiermit zu belasten oder es auch nur zu brauchen.&lt;br /&gt;
Wir können also sehr schnell unsere Kühlschranktemperatur mit diversen Programmiersprachen auf einer Unzahl von Geräten lesen und auswerten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Cool, was braucht man? ==&lt;br /&gt;
&lt;br /&gt;
Einen MQTT Broker; z.B. Mosquitto.&lt;br /&gt;
Für den Mikrocontroller der eigenen Wahl eine passende Library. Für Arduinos böte sich der PubSubClient an&lt;br /&gt;
Ggfs. ein Analyse-Tool wie MQTT.fx&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Nachteile ==&lt;br /&gt;
&lt;br /&gt;
=== Single Point of Failure ===&lt;br /&gt;
&lt;br /&gt;
Wo Licht ist, ist bekanntermaßen auch Schatten. Für uns, da wir FHEM zur Haussteuerung einsetzen, stellt sich die erste Frage, warum man seine Geräte nicht einfach gleich an FHEM anbindet, sondern erst noch einen MQTT Broker (letztlich noch ein Stück Software) extra davor setzt.&lt;br /&gt;
Möglicher Grund:&lt;br /&gt;
MQTT ist besser ausgereift als jedes selbst gestricke Protokoll. Es ist sogar ISO Standard. Es gibt viele Tools und Hilfestellungen dafür; eigene Intelligenz den Geräten beizubringen ist auch recht einfach.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Sicherheit ===&lt;br /&gt;
&lt;br /&gt;
Prinzipiell ist MQTT ebenso sicher wie eine Postkarte. Solange man es nicht extra absichert, kann jeder der im eigenen LAN ist (und die Adresse vom Broker kennt) alle Topics mitlesen.&lt;br /&gt;
meinHaus/Flur/Haustuer:open / close&lt;br /&gt;
Ist da nicht wirklich schlau! &lt;br /&gt;
Abhilfe:&lt;br /&gt;
Zunächst kann man erst mal einen Username / Passwort vergeben. Da ist zwar auch noch lange nicht sicher, aber zumindest steigert es den Aufwand schon mal. Jetzt muss man zumindest schon mal Pakete sniffen und verstehen, um unbefugt zu lesen oder gar zu publishen.&lt;br /&gt;
&lt;br /&gt;
TLS&lt;br /&gt;
Um wirklich sicher zu werden, führt kein Weg an TLS vorbei. Leider kann z.B. ein Arduino das schlicht nicht mehr. Irgendwo machen sich der Speicher und die Rechenleistung dann doch bemerkbar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Änderung der Topic Hierarchie ===&lt;br /&gt;
Ja, das ist ein Problem. Wenn man die Hierarchie der Topics ändern will, wird man in den seltensten Fällen drum rum kommen, seinen Programmcode (Arduino..,) anzupassen, neu zu kompilieren und wieder hoch zu laden.&lt;br /&gt;
Gleiches gilt, wenn sich z.B. die IP Adresse des Brokers ändert.&lt;br /&gt;
&lt;br /&gt;
=== Netzwerktraffic ===&lt;br /&gt;
Eine weitere Frage, die man sich stellen kann ist eine grundsätzliche:&lt;br /&gt;
Welchen Sinn hat es, sein Netzwerk (insbesondere WLAN) mit so Dingen wie Sensordaten zuzukleistern. Das ist nicht völlig unberechtigt. MySensors ist für viele kleine batteriebetriebenen Sensoren vermutlich eine deutlich bessere Wahl. Sensoren mit Akku in ein WLAN einzubinden, ist technisch eine echte Herausforderung. De große Vorteil ist aber, dass man sein WLAN im Fall des Reichweitenendes einfach erweitern kann. WLAN-Repeater, Sache gut.&lt;br /&gt;
&lt;br /&gt;
== Ausblik ==&lt;br /&gt;
Hier endet erst mal der kurze Überblick. Wer neugierig geworden ist, darf sich auf viele weitere spannenden Themen freuen:&lt;br /&gt;
&lt;br /&gt;
=== QoS ===&lt;br /&gt;
Ein weiteres Feature sind die QoS Level von MQTT.&lt;br /&gt;
 * QoS Level 0: ist eine Art fire and forget. Ob die Daten ankommen, wird nicht weiter geprüft&lt;br /&gt;
 * QoS Level 1: garantiert die Zustellung der Nachricht; es kann aber auch passieren, dass eine Nachricht öfter zugestellt und empfangen wird&lt;br /&gt;
 * QoS Level 3: Hier wird garantiert, dass jede Nachricht &#039;&#039;&#039;genau 1x&#039;&#039;&#039; bei den Empfängern ankommt&lt;br /&gt;
&lt;br /&gt;
=== Retained Messages ===&lt;br /&gt;
Auch eine lustige Sache, lernen wir später kennen. Aber ein Beispiel möchte ich dennoch schon schildern: Wir basteln uns später den oben angesprochenen Temperatursensor und das zugehörige Display. Das erweitern wir um eine blinkende LED, wenn eine bestimmte Temperatur überschritten wird. Quizzfrage: woher kennt das Display den gewünschten Schwellenwert? Freilich könnte man ihn im Programmcode hinterlegen. Aber dann ist er fest verdrahtet. Wenn wir ihn einfach nur normal publishen würden, würde das Display ihn erst kennen, wenn der Schwellwert gepublished würde nachdem das Display mit dem Broker verbunden war... Hier kommen retained Messages. Diese werden auch beim Verbinden eines Subscribers gesendet, obwohl es da keine Änderung gab.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
* [http://mqtt.org Offizielle Homepage von MQTT, englisch]&lt;br /&gt;
* [http://www.hivemq.com/blog/mqtt-essentials-part-1-introducing-mqtt, Sehr gute Einführung, englisch, sind 5 lesenswerte Teile]&lt;br /&gt;
* [https://www.heise.de/developer/artikel/MQTT-Protokoll-fuer-das-Internet-der-Dinge-2168152.html Ein Exkurs von Heise mit Beispielen, deusch, sehr lesenswert]&lt;br /&gt;
* [https://forum.fhem.de/index.php/topic,69230.0.html Diskussionsthread im Forum]&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung&amp;diff=20768</id>
		<title>MQTT Einführung</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung&amp;diff=20768"/>
		<updated>2017-03-18T16:44:11Z</updated>

		<summary type="html">&lt;p&gt;Rince: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
= MQTT =&lt;br /&gt;
&lt;br /&gt;
Message Queue Telemetry Transport&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Was ist das? ==&lt;br /&gt;
&lt;br /&gt;
Es handelt sich um ein Protokoll um Daten unter verschiedenen Geräten zu übermitteln. MQTT funktioniert z.B. über eine TCP/IP Verbindung. &lt;br /&gt;
(Für die, die etwas verbal posen wollen: Man nennt das M2M, Machine to Machine; im Übrigen handelt es sich bei MQTT um ein Transportprotokoll.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau ==&lt;br /&gt;
&lt;br /&gt;
Herzstück des eigenen MQTT Netzes ist ein Broker. Die mit dem Broker verbundenen Geräte nennen wir der Einfachheit halber mal Clients. (stimmt nicht ganz, aber später lernen wir das genauer kennen)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== So tickt MQTT ==&lt;br /&gt;
&lt;br /&gt;
Wir schreiben/schicken einfach eine Nachricht an den Broker. Wer wann die Nachricht abholt und liest, interessiert an dieser Stelle überhaupt nicht. Das ist einer der großen Vorteile.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ordnung in das Chaos ==&lt;br /&gt;
&lt;br /&gt;
Worin liegt nun der Vorteil? Und wie kann nun jemand eine Nachricht lesen?&lt;br /&gt;
Hier beginnt das raffinierte Konzept von MQTT:&lt;br /&gt;
Wir stellen nicht einfach nur Daten dem Broker zur Verfügung. Wir organisieren sie auch selbst. Das Zauberwort hierfür nennt sich &amp;quot;Topic&amp;quot;. &lt;br /&gt;
Kann man sich so ähnlich vorstellen wie einen Verzeichnisbaum unter Windows, oder wie eine Datei auf einem Webserver.&lt;br /&gt;
Ein anderes Bild für einen &amp;quot;Topic&amp;quot; wäre eine Art schwarzes Brett.&lt;br /&gt;
&lt;br /&gt;
Ein Topic könnte so lauten:&lt;br /&gt;
&#039;&#039;&#039;zuHause/1OG/Kueche/Licht/state&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Dieses Topic böte sich geradezu an, den Zustand des Küchenlichts im 1. Stock reinzuschreiben.&lt;br /&gt;
&lt;br /&gt;
Unser kleiner schlauer Lichtschalter könnte in diesem Topic immer den aktuellen Zustand des Lichts notieren. In &amp;quot;MQTT-Sprechweise&amp;quot; würde man sagen, unser Client ist ein Publisher. Er veröffentlicht Informationen.&lt;br /&gt;
&lt;br /&gt;
Nehmen wir im folgenden einen Sensor:&lt;br /&gt;
&#039;&#039;&#039;zuHause/1OG/Kueche/Kuehlschrank/Temperatur/state&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Das ergäbe ein hübsches Topic für einen im Kühlschrank befindlichen Temperatursensor.&lt;br /&gt;
Auch hier hätten wir es mit einem Publisher zu tun.&lt;br /&gt;
&lt;br /&gt;
Wichtig ist hierbei, dass wir uns nicht um die Technik kümmern müssen. Auch bei der Organisation der Topics haben wir ziemlich freie Hand.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Was kann man jetzt damit anfangen? ==&lt;br /&gt;
&lt;br /&gt;
Nun wollen wir die Kühlschranktemperatur auf einem Display sehen. Vielleicht lagern wir ja empfindliche Medikamente im Kühlschrank und haben Kinder, die gerne die Kühlschranktür offen lassen?&lt;br /&gt;
&lt;br /&gt;
Wir nehmen also ein Display und klemmen das auch an unseren Broker. Jetzt möchten wir aber nicht die Temperatur publishen, das macht ja der Sensor. Wir wollen sie lesen. Also melden wir uns mit dem Display beim Broker an und &amp;quot;subscriben&amp;quot; das Topic. Wir teilen dem Broker mit, dass uns diese Information interessiert.&lt;br /&gt;
&lt;br /&gt;
Unser Display abonniert also die Temperatur. Zukünftig wird der Broker immer versuchen, unserem Display die Temperatur zu übermitteln.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ah ja. Und was ist daran toll? ==&lt;br /&gt;
&lt;br /&gt;
Nun, wie wir das Thermometer programmiert haben, wussten wir nichts von dem Display. Wir müssen auch am Thermometer gar nichts mehr verändern. Das bleibt so wie es ist.&lt;br /&gt;
&lt;br /&gt;
Wenn wir nun ein weiteres Display haben wollen, bauen wir uns eben ein zweites Display und subscriben das Topic ebenfalls beim Broker.&lt;br /&gt;
Zukünftig wird er an beide Displays die Information schicken.&lt;br /&gt;
&lt;br /&gt;
Wenn wir eine grafische Auswertung des Temperaturverlaufs wollen, dann könnten wir das Topic beim Broker zusätzlich mit FHEM subscriben. Temperatur bekommen, in Logfile schreiben, Plot, fertig.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Immer noch: warum ist das so toll? ==&lt;br /&gt;
&lt;br /&gt;
Nun, bei der Konzeption von MQTT hat man Wert darauf gelegt, dass es ohne große Ressourcen auskommt. Das bedeutet für uns, dass es für viele &amp;quot;Bastelhardware&amp;quot; (Arduino etc.) fertige Libraries gibt. Ich zeige das später. Auch wer gerne mit Javascript, Java, Perl, Python programmiert, findet gut funktionierende Bibliotheken. &lt;br /&gt;
Für den &amp;quot;ambitionierten Bastler&amp;quot; bedeutet dies:&lt;br /&gt;
Wir können Geräte bauen und programmieren, die sich selbstständig miteinander unterhalten. Ein Taster der Licht an einem entfernten Aktor einschaltet, ist kein Problem. Und zwar ohne FHEM hiermit zu belasten oder es auch nur zu brauchen.&lt;br /&gt;
Wir können also sehr schnell unsere Kühlschranktemperatur mit diversen Programmiersprachen auf einer Unzahl von Geräten lesen und auswerten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Cool, was braucht man? ==&lt;br /&gt;
&lt;br /&gt;
Einen MQTT Broker; z.B. Mosquitto.&lt;br /&gt;
Für den Mikrocontroller der eigenen Wahl eine passende Library. Für Arduinos böte sich der PubSubClient an&lt;br /&gt;
Ggfs. ein Analyse-Tool wie MQTT.fx&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Nachteile ==&lt;br /&gt;
&lt;br /&gt;
=== Single Point of Failure ===&lt;br /&gt;
&lt;br /&gt;
Wo Licht ist, ist bekanntermaßen auch Schatten. Für uns, da wir FHEM zur Haussteuerung einsetzen, stellt sich die erste Frage, warum man seine Geräte nicht einfach gleich an FHEM anbindet, sondern erst noch einen MQTT Broker (letztlich noch ein Stück Software) extra davor setzt.&lt;br /&gt;
Möglicher Grund:&lt;br /&gt;
MQTT ist besser ausgereift als jedes selbst gestricke Protokoll. Es ist sogar ISO Standard. Es gibt viele Tools und Hilfestellungen dafür; eigene Intelligenz den Geräten beizubringen ist auch recht einfach.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Sicherheit ===&lt;br /&gt;
&lt;br /&gt;
Prinzipiell ist MQTT ebenso sicher wie eine Postkarte. Solange man es nicht extra absichert, kann jeder der im eigenen LAN ist (und die Adresse vom Broker kennt) alle Topics mitlesen.&lt;br /&gt;
meinHaus/Flur/Haustuer:open / close&lt;br /&gt;
Ist da nicht wirklich schlau! &lt;br /&gt;
Abhilfe:&lt;br /&gt;
Zunächst kann man erst mal einen Username / Passwort vergeben. Da ist zwar auch noch lange nicht sicher, aber zumindest steigert es den Aufwand schon mal. Jetzt muss man zumindest schon mal Pakete sniffen und verstehen, um unbefugt zu lesen oder gar zu publishen.&lt;br /&gt;
&lt;br /&gt;
TLS&lt;br /&gt;
Um wirklich sicher zu werden, führt kein Weg an TLS vorbei. Leider kann z.B. ein Arduino das schlicht nicht mehr. Irgendwo machen sich der Speicher und die Rechenleistung dann doch bemerkbar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Änderung der Topic Hierarchie ===&lt;br /&gt;
Ja, das ist ein Problem. Wenn man die Hierarchie der Topics ändern will, wird man in den seltensten Fällen drum rum kommen, seinen Programmcode (Arduino..,) anzupassen, neu zu kompilieren und wieder hoch zu laden.&lt;br /&gt;
Gleiches gilt, wenn sich z.B. die IP Adresse des Brokers ändert.&lt;br /&gt;
&lt;br /&gt;
=== Netzwerktraffic ===&lt;br /&gt;
Eine weitere Frage, die man sich stellen kann ist eine grundsätzliche:&lt;br /&gt;
Welchen Sinn hat es, sein Netzwerk (insbesondere WLAN) mit so Dingen wie Sensordaten zuzukleistern. Das ist nicht völlig unberechtigt. MySensors ist für viele kleine batteriebetriebenen Sensoren vermutlich eine deutlich bessere Wahl. Sensoren mit Akku in ein WLAN einzubinden, ist technisch eine echte Herausforderung. De große Vorteil ist aber, dass man sein WLAN im Fall des Reichweitenendes einfach erweitern kann. WLAN-Repeater, Sache gut.&lt;br /&gt;
&lt;br /&gt;
== Ausblik ==&lt;br /&gt;
Hier endet erst mal der kurze Überblick. Wer neugierig geworden ist, darf sich auf viele weitere spannenden Themen freuen:&lt;br /&gt;
&lt;br /&gt;
=== QoS ===&lt;br /&gt;
Ein weiteres Feature sind die QoS Level von MQTT.&lt;br /&gt;
 * QoS Level 0: ist eine Art fire and forget. Ob die Daten ankommen, wird nicht weiter geprüft&lt;br /&gt;
 * QoS Level 1: garantiert die Zustellung der Nachricht; es kann aber auch passieren, dass eine Nachricht öfter zugestellt und empfangen wird&lt;br /&gt;
 * QoS Level 3: Hier wird garantiert, dass jede Nachricht &#039;&#039;&#039;genau 1x&#039;&#039;&#039; bei den Empfängern ankommt&lt;br /&gt;
&lt;br /&gt;
=== Retained Messages ===&lt;br /&gt;
Auch eine lustige Sache, lernen wir später kennen. Aber ein Beispiel möchte ich dennoch schon schildern: Wir basteln uns später den oben angesprochenen Temperatursensor und das zugehörige Display. Das erweitern wir um eine blinkende LED, wenn eine bestimmte Temperatur überschritten wird. Quizzfrage: woher kennt das Display den gewünschten Schwellenwert? Freilich könnte man ihn im Programmcode hinterlegen. Aber dann ist er fest verdrahtet. Wenn wir ihn einfach nur normal publishen würden, würde das Display ihn erst kennen, wenn der Schwellwert gepublished würde nachdem das Display mit dem Broker verbunden war... Hier kommen retained Messages. Diese werden auch beim Verbinden eines Subscribers gesendet, obwohl es da keine Änderung gab.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
* [http://mqtt.org Offizielle Homepage von MQTT, englisch]&lt;br /&gt;
* [http://www.hivemq.com/blog/mqtt-essentials-part-1-introducing-mqtt, englisch, sind 5 lesenswerte Teile]&lt;br /&gt;
* [https://www.heise.de/developer/artikel/MQTT-Protokoll-fuer-das-Internet-der-Dinge-2168152.html Ein exkurs von Heise mit Beispielen, deusch, sehr lesenswert]&lt;br /&gt;
* [https://forum.fhem.de/index.php/topic,69230.0.html Diskussionsthread im Forum]&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung&amp;diff=20767</id>
		<title>MQTT Einführung</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MQTT_Einf%C3%BChrung&amp;diff=20767"/>
		<updated>2017-03-18T16:38:20Z</updated>

		<summary type="html">&lt;p&gt;Rince: Die Seite wurde neu angelegt: „ = MQTT =  Message Queue Telemetry Transport   == Was ist das? ==  Es handelt sich um ein Protokoll um Daten unter verschiedenen Geräten zu übermitteln. MQTT…“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
= MQTT =&lt;br /&gt;
&lt;br /&gt;
Message Queue Telemetry Transport&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Was ist das? ==&lt;br /&gt;
&lt;br /&gt;
Es handelt sich um ein Protokoll um Daten unter verschiedenen Geräten zu übermitteln. MQTT funktioniert z.B. über eine TCP/IP Verbindung. &lt;br /&gt;
(Für die, die etwas verbal posen wollen: Man nennt das M2M, Machine to Machine; im Übrigen handelt es sich bei MQTT um ein Transportprotokoll.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau ==&lt;br /&gt;
&lt;br /&gt;
Herzstück des eigenen MQTT Netzes ist ein Broker. Die mit dem Broker verbundenen Geräte nennen wir der Einfachheit halber mal Clients. (stimmt nicht ganz, aber später lernen wir das genauer kennen)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== So tickt MQTT ==&lt;br /&gt;
&lt;br /&gt;
Wir schreiben/schicken einfach eine Nachricht an den Broker. Wer wann die Nachricht abholt und liest, interessiert an dieser Stelle überhaupt nicht. Das ist einer der großen Vorteile.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ordnung in das Chaos ==&lt;br /&gt;
&lt;br /&gt;
Worin liegt nun der Vorteil? Und wie kann nun jemand eine Nachricht lesen?&lt;br /&gt;
Hier beginnt das raffinierte Konzept von MQTT:&lt;br /&gt;
Wir stellen nicht einfach nur Daten dem Broker zur Verfügung. Wir organisieren sie auch selbst. Das Zauberwort hierfür nennt sich &amp;quot;Topic&amp;quot;. &lt;br /&gt;
Kann man sich so ähnlich vorstellen wie einen Verzeichnisbaum unter Windows, oder wie eine Datei auf einem Webserver.&lt;br /&gt;
Ein anderes Bild für einen &amp;quot;Topic&amp;quot; wäre eine Art schwarzes Brett.&lt;br /&gt;
&lt;br /&gt;
Ein Topic könnte so lauten:&lt;br /&gt;
&#039;&#039;&#039;zuHause/1OG/Kueche/Licht/state&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Dieses Topic böte sich geradezu an, den Zustand des Küchenlichts im 1. Stock reinzuschreiben.&lt;br /&gt;
&lt;br /&gt;
Unser kleiner schlauer Lichtschalter könnte in diesem Topic immer den aktuellen Zustand des Lichts notieren. In &amp;quot;MQTT-Sprechweise&amp;quot; würde man sagen, unser Client ist ein Publisher. Er veröffentlicht Informationen.&lt;br /&gt;
&lt;br /&gt;
Nehmen wir im folgenden einen Sensor:&lt;br /&gt;
&#039;&#039;&#039;zuHause/1OG/Kueche/Kuehlschrank/Temperatur/state&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Das ergäbe ein hübsches Topic für einen im Kühlschrank befindlichen Temperatursensor.&lt;br /&gt;
Auch hier hätten wir es mit einem Publisher zu tun.&lt;br /&gt;
&lt;br /&gt;
Wichtig ist hierbei, dass wir uns nicht um die Technik kümmern müssen. Auch bei der Organisation der Topics haben wir ziemlich freie Hand.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Was kann man jetzt damit anfangen? ==&lt;br /&gt;
&lt;br /&gt;
Nun wollen wir die Kühlschranktemperatur auf einem Display sehen. Vielleicht lagern wir ja empfindliche Medikamente im Kühlschrank und haben Kinder, die gerne die Kühlschranktür offen lassen?&lt;br /&gt;
&lt;br /&gt;
Wir nehmen also ein Display und klemmen das auch an unseren Broker. Jetzt möchten wir aber nicht die Temperatur publishen, das macht ja der Sensor. Wir wollen sie lesen. Also melden wir uns mit dem Display beim Broker an und &amp;quot;subscriben&amp;quot; das Topic. Wir teilen dem Broker mit, dass uns diese Information interessiert.&lt;br /&gt;
&lt;br /&gt;
Unser Display abonniert also die Temperatur. Zukünftig wird der Broker immer versuchen, unserem Display die Temperatur zu übermitteln.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ah ja. Und was ist daran toll? ==&lt;br /&gt;
&lt;br /&gt;
Nun, wie wir das Thermometer programmiert haben, wussten wir nichts von dem Display. Wir müssen auch am Thermometer gar nichts mehr verändern. Das bleibt so wie es ist.&lt;br /&gt;
&lt;br /&gt;
Wenn wir nun ein weiteres Display haben wollen, bauen wir uns eben ein zweites Display und subscriben das Topic ebenfalls beim Broker.&lt;br /&gt;
Zukünftig wird er an beide Displays die Information schicken.&lt;br /&gt;
&lt;br /&gt;
Wenn wir eine grafische Auswertung des Temperaturverlaufs wollen, dann könnten wir das Topic beim Broker zusätzlich mit FHEM subscriben. Temperatur bekommen, in Logfile schreiben, Plot, fertig.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Immer noch: warum ist das so toll? ==&lt;br /&gt;
&lt;br /&gt;
Nun, bei der Konzeption von MQTT hat man Wert darauf gelegt, dass es ohne große Ressourcen auskommt. Das bedeutet für uns, dass es für viele &amp;quot;Bastelhardware&amp;quot; (Arduino etc.) fertige Libraries gibt. Ich zeige das später. Auch wer gerne mit Javascript, Java, Perl, Python programmiert, findet gut funktionierende Bibliotheken. &lt;br /&gt;
Für den &amp;quot;ambitionierten Bastler&amp;quot; bedeutet dies:&lt;br /&gt;
Wir können Geräte bauen und programmieren, die sich selbstständig miteinander unterhalten. Ein Taster der Licht an einem entfernten Aktor einschaltet, ist kein Problem. Und zwar ohne FHEM hiermit zu belasten oder es auch nur zu brauchen.&lt;br /&gt;
Wir können also sehr schnell unsere Kühlschranktemperatur mit diversen Programmiersprachen auf einer Unzahl von Geräten lesen und auswerten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Cool, was braucht man? ==&lt;br /&gt;
&lt;br /&gt;
Einen MQTT Broker; z.B. Mosquitto.&lt;br /&gt;
Für den Mikrocontroller der eigenen Wahl eine passende Library. Für Arduinos böte sich der PubSubClient an&lt;br /&gt;
Ggfs. ein Analyse-Tool wie MQTT.fx&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Nachteile ==&lt;br /&gt;
&lt;br /&gt;
=== Single Point of Failure ===&lt;br /&gt;
&lt;br /&gt;
Wo Licht ist, ist bekanntermaßen auch Schatten. Für uns, da wir FHEM zur Haussteuerung einsetzen, stellt sich die erste Frage, warum man seine Geräte nicht einfach gleich an FHEM anbindet, sondern erst noch einen MQTT Broker (letztlich noch ein Stück Software) extra davor setzt.&lt;br /&gt;
Möglicher Grund:&lt;br /&gt;
MQTT ist besser ausgereift als jedes selbst gestricke Protokoll. Es ist sogar ISO Standard. Es gibt viele Tools und Hilfestellungen dafür; eigene Intelligenz den Geräten beizubringen ist auch recht einfach.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Sicherheit ===&lt;br /&gt;
&lt;br /&gt;
Prinzipiell ist MQTT ebenso sicher wie eine Postkarte. Solange man es nicht extra absichert, kann jeder der im eigenen LAN ist (und die Adresse vom Broker kennt) alle Topics mitlesen.&lt;br /&gt;
meinHaus/Flur/Haustuer:open / close&lt;br /&gt;
Ist da nicht wirklich schlau! &lt;br /&gt;
Abhilfe:&lt;br /&gt;
Zunächst kann man erst mal einen Username / Passwort vergeben. Da ist zwar auch noch lange nicht sicher, aber zumindest steigert es den Aufwand schon mal. Jetzt muss man zumindest schon mal Pakete sniffen und verstehen, um unbefugt zu lesen oder gar zu publishen.&lt;br /&gt;
&lt;br /&gt;
TLS&lt;br /&gt;
Um wirklich sicher zu werden, führt kein Weg an TLS vorbei. Leider kann z.B. ein Arduino das schlicht nicht mehr. Irgendwo machen sich der Speicher und die Rechenleistung dann doch bemerkbar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Änderung der Topic Hierarchie ===&lt;br /&gt;
Ja, das ist ein Problem. Wenn man die Hierarchie der Topics ändern will, wird man in den seltensten Fällen drum rum kommen, seinen Programmcode (Arduino..,) anzupassen, neu zu kompilieren und wieder hoch zu laden.&lt;br /&gt;
Gleiches gilt, wenn sich z.B. die IP Adresse des Brokers ändert.&lt;br /&gt;
&lt;br /&gt;
=== Netzwerktraffic ===&lt;br /&gt;
Eine weitere Frage, die man sich stellen kann ist eine grundsätzliche:&lt;br /&gt;
Welchen Sinn hat es, sein Netzwerk (insbesondere WLAN) mit so Dingen wie Sensordaten zuzukleistern. Das ist nicht völlig unberechtigt. MySensors ist für viele kleine batteriebetriebenen Sensoren vermutlich eine deutlich bessere Wahl. Sensoren mit Akku in ein WLAN einzubinden, ist technisch eine echte Herausforderung. De große Vorteil ist aber, dass man sein WLAN im Fall des Reichweitenendes einfach erweitern kann. WLAN-Repeater, Sache gut.&lt;br /&gt;
&lt;br /&gt;
== Ausblik ==&lt;br /&gt;
Hier endet erst mal der kurze Überblick. Wer neugierig geworden ist, darf sich auf viele weitere spannenden Themen freuen:&lt;br /&gt;
&lt;br /&gt;
=== QoS ===&lt;br /&gt;
Ein weiteres Feature sind die QoS Level von MQTT.&lt;br /&gt;
 * QoS Level 0: ist eine Art fire and forget. Ob die Daten ankommen, wird nicht weiter geprüft&lt;br /&gt;
 * QoS Level 1: garantiert die Zustellung der Nachricht; es kann aber auch passieren, dass eine Nachricht öfter zugestellt und empfangen wird&lt;br /&gt;
 * QoS Level 3: Hier wird garantiert, dass jede Nachricht &#039;&#039;&#039;genau 1x&#039;&#039;&#039; bei den Empfängern ankommt&lt;br /&gt;
&lt;br /&gt;
=== Retained Messages ===&lt;br /&gt;
Auch eine lustige Sache, lernen wir später kennen. Aber ein Beispiel möchte ich dennoch schon schildern: Wir basteln uns später den oben angesprochenen Temperatursensor und das zugehörige Display. Das erweitern wir um eine blinkende LED, wenn eine bestimmte Temperatur überschritten wird. Quizzfrage: woher kennt das Display den gewünschten Schwellenwert? Freilich könnte man ihn im Programmcode hinterlegen. Aber dann ist er fest verdrahtet. Wenn wir ihn einfach nur normal publishen würden, würde das Display ihn erst kennen, wenn der Schwellwert gepublished würde nachdem das Display mit dem Broker verbunden war... Hier kommen retained Messages. Diese werden auch beim Verbinden eines Subscribers gesendet, obwohl es da keine Änderung gab.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
* [http://mqtt.org Offizielle Homepage von MQTT, englisch]&lt;br /&gt;
* [http://www.hivemq.com/blog/mqtt-essentials-part-1-introducing-mqtt, englisch, sind 5 lesenswerte Teile]&lt;br /&gt;
* [https://www.heise.de/developer/artikel/MQTT-Protokoll-fuer-das-Internet-der-Dinge-2168152.html Ein exkurs von Heise mit Beispielen, deusch, sehr lesenswert]&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=WiiFit_Waage&amp;diff=13126</id>
		<title>WiiFit Waage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=WiiFit_Waage&amp;diff=13126"/>
		<updated>2015-12-03T11:00:49Z</updated>

		<summary type="html">&lt;p&gt;Rince: /* Konfiguration der Software */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Übersicht==&lt;br /&gt;
Dieses Python Skript baut eine Bluetooth Verbindung mit einem Wii Fit Board auf. Ist dies erledigt, schickt es das ermittelte Gewicht (in einer Dauerschleife) übers Netzwerk an FHEM.&lt;br /&gt;
{{Link2Forum|Topic=44684|LinkText=Forumsthread}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ohne eine Versionsnummerierung zu haben, nenne ich es mal 0.1 =&amp;gt; erste öffentliche Version&lt;br /&gt;
&lt;br /&gt;
==Voraussetzungen==&lt;br /&gt;
* Getestet mit Debian Wheezy.&lt;br /&gt;
* Bluetooth Stick&lt;br /&gt;
* Relais (wenn fhem das Pairing automatisch machen soll)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Konfiguration der Software===&lt;br /&gt;
Das Programm an sich benötigt eine Config-Datei.&lt;br /&gt;
&lt;br /&gt;
Beispieldatei, könnte Fass_1.json&amp;quot; genannt werden&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;BT-Adress&amp;quot;: &amp;quot;00:25:A0:40:5C:28&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_host_port&amp;quot;: &amp;quot;http://127.0.0.1:8083&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_request&amp;quot;: &amp;quot;/fhem?cmd=&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command&amp;quot;: &amp;quot;setreading%20Fass_1%20Gewicht&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Was ist hier einzustellen?&lt;br /&gt;
* &amp;quot;BTAdress&amp;quot;: Bluetoothadresse des Wii Fit Boards&lt;br /&gt;
* &amp;quot;fhem_host_port&amp;quot;: Adresse des fhem Servers, ebenso wie der Port. (Muss man also anpassen)&lt;br /&gt;
* &amp;quot;fhem_request&amp;quot;: (weiß nicht, wie es heißt), sollte aber so passen&lt;br /&gt;
* &amp;quot;fhem_command&amp;quot;: das, was fhem dann wirklich tun soll; hier: setreading Fass_1 Gewicht&lt;br /&gt;
** das Gewicht.py hängt da dann das Gewicht in dran und sendet es an fhem&lt;br /&gt;
&lt;br /&gt;
=== Aufruf ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./Gewicht.py --conf &amp;quot;Fass_1.json&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Benötigte Pakete installieren ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt-get install python-bluetooth bluez python-gobject&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Um die Adresse in Erfahrung zu bringen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ hcitool dev&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Hardware-Modding ===&lt;br /&gt;
Leider kann man kein automatisches Pairing (wie bei einer Freisprechanlage und dem Handy im Auto) einrichten. Also ich kann es jedenfalls nicht. Daher muss bei jedem Skriptaufruf (das Skript läuft dann in einer Dauerschleife) den kleinen roten Pairing Knopf drücken. Der ist intelligenterweise unter der Batterieabdeckung.&lt;br /&gt;
&lt;br /&gt;
Lösung:&lt;br /&gt;
&lt;br /&gt;
Auf die Rückseite der Platine werden bei dem Taster 2 Drähte angelötet. Nun kann man z.B. mit einem Relais einfach kurz den Kontakt schließen lassen, so dass das Pairing am Board eingeleitet wird. Vom Timing her empfiehlt es sich (wenn man es von Hand mal ausprobieren will ohne Löterei), zuerst das Wii Fit Board in den Pairing Modus zu bringen, dann das Skript zu starten.&lt;br /&gt;
&lt;br /&gt;
==Programmcode==&lt;br /&gt;
z,B. mit&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ nano Gewicht.py&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Direkt im Wunschverzeichnis ablegen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
&lt;br /&gt;
import collections&lt;br /&gt;
import time&lt;br /&gt;
import bluetooth&lt;br /&gt;
import sys&lt;br /&gt;
import subprocess&lt;br /&gt;
import json&lt;br /&gt;
import urllib&lt;br /&gt;
import argparse&lt;br /&gt;
&lt;br /&gt;
# --------- User Settings ---------&lt;br /&gt;
WEIGHT_SAMPLES = 500&lt;br /&gt;
# ---------------------------------&lt;br /&gt;
&lt;br /&gt;
# Wiiboard Parameters&lt;br /&gt;
CONTINUOUS_REPORTING = &amp;quot;04&amp;quot;  # Easier as string with leading zero&lt;br /&gt;
COMMAND_LIGHT = 11&lt;br /&gt;
COMMAND_REPORTING = 12&lt;br /&gt;
COMMAND_REQUEST_STATUS = 15&lt;br /&gt;
COMMAND_REGISTER = 16&lt;br /&gt;
COMMAND_READ_REGISTER = 17&lt;br /&gt;
INPUT_STATUS = 20&lt;br /&gt;
INPUT_READ_DATA = 21&lt;br /&gt;
EXTENSION_8BYTES = 32&lt;br /&gt;
BUTTON_DOWN_MASK = 8&lt;br /&gt;
TOP_RIGHT = 0&lt;br /&gt;
BOTTOM_RIGHT = 1&lt;br /&gt;
TOP_LEFT = 2&lt;br /&gt;
BOTTOM_LEFT = 3&lt;br /&gt;
BLUETOOTH_NAME = &amp;quot;Nintendo RVL-WBC-01&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Read Configuration from .json file&lt;br /&gt;
ap = argparse.ArgumentParser()&lt;br /&gt;
ap.add_argument(&amp;quot;-c&amp;quot;, &amp;quot;--conf&amp;quot;, required=True,&lt;br /&gt;
	help=&amp;quot;path to the JSON configuration file; eg try: &amp;gt;wiiboard_kneipe.py --conf waage1.json&amp;quot;)&lt;br /&gt;
args = vars(ap.parse_args())&lt;br /&gt;
&lt;br /&gt;
#ConfigFile laden&lt;br /&gt;
conf = json.load(open(args[&amp;quot;conf&amp;quot;]))&lt;br /&gt;
client = None&lt;br /&gt;
&lt;br /&gt;
# create Network command&lt;br /&gt;
url = (conf[&amp;quot;fhem_host_port&amp;quot;])&lt;br /&gt;
request = (conf[&amp;quot;fhem_request&amp;quot;])&lt;br /&gt;
command = (conf[&amp;quot;fhem_command&amp;quot;])&lt;br /&gt;
#value =  &amp;quot;%20&amp;quot; + str(white)&lt;br /&gt;
fhem = url + request + command +&amp;quot;%20&amp;quot;&lt;br /&gt;
#print fhem&lt;br /&gt;
#urllib.urlopen(fhem)&lt;br /&gt;
&lt;br /&gt;
class EventProcessor:&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        self._measured = False&lt;br /&gt;
        self.done = False&lt;br /&gt;
        self._measureCnt = 0&lt;br /&gt;
        self._events = range(WEIGHT_SAMPLES)&lt;br /&gt;
&lt;br /&gt;
    def mass(self, event):&lt;br /&gt;
        if (event.totalWeight &amp;gt; 2):&lt;br /&gt;
            self._events[self._measureCnt] = event.totalWeight&lt;br /&gt;
            self._measureCnt += 1&lt;br /&gt;
            if self._measureCnt == WEIGHT_SAMPLES:&lt;br /&gt;
                self._sum = 0&lt;br /&gt;
                for x in range(0, WEIGHT_SAMPLES-1):&lt;br /&gt;
                    self._sum += event.totalWeight&lt;br /&gt;
                self._weight = self._sum/WEIGHT_SAMPLES&lt;br /&gt;
                self._measureCnt = 0&lt;br /&gt;
                print str(self._weight) + &amp;quot; kg&amp;quot;&lt;br /&gt;
		fhemComplete = fhem + str(self._weight)&lt;br /&gt;
		#print fhemComplete&lt;br /&gt;
		urllib.urlopen(fhemComplete)&lt;br /&gt;
            if not self._measured:&lt;br /&gt;
                self._measured = True&lt;br /&gt;
&lt;br /&gt;
    @property&lt;br /&gt;
    def weight(self):&lt;br /&gt;
        if not self._events:&lt;br /&gt;
            return 0&lt;br /&gt;
        histogram = collections.Counter(round(num, 1) for num in self._events)&lt;br /&gt;
        return histogram.most_common(1)[0][0]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class BoardEvent:&lt;br /&gt;
    def __init__(self, topLeft, topRight, bottomLeft, bottomRight, buttonPressed, buttonReleased):&lt;br /&gt;
&lt;br /&gt;
        self.topLeft = topLeft&lt;br /&gt;
        self.topRight = topRight&lt;br /&gt;
        self.bottomLeft = bottomLeft&lt;br /&gt;
        self.bottomRight = bottomRight&lt;br /&gt;
        self.buttonPressed = buttonPressed&lt;br /&gt;
        self.buttonReleased = buttonReleased&lt;br /&gt;
        #convenience value&lt;br /&gt;
        self.totalWeight = topLeft + topRight + bottomLeft + bottomRight&lt;br /&gt;
&lt;br /&gt;
class Wiiboard:&lt;br /&gt;
    def __init__(self, processor):&lt;br /&gt;
        # Sockets and status&lt;br /&gt;
        self.receivesocket = None&lt;br /&gt;
        self.controlsocket = None&lt;br /&gt;
&lt;br /&gt;
        self.processor = processor&lt;br /&gt;
        self.calibration = []&lt;br /&gt;
        self.calibrationRequested = False&lt;br /&gt;
        self.LED = False&lt;br /&gt;
        self.address = None&lt;br /&gt;
        self.buttonDown = False&lt;br /&gt;
        for i in xrange(3):&lt;br /&gt;
            self.calibration.append([])&lt;br /&gt;
            for j in xrange(4):&lt;br /&gt;
                self.calibration[i].append(10000)  # high dummy value so events with it don&#039;t register&lt;br /&gt;
&lt;br /&gt;
        self.status = &amp;quot;Disconnected&amp;quot;&lt;br /&gt;
        self.lastEvent = BoardEvent(0, 0, 0, 0, False, False)&lt;br /&gt;
&lt;br /&gt;
        try:&lt;br /&gt;
            self.receivesocket = bluetooth.BluetoothSocket(bluetooth.L2CAP)&lt;br /&gt;
            self.controlsocket = bluetooth.BluetoothSocket(bluetooth.L2CAP)&lt;br /&gt;
        except ValueError:&lt;br /&gt;
            raise Exception(&amp;quot;Error: Bluetooth not found&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    def isConnected(self):&lt;br /&gt;
        return self.status == &amp;quot;Connected&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    # Connect to the Wiiboard at bluetooth address &amp;lt;address&amp;gt;&lt;br /&gt;
    def connect(self, address):&lt;br /&gt;
        if address is None:&lt;br /&gt;
            print &amp;quot;Non existant address&amp;quot;&lt;br /&gt;
            return&lt;br /&gt;
        self.receivesocket.connect((address, 0x13))&lt;br /&gt;
        self.controlsocket.connect((address, 0x11))&lt;br /&gt;
        if self.receivesocket and self.controlsocket:&lt;br /&gt;
            print &amp;quot;Connected to Wiiboard at address &amp;quot; + address&lt;br /&gt;
            self.status = &amp;quot;Connected&amp;quot;&lt;br /&gt;
            self.address = address&lt;br /&gt;
            self.calibrate()&lt;br /&gt;
            useExt = [&amp;quot;00&amp;quot;, COMMAND_REGISTER, &amp;quot;04&amp;quot;, &amp;quot;A4&amp;quot;, &amp;quot;00&amp;quot;, &amp;quot;40&amp;quot;, &amp;quot;00&amp;quot;]&lt;br /&gt;
            self.send(useExt)&lt;br /&gt;
            self.setReportingType()&lt;br /&gt;
            print &amp;quot;Wiiboard connected&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            print &amp;quot;Could not connect to Wiiboard at address &amp;quot; + address&lt;br /&gt;
&lt;br /&gt;
    def receive(self):&lt;br /&gt;
        while self.status == &amp;quot;Connected&amp;quot; and not self.processor.done:&lt;br /&gt;
            data = self.receivesocket.recv(25)&lt;br /&gt;
            intype = int(data.encode(&amp;quot;hex&amp;quot;)[2:4])&lt;br /&gt;
            if intype == INPUT_STATUS:&lt;br /&gt;
                # TODO: Status input received. It just tells us battery life really&lt;br /&gt;
                self.setReportingType()&lt;br /&gt;
            elif intype == INPUT_READ_DATA:&lt;br /&gt;
                if self.calibrationRequested:&lt;br /&gt;
                    packetLength = (int(str(data[4]).encode(&amp;quot;hex&amp;quot;), 16) / 16 + 1)&lt;br /&gt;
                    self.parseCalibrationResponse(data[7:(7 + packetLength)])&lt;br /&gt;
&lt;br /&gt;
                    if packetLength &amp;lt; 16:&lt;br /&gt;
                        self.calibrationRequested = False&lt;br /&gt;
            elif intype == EXTENSION_8BYTES:&lt;br /&gt;
                self.processor.mass(self.createBoardEvent(data[2:12]))&lt;br /&gt;
            else:&lt;br /&gt;
                print &amp;quot;ACK to data write received&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    def disconnect(self):&lt;br /&gt;
        if self.status == &amp;quot;Connected&amp;quot;:&lt;br /&gt;
            self.status = &amp;quot;Disconnecting&amp;quot;&lt;br /&gt;
            while self.status == &amp;quot;Disconnecting&amp;quot;:&lt;br /&gt;
                self.wait(100)&lt;br /&gt;
        try:&lt;br /&gt;
            self.receivesocket.close()&lt;br /&gt;
        except:&lt;br /&gt;
            pass&lt;br /&gt;
        try:&lt;br /&gt;
            self.controlsocket.close()&lt;br /&gt;
        except:&lt;br /&gt;
            pass&lt;br /&gt;
        print &amp;quot;WiiBoard disconnected&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    # Try to discover a Wiiboard&lt;br /&gt;
    def discover(self):&lt;br /&gt;
        print &amp;quot;Press the red sync button on the board now&amp;quot;&lt;br /&gt;
        address = None&lt;br /&gt;
        bluetoothdevices = bluetooth.discover_devices(duration=6, lookup_names=True)&lt;br /&gt;
        for bluetoothdevice in bluetoothdevices:&lt;br /&gt;
            if bluetoothdevice[1] == BLUETOOTH_NAME:&lt;br /&gt;
                address = bluetoothdevice[0]&lt;br /&gt;
                print &amp;quot;Found Wiiboard at address &amp;quot; + address&lt;br /&gt;
        if address is None:&lt;br /&gt;
            print &amp;quot;No Wiiboards discovered.&amp;quot;&lt;br /&gt;
        return address&lt;br /&gt;
&lt;br /&gt;
    def createBoardEvent(self, bytes):&lt;br /&gt;
        buttonBytes = bytes[0:2]&lt;br /&gt;
        bytes = bytes[2:12]&lt;br /&gt;
        buttonPressed = False&lt;br /&gt;
        buttonReleased = False&lt;br /&gt;
&lt;br /&gt;
        state = (int(buttonBytes[0].encode(&amp;quot;hex&amp;quot;), 16) &amp;lt;&amp;lt; 8) | int(buttonBytes[1].encode(&amp;quot;hex&amp;quot;), 16)&lt;br /&gt;
        if state == BUTTON_DOWN_MASK:&lt;br /&gt;
            buttonPressed = True&lt;br /&gt;
            if not self.buttonDown:&lt;br /&gt;
                print &amp;quot;Button pressed&amp;quot;&lt;br /&gt;
                self.buttonDown = True&lt;br /&gt;
&lt;br /&gt;
        if not buttonPressed:&lt;br /&gt;
            if self.lastEvent.buttonPressed:&lt;br /&gt;
                buttonReleased = True&lt;br /&gt;
                self.buttonDown = False&lt;br /&gt;
                print &amp;quot;Button released&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        rawTR = (int(bytes[0].encode(&amp;quot;hex&amp;quot;), 16) &amp;lt;&amp;lt; 8) + int(bytes[1].encode(&amp;quot;hex&amp;quot;), 16)&lt;br /&gt;
        rawBR = (int(bytes[2].encode(&amp;quot;hex&amp;quot;), 16) &amp;lt;&amp;lt; 8) + int(bytes[3].encode(&amp;quot;hex&amp;quot;), 16)&lt;br /&gt;
        rawTL = (int(bytes[4].encode(&amp;quot;hex&amp;quot;), 16) &amp;lt;&amp;lt; 8) + int(bytes[5].encode(&amp;quot;hex&amp;quot;), 16)&lt;br /&gt;
        rawBL = (int(bytes[6].encode(&amp;quot;hex&amp;quot;), 16) &amp;lt;&amp;lt; 8) + int(bytes[7].encode(&amp;quot;hex&amp;quot;), 16)&lt;br /&gt;
&lt;br /&gt;
        topLeft = self.calcMass(rawTL, TOP_LEFT)&lt;br /&gt;
        topRight = self.calcMass(rawTR, TOP_RIGHT)&lt;br /&gt;
        bottomLeft = self.calcMass(rawBL, BOTTOM_LEFT)&lt;br /&gt;
        bottomRight = self.calcMass(rawBR, BOTTOM_RIGHT)&lt;br /&gt;
        boardEvent = BoardEvent(topLeft, topRight, bottomLeft, bottomRight, buttonPressed, buttonReleased)&lt;br /&gt;
        return boardEvent&lt;br /&gt;
&lt;br /&gt;
    def calcMass(self, raw, pos):&lt;br /&gt;
        val = 0.0&lt;br /&gt;
        #calibration[0] is calibration values for 0kg&lt;br /&gt;
        #calibration[1] is calibration values for 17kg&lt;br /&gt;
        #calibration[2] is calibration values for 34kg&lt;br /&gt;
        if raw &amp;lt; self.calibration[0][pos]:&lt;br /&gt;
            return val&lt;br /&gt;
        elif raw &amp;lt; self.calibration[1][pos]:&lt;br /&gt;
            val = 17 * ((raw - self.calibration[0][pos]) / float((self.calibration[1][pos] - self.calibration[0][pos])))&lt;br /&gt;
        elif raw &amp;gt; self.calibration[1][pos]:&lt;br /&gt;
            val = 17 + 17 * ((raw - self.calibration[1][pos]) / float((self.calibration[2][pos] - self.calibration[1][pos])))&lt;br /&gt;
&lt;br /&gt;
        return val&lt;br /&gt;
&lt;br /&gt;
    def getEvent(self):&lt;br /&gt;
        return self.lastEvent&lt;br /&gt;
&lt;br /&gt;
    def getLED(self):&lt;br /&gt;
        return self.LED&lt;br /&gt;
&lt;br /&gt;
    def parseCalibrationResponse(self, bytes):&lt;br /&gt;
        index = 0&lt;br /&gt;
        if len(bytes) == 16:&lt;br /&gt;
            for i in xrange(2):&lt;br /&gt;
                for j in xrange(4):&lt;br /&gt;
                    self.calibration[i][j] = (int(bytes[index].encode(&amp;quot;hex&amp;quot;), 16) &amp;lt;&amp;lt; 8) + int(bytes[index + 1].encode(&amp;quot;hex&amp;quot;), 16)&lt;br /&gt;
                    index += 2&lt;br /&gt;
        elif len(bytes) &amp;lt; 16:&lt;br /&gt;
            for i in xrange(4):&lt;br /&gt;
                self.calibration[2][i] = (int(bytes[index].encode(&amp;quot;hex&amp;quot;), 16) &amp;lt;&amp;lt; 8) + int(bytes[index + 1].encode(&amp;quot;hex&amp;quot;), 16)&lt;br /&gt;
                index += 2&lt;br /&gt;
&lt;br /&gt;
    # Send &amp;lt;data&amp;gt; to the Wiiboard&lt;br /&gt;
    # &amp;lt;data&amp;gt; should be an array of strings, each string representing a single hex byte&lt;br /&gt;
    def send(self, data):&lt;br /&gt;
        if self.status != &amp;quot;Connected&amp;quot;:&lt;br /&gt;
            return&lt;br /&gt;
        data[0] = &amp;quot;52&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        senddata = &amp;quot;&amp;quot;&lt;br /&gt;
        for byte in data:&lt;br /&gt;
            byte = str(byte)&lt;br /&gt;
            senddata += byte.decode(&amp;quot;hex&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        self.controlsocket.send(senddata)&lt;br /&gt;
&lt;br /&gt;
    #Turns the power button LED on if light is True, off if False&lt;br /&gt;
    #The board must be connected in order to set the light&lt;br /&gt;
    def setLight(self, light):&lt;br /&gt;
        if light:&lt;br /&gt;
            val = &amp;quot;10&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            val = &amp;quot;00&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        message = [&amp;quot;00&amp;quot;, COMMAND_LIGHT, val]&lt;br /&gt;
        self.send(message)&lt;br /&gt;
        self.LED = light&lt;br /&gt;
&lt;br /&gt;
    def calibrate(self):&lt;br /&gt;
        message = [&amp;quot;00&amp;quot;, COMMAND_READ_REGISTER, &amp;quot;04&amp;quot;, &amp;quot;A4&amp;quot;, &amp;quot;00&amp;quot;, &amp;quot;24&amp;quot;, &amp;quot;00&amp;quot;, &amp;quot;18&amp;quot;]&lt;br /&gt;
        self.send(message)&lt;br /&gt;
        self.calibrationRequested = True&lt;br /&gt;
&lt;br /&gt;
    def setReportingType(self):&lt;br /&gt;
        bytearr = [&amp;quot;00&amp;quot;, COMMAND_REPORTING, CONTINUOUS_REPORTING, EXTENSION_8BYTES]&lt;br /&gt;
        self.send(bytearr)&lt;br /&gt;
&lt;br /&gt;
    def wait(self, millis):&lt;br /&gt;
        time.sleep(millis / 1000.0)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    processor = EventProcessor()&lt;br /&gt;
&lt;br /&gt;
    board = Wiiboard(processor)&lt;br /&gt;
    address = (conf[&amp;quot;BT-Adress&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
    try:&lt;br /&gt;
        # Disconnect already-connected devices.&lt;br /&gt;
        # This is basically Linux black magic just to get the thing to work.&lt;br /&gt;
        subprocess.check_output([&amp;quot;bluez-test-input&amp;quot;, &amp;quot;disconnect&amp;quot;, address], stderr=subprocess.STDOUT)&lt;br /&gt;
        subprocess.check_output([&amp;quot;bluez-test-input&amp;quot;, &amp;quot;disconnect&amp;quot;, address], stderr=subprocess.STDOUT)&lt;br /&gt;
    except:&lt;br /&gt;
        pass&lt;br /&gt;
&lt;br /&gt;
    print &amp;quot;Trying to connect...&amp;quot;&lt;br /&gt;
    board.connect(address)  # The wii board must be in sync mode at this time&lt;br /&gt;
    board.wait(200)&lt;br /&gt;
    # Flash the LED so we know we can step on.&lt;br /&gt;
    board.setLight(False)&lt;br /&gt;
    board.wait(500)&lt;br /&gt;
    board.setLight(True)&lt;br /&gt;
    board.receive()&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ chmod 755 Gewicht.py&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
noch die Flags für Ausführbarkeit setzen&lt;br /&gt;
&lt;br /&gt;
==Links/Credits==&lt;br /&gt;
[http://makezine.com/projects/create-raspberry-pi-smart-beer-fridge/ Make]&lt;br /&gt;
{{Link2Forum|Topic=44684|LinkText=Forumsthread}}&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=WiiFit_Waage&amp;diff=13125</id>
		<title>WiiFit Waage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=WiiFit_Waage&amp;diff=13125"/>
		<updated>2015-12-03T10:09:02Z</updated>

		<summary type="html">&lt;p&gt;Rince: Sollte soweit erst mal fertig sein :)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Übersicht==&lt;br /&gt;
Dieses Python Skript baut eine Bluetooth Verbindung mit einem Wii Fit Board auf. Ist dies erledigt, schickt es das ermittelte Gewicht (in einer Dauerschleife) übers Netzwerk an FHEM.&lt;br /&gt;
{{Link2Forum|Topic=44684|LinkText=Forumsthread}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ohne eine Versionsnummerierung zu haben, nenne ich es mal 0.1 =&amp;gt; erste öffentliche Version&lt;br /&gt;
&lt;br /&gt;
==Voraussetzungen==&lt;br /&gt;
* Getestet mit Debian Wheezy.&lt;br /&gt;
* Bluetooth Stick&lt;br /&gt;
* Relais (wenn fhem das Pairing automatisch machen soll)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Konfiguration der Software===&lt;br /&gt;
Das Programm an sich benötigt eine Config-Datei.&lt;br /&gt;
&lt;br /&gt;
Beispieldatei, könnte Fass_1.json&amp;quot; genannt werden&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;BT-Adress&amp;quot;: &amp;quot;00:25:A0:40:5C:28&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_host_port&amp;quot;: &amp;quot;http://127.0.0.1:8083&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_request&amp;quot;: &amp;quot;/fhem?cmd=&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command&amp;quot;: &amp;quot;setreading%20Fass_1%20Gewicht&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Was ist hier einzustellen?&lt;br /&gt;
* &amp;quot;BTAdress&amp;quot;: Bluetoothadresse des Wii Fit Boards&lt;br /&gt;
* &amp;quot;fhem_host_port&amp;quot;: Adresse des fhem Servers, ebenso wie der Port. (Muss man also anpassen)&lt;br /&gt;
* &amp;quot;fhem_request&amp;quot;: (weiß nicht, wie es heißt), sollte aber so passen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Aufruf ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./Gewicht.py --conf &amp;quot;Fass_1.json&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Benötigte Pakete installieren ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt-get install python-bluetooth bluez python-gobject&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Um die Adresse in Erfahrung zu bringen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ hcitool dev&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Hardware-Modding ===&lt;br /&gt;
Leider kann man kein automatisches Pairing (wie bei einer Freisprechanlage und dem Handy im Auto) einrichten. Also ich kann es jedenfalls nicht. Daher muss bei jedem Skriptaufruf (das Skript läuft dann in einer Dauerschleife) den kleinen roten Pairing Knopf drücken. Der ist intelligenterweise unter der Batterieabdeckung.&lt;br /&gt;
&lt;br /&gt;
Lösung:&lt;br /&gt;
&lt;br /&gt;
Auf die Rückseite der Platine werden bei dem Taster 2 Drähte angelötet. Nun kann man z.B. mit einem Relais einfach kurz den Kontakt schließen lassen, so dass das Pairing am Board eingeleitet wird. Vom Timing her empfiehlt es sich (wenn man es von Hand mal ausprobieren will ohne Löterei), zuerst das Wii Fit Board in den Pairing Modus zu bringen, dann das Skript zu starten.&lt;br /&gt;
&lt;br /&gt;
==Programmcode==&lt;br /&gt;
z,B. mit&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ nano Gewicht.py&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Direkt im Wunschverzeichnis ablegen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
&lt;br /&gt;
import collections&lt;br /&gt;
import time&lt;br /&gt;
import bluetooth&lt;br /&gt;
import sys&lt;br /&gt;
import subprocess&lt;br /&gt;
import json&lt;br /&gt;
import urllib&lt;br /&gt;
import argparse&lt;br /&gt;
&lt;br /&gt;
# --------- User Settings ---------&lt;br /&gt;
WEIGHT_SAMPLES = 500&lt;br /&gt;
# ---------------------------------&lt;br /&gt;
&lt;br /&gt;
# Wiiboard Parameters&lt;br /&gt;
CONTINUOUS_REPORTING = &amp;quot;04&amp;quot;  # Easier as string with leading zero&lt;br /&gt;
COMMAND_LIGHT = 11&lt;br /&gt;
COMMAND_REPORTING = 12&lt;br /&gt;
COMMAND_REQUEST_STATUS = 15&lt;br /&gt;
COMMAND_REGISTER = 16&lt;br /&gt;
COMMAND_READ_REGISTER = 17&lt;br /&gt;
INPUT_STATUS = 20&lt;br /&gt;
INPUT_READ_DATA = 21&lt;br /&gt;
EXTENSION_8BYTES = 32&lt;br /&gt;
BUTTON_DOWN_MASK = 8&lt;br /&gt;
TOP_RIGHT = 0&lt;br /&gt;
BOTTOM_RIGHT = 1&lt;br /&gt;
TOP_LEFT = 2&lt;br /&gt;
BOTTOM_LEFT = 3&lt;br /&gt;
BLUETOOTH_NAME = &amp;quot;Nintendo RVL-WBC-01&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Read Configuration from .json file&lt;br /&gt;
ap = argparse.ArgumentParser()&lt;br /&gt;
ap.add_argument(&amp;quot;-c&amp;quot;, &amp;quot;--conf&amp;quot;, required=True,&lt;br /&gt;
	help=&amp;quot;path to the JSON configuration file; eg try: &amp;gt;wiiboard_kneipe.py --conf waage1.json&amp;quot;)&lt;br /&gt;
args = vars(ap.parse_args())&lt;br /&gt;
&lt;br /&gt;
#ConfigFile laden&lt;br /&gt;
conf = json.load(open(args[&amp;quot;conf&amp;quot;]))&lt;br /&gt;
client = None&lt;br /&gt;
&lt;br /&gt;
# create Network command&lt;br /&gt;
url = (conf[&amp;quot;fhem_host_port&amp;quot;])&lt;br /&gt;
request = (conf[&amp;quot;fhem_request&amp;quot;])&lt;br /&gt;
command = (conf[&amp;quot;fhem_command&amp;quot;])&lt;br /&gt;
#value =  &amp;quot;%20&amp;quot; + str(white)&lt;br /&gt;
fhem = url + request + command +&amp;quot;%20&amp;quot;&lt;br /&gt;
#print fhem&lt;br /&gt;
#urllib.urlopen(fhem)&lt;br /&gt;
&lt;br /&gt;
class EventProcessor:&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        self._measured = False&lt;br /&gt;
        self.done = False&lt;br /&gt;
        self._measureCnt = 0&lt;br /&gt;
        self._events = range(WEIGHT_SAMPLES)&lt;br /&gt;
&lt;br /&gt;
    def mass(self, event):&lt;br /&gt;
        if (event.totalWeight &amp;gt; 2):&lt;br /&gt;
            self._events[self._measureCnt] = event.totalWeight&lt;br /&gt;
            self._measureCnt += 1&lt;br /&gt;
            if self._measureCnt == WEIGHT_SAMPLES:&lt;br /&gt;
                self._sum = 0&lt;br /&gt;
                for x in range(0, WEIGHT_SAMPLES-1):&lt;br /&gt;
                    self._sum += event.totalWeight&lt;br /&gt;
                self._weight = self._sum/WEIGHT_SAMPLES&lt;br /&gt;
                self._measureCnt = 0&lt;br /&gt;
                print str(self._weight) + &amp;quot; kg&amp;quot;&lt;br /&gt;
		fhemComplete = fhem + str(self._weight)&lt;br /&gt;
		#print fhemComplete&lt;br /&gt;
		urllib.urlopen(fhemComplete)&lt;br /&gt;
            if not self._measured:&lt;br /&gt;
                self._measured = True&lt;br /&gt;
&lt;br /&gt;
    @property&lt;br /&gt;
    def weight(self):&lt;br /&gt;
        if not self._events:&lt;br /&gt;
            return 0&lt;br /&gt;
        histogram = collections.Counter(round(num, 1) for num in self._events)&lt;br /&gt;
        return histogram.most_common(1)[0][0]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class BoardEvent:&lt;br /&gt;
    def __init__(self, topLeft, topRight, bottomLeft, bottomRight, buttonPressed, buttonReleased):&lt;br /&gt;
&lt;br /&gt;
        self.topLeft = topLeft&lt;br /&gt;
        self.topRight = topRight&lt;br /&gt;
        self.bottomLeft = bottomLeft&lt;br /&gt;
        self.bottomRight = bottomRight&lt;br /&gt;
        self.buttonPressed = buttonPressed&lt;br /&gt;
        self.buttonReleased = buttonReleased&lt;br /&gt;
        #convenience value&lt;br /&gt;
        self.totalWeight = topLeft + topRight + bottomLeft + bottomRight&lt;br /&gt;
&lt;br /&gt;
class Wiiboard:&lt;br /&gt;
    def __init__(self, processor):&lt;br /&gt;
        # Sockets and status&lt;br /&gt;
        self.receivesocket = None&lt;br /&gt;
        self.controlsocket = None&lt;br /&gt;
&lt;br /&gt;
        self.processor = processor&lt;br /&gt;
        self.calibration = []&lt;br /&gt;
        self.calibrationRequested = False&lt;br /&gt;
        self.LED = False&lt;br /&gt;
        self.address = None&lt;br /&gt;
        self.buttonDown = False&lt;br /&gt;
        for i in xrange(3):&lt;br /&gt;
            self.calibration.append([])&lt;br /&gt;
            for j in xrange(4):&lt;br /&gt;
                self.calibration[i].append(10000)  # high dummy value so events with it don&#039;t register&lt;br /&gt;
&lt;br /&gt;
        self.status = &amp;quot;Disconnected&amp;quot;&lt;br /&gt;
        self.lastEvent = BoardEvent(0, 0, 0, 0, False, False)&lt;br /&gt;
&lt;br /&gt;
        try:&lt;br /&gt;
            self.receivesocket = bluetooth.BluetoothSocket(bluetooth.L2CAP)&lt;br /&gt;
            self.controlsocket = bluetooth.BluetoothSocket(bluetooth.L2CAP)&lt;br /&gt;
        except ValueError:&lt;br /&gt;
            raise Exception(&amp;quot;Error: Bluetooth not found&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    def isConnected(self):&lt;br /&gt;
        return self.status == &amp;quot;Connected&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    # Connect to the Wiiboard at bluetooth address &amp;lt;address&amp;gt;&lt;br /&gt;
    def connect(self, address):&lt;br /&gt;
        if address is None:&lt;br /&gt;
            print &amp;quot;Non existant address&amp;quot;&lt;br /&gt;
            return&lt;br /&gt;
        self.receivesocket.connect((address, 0x13))&lt;br /&gt;
        self.controlsocket.connect((address, 0x11))&lt;br /&gt;
        if self.receivesocket and self.controlsocket:&lt;br /&gt;
            print &amp;quot;Connected to Wiiboard at address &amp;quot; + address&lt;br /&gt;
            self.status = &amp;quot;Connected&amp;quot;&lt;br /&gt;
            self.address = address&lt;br /&gt;
            self.calibrate()&lt;br /&gt;
            useExt = [&amp;quot;00&amp;quot;, COMMAND_REGISTER, &amp;quot;04&amp;quot;, &amp;quot;A4&amp;quot;, &amp;quot;00&amp;quot;, &amp;quot;40&amp;quot;, &amp;quot;00&amp;quot;]&lt;br /&gt;
            self.send(useExt)&lt;br /&gt;
            self.setReportingType()&lt;br /&gt;
            print &amp;quot;Wiiboard connected&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            print &amp;quot;Could not connect to Wiiboard at address &amp;quot; + address&lt;br /&gt;
&lt;br /&gt;
    def receive(self):&lt;br /&gt;
        while self.status == &amp;quot;Connected&amp;quot; and not self.processor.done:&lt;br /&gt;
            data = self.receivesocket.recv(25)&lt;br /&gt;
            intype = int(data.encode(&amp;quot;hex&amp;quot;)[2:4])&lt;br /&gt;
            if intype == INPUT_STATUS:&lt;br /&gt;
                # TODO: Status input received. It just tells us battery life really&lt;br /&gt;
                self.setReportingType()&lt;br /&gt;
            elif intype == INPUT_READ_DATA:&lt;br /&gt;
                if self.calibrationRequested:&lt;br /&gt;
                    packetLength = (int(str(data[4]).encode(&amp;quot;hex&amp;quot;), 16) / 16 + 1)&lt;br /&gt;
                    self.parseCalibrationResponse(data[7:(7 + packetLength)])&lt;br /&gt;
&lt;br /&gt;
                    if packetLength &amp;lt; 16:&lt;br /&gt;
                        self.calibrationRequested = False&lt;br /&gt;
            elif intype == EXTENSION_8BYTES:&lt;br /&gt;
                self.processor.mass(self.createBoardEvent(data[2:12]))&lt;br /&gt;
            else:&lt;br /&gt;
                print &amp;quot;ACK to data write received&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    def disconnect(self):&lt;br /&gt;
        if self.status == &amp;quot;Connected&amp;quot;:&lt;br /&gt;
            self.status = &amp;quot;Disconnecting&amp;quot;&lt;br /&gt;
            while self.status == &amp;quot;Disconnecting&amp;quot;:&lt;br /&gt;
                self.wait(100)&lt;br /&gt;
        try:&lt;br /&gt;
            self.receivesocket.close()&lt;br /&gt;
        except:&lt;br /&gt;
            pass&lt;br /&gt;
        try:&lt;br /&gt;
            self.controlsocket.close()&lt;br /&gt;
        except:&lt;br /&gt;
            pass&lt;br /&gt;
        print &amp;quot;WiiBoard disconnected&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    # Try to discover a Wiiboard&lt;br /&gt;
    def discover(self):&lt;br /&gt;
        print &amp;quot;Press the red sync button on the board now&amp;quot;&lt;br /&gt;
        address = None&lt;br /&gt;
        bluetoothdevices = bluetooth.discover_devices(duration=6, lookup_names=True)&lt;br /&gt;
        for bluetoothdevice in bluetoothdevices:&lt;br /&gt;
            if bluetoothdevice[1] == BLUETOOTH_NAME:&lt;br /&gt;
                address = bluetoothdevice[0]&lt;br /&gt;
                print &amp;quot;Found Wiiboard at address &amp;quot; + address&lt;br /&gt;
        if address is None:&lt;br /&gt;
            print &amp;quot;No Wiiboards discovered.&amp;quot;&lt;br /&gt;
        return address&lt;br /&gt;
&lt;br /&gt;
    def createBoardEvent(self, bytes):&lt;br /&gt;
        buttonBytes = bytes[0:2]&lt;br /&gt;
        bytes = bytes[2:12]&lt;br /&gt;
        buttonPressed = False&lt;br /&gt;
        buttonReleased = False&lt;br /&gt;
&lt;br /&gt;
        state = (int(buttonBytes[0].encode(&amp;quot;hex&amp;quot;), 16) &amp;lt;&amp;lt; 8) | int(buttonBytes[1].encode(&amp;quot;hex&amp;quot;), 16)&lt;br /&gt;
        if state == BUTTON_DOWN_MASK:&lt;br /&gt;
            buttonPressed = True&lt;br /&gt;
            if not self.buttonDown:&lt;br /&gt;
                print &amp;quot;Button pressed&amp;quot;&lt;br /&gt;
                self.buttonDown = True&lt;br /&gt;
&lt;br /&gt;
        if not buttonPressed:&lt;br /&gt;
            if self.lastEvent.buttonPressed:&lt;br /&gt;
                buttonReleased = True&lt;br /&gt;
                self.buttonDown = False&lt;br /&gt;
                print &amp;quot;Button released&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        rawTR = (int(bytes[0].encode(&amp;quot;hex&amp;quot;), 16) &amp;lt;&amp;lt; 8) + int(bytes[1].encode(&amp;quot;hex&amp;quot;), 16)&lt;br /&gt;
        rawBR = (int(bytes[2].encode(&amp;quot;hex&amp;quot;), 16) &amp;lt;&amp;lt; 8) + int(bytes[3].encode(&amp;quot;hex&amp;quot;), 16)&lt;br /&gt;
        rawTL = (int(bytes[4].encode(&amp;quot;hex&amp;quot;), 16) &amp;lt;&amp;lt; 8) + int(bytes[5].encode(&amp;quot;hex&amp;quot;), 16)&lt;br /&gt;
        rawBL = (int(bytes[6].encode(&amp;quot;hex&amp;quot;), 16) &amp;lt;&amp;lt; 8) + int(bytes[7].encode(&amp;quot;hex&amp;quot;), 16)&lt;br /&gt;
&lt;br /&gt;
        topLeft = self.calcMass(rawTL, TOP_LEFT)&lt;br /&gt;
        topRight = self.calcMass(rawTR, TOP_RIGHT)&lt;br /&gt;
        bottomLeft = self.calcMass(rawBL, BOTTOM_LEFT)&lt;br /&gt;
        bottomRight = self.calcMass(rawBR, BOTTOM_RIGHT)&lt;br /&gt;
        boardEvent = BoardEvent(topLeft, topRight, bottomLeft, bottomRight, buttonPressed, buttonReleased)&lt;br /&gt;
        return boardEvent&lt;br /&gt;
&lt;br /&gt;
    def calcMass(self, raw, pos):&lt;br /&gt;
        val = 0.0&lt;br /&gt;
        #calibration[0] is calibration values for 0kg&lt;br /&gt;
        #calibration[1] is calibration values for 17kg&lt;br /&gt;
        #calibration[2] is calibration values for 34kg&lt;br /&gt;
        if raw &amp;lt; self.calibration[0][pos]:&lt;br /&gt;
            return val&lt;br /&gt;
        elif raw &amp;lt; self.calibration[1][pos]:&lt;br /&gt;
            val = 17 * ((raw - self.calibration[0][pos]) / float((self.calibration[1][pos] - self.calibration[0][pos])))&lt;br /&gt;
        elif raw &amp;gt; self.calibration[1][pos]:&lt;br /&gt;
            val = 17 + 17 * ((raw - self.calibration[1][pos]) / float((self.calibration[2][pos] - self.calibration[1][pos])))&lt;br /&gt;
&lt;br /&gt;
        return val&lt;br /&gt;
&lt;br /&gt;
    def getEvent(self):&lt;br /&gt;
        return self.lastEvent&lt;br /&gt;
&lt;br /&gt;
    def getLED(self):&lt;br /&gt;
        return self.LED&lt;br /&gt;
&lt;br /&gt;
    def parseCalibrationResponse(self, bytes):&lt;br /&gt;
        index = 0&lt;br /&gt;
        if len(bytes) == 16:&lt;br /&gt;
            for i in xrange(2):&lt;br /&gt;
                for j in xrange(4):&lt;br /&gt;
                    self.calibration[i][j] = (int(bytes[index].encode(&amp;quot;hex&amp;quot;), 16) &amp;lt;&amp;lt; 8) + int(bytes[index + 1].encode(&amp;quot;hex&amp;quot;), 16)&lt;br /&gt;
                    index += 2&lt;br /&gt;
        elif len(bytes) &amp;lt; 16:&lt;br /&gt;
            for i in xrange(4):&lt;br /&gt;
                self.calibration[2][i] = (int(bytes[index].encode(&amp;quot;hex&amp;quot;), 16) &amp;lt;&amp;lt; 8) + int(bytes[index + 1].encode(&amp;quot;hex&amp;quot;), 16)&lt;br /&gt;
                index += 2&lt;br /&gt;
&lt;br /&gt;
    # Send &amp;lt;data&amp;gt; to the Wiiboard&lt;br /&gt;
    # &amp;lt;data&amp;gt; should be an array of strings, each string representing a single hex byte&lt;br /&gt;
    def send(self, data):&lt;br /&gt;
        if self.status != &amp;quot;Connected&amp;quot;:&lt;br /&gt;
            return&lt;br /&gt;
        data[0] = &amp;quot;52&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        senddata = &amp;quot;&amp;quot;&lt;br /&gt;
        for byte in data:&lt;br /&gt;
            byte = str(byte)&lt;br /&gt;
            senddata += byte.decode(&amp;quot;hex&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        self.controlsocket.send(senddata)&lt;br /&gt;
&lt;br /&gt;
    #Turns the power button LED on if light is True, off if False&lt;br /&gt;
    #The board must be connected in order to set the light&lt;br /&gt;
    def setLight(self, light):&lt;br /&gt;
        if light:&lt;br /&gt;
            val = &amp;quot;10&amp;quot;&lt;br /&gt;
        else:&lt;br /&gt;
            val = &amp;quot;00&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        message = [&amp;quot;00&amp;quot;, COMMAND_LIGHT, val]&lt;br /&gt;
        self.send(message)&lt;br /&gt;
        self.LED = light&lt;br /&gt;
&lt;br /&gt;
    def calibrate(self):&lt;br /&gt;
        message = [&amp;quot;00&amp;quot;, COMMAND_READ_REGISTER, &amp;quot;04&amp;quot;, &amp;quot;A4&amp;quot;, &amp;quot;00&amp;quot;, &amp;quot;24&amp;quot;, &amp;quot;00&amp;quot;, &amp;quot;18&amp;quot;]&lt;br /&gt;
        self.send(message)&lt;br /&gt;
        self.calibrationRequested = True&lt;br /&gt;
&lt;br /&gt;
    def setReportingType(self):&lt;br /&gt;
        bytearr = [&amp;quot;00&amp;quot;, COMMAND_REPORTING, CONTINUOUS_REPORTING, EXTENSION_8BYTES]&lt;br /&gt;
        self.send(bytearr)&lt;br /&gt;
&lt;br /&gt;
    def wait(self, millis):&lt;br /&gt;
        time.sleep(millis / 1000.0)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def main():&lt;br /&gt;
    processor = EventProcessor()&lt;br /&gt;
&lt;br /&gt;
    board = Wiiboard(processor)&lt;br /&gt;
    address = (conf[&amp;quot;BT-Adress&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
    try:&lt;br /&gt;
        # Disconnect already-connected devices.&lt;br /&gt;
        # This is basically Linux black magic just to get the thing to work.&lt;br /&gt;
        subprocess.check_output([&amp;quot;bluez-test-input&amp;quot;, &amp;quot;disconnect&amp;quot;, address], stderr=subprocess.STDOUT)&lt;br /&gt;
        subprocess.check_output([&amp;quot;bluez-test-input&amp;quot;, &amp;quot;disconnect&amp;quot;, address], stderr=subprocess.STDOUT)&lt;br /&gt;
    except:&lt;br /&gt;
        pass&lt;br /&gt;
&lt;br /&gt;
    print &amp;quot;Trying to connect...&amp;quot;&lt;br /&gt;
    board.connect(address)  # The wii board must be in sync mode at this time&lt;br /&gt;
    board.wait(200)&lt;br /&gt;
    # Flash the LED so we know we can step on.&lt;br /&gt;
    board.setLight(False)&lt;br /&gt;
    board.wait(500)&lt;br /&gt;
    board.setLight(True)&lt;br /&gt;
    board.receive()&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    main()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ chmod 755 Gewicht.py&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
noch die Flags für Ausführbarkeit setzen&lt;br /&gt;
&lt;br /&gt;
==Links/Credits==&lt;br /&gt;
[http://makezine.com/projects/create-raspberry-pi-smart-beer-fridge/ Make]&lt;br /&gt;
{{Link2Forum|Topic=44684|LinkText=Forumsthread}}&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=WiiFit_Waage&amp;diff=13124</id>
		<title>WiiFit Waage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=WiiFit_Waage&amp;diff=13124"/>
		<updated>2015-12-03T08:11:43Z</updated>

		<summary type="html">&lt;p&gt;Rince: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Übersicht==&lt;br /&gt;
Dieses Python Skript baut eine Bluetooth Verbindung mit einem Wii Fit Board auf. Ist dies erledigt, schickt es das ermittelte Gewicht (in einer Dauerschleife) übers Netzwerk an FHEM.&lt;br /&gt;
{{Link2Forum|Topic=44684|LinkText=Forumsthread}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Voraussetzungen==&lt;br /&gt;
* Getestet mit Debian Wheezy.&lt;br /&gt;
* Bluetooth Stick&lt;br /&gt;
* Relais (wenn fhem das Pairing automatisch machen soll)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Konfiguration der Software===&lt;br /&gt;
Das Programm an sich benötigt eine Config-Datei.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Was ist hier einzustellen?&lt;br /&gt;
* &amp;quot;BTAdress&amp;quot;: Bluetoothadresse des Wii Fit Boards&lt;br /&gt;
* &amp;quot;fhem_host_port&amp;quot;: Adresse des fhem Servers, ebenso wie der Port. (Muss man also anpassen)&lt;br /&gt;
* &amp;quot;fhem_request&amp;quot;: (weiß nicht, wie es heißt), sollte aber so passen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Benötigte Pakete installieren ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt-get install python-bluetooth bluez python-gobject&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Um die Adresse in Erfahrung zu bringen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ hcitool dev&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Hardware-Modding ===&lt;br /&gt;
Leider kann man kein automatisches Pairing (wie bei einer Freisprechanlage und dem Handy im Auto) einrichten. Also ich kann es jedenfalls nicht. Daher muss bei jedem Skriptaufruf (das Skript läuft dann in einer Dauerschleife) den kleinen roten Pairing Knopf drücken. Der ist intelligenterweise unter der Batterieabdeckung.&lt;br /&gt;
&lt;br /&gt;
Lösung:&lt;br /&gt;
&lt;br /&gt;
Auf die Rückseite der Platine werden bei dem Taster 2 Drähte angelötet. Nun kann man z.B. mit einem Relais einfach kurz den Kontakt schließen lassen, so dass das Pairing am Board eingeleitet wird. Vom Timing her empfiehlt es sich (wenn man es von Hand mal ausprobieren will ohne Löterei), zuerst das Wii Fit Board in den Pairing Modus zu bringen, dann das Skript zu starten.&lt;br /&gt;
&lt;br /&gt;
==Programmcode==&lt;br /&gt;
z,B. mit&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ nano Gewicht.py&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Direkt im Wunschverzeichnis ablegen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
KOMMT SPÄTER&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ chmod 755 Gewicht.py&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
noch die Flags für Ausführbarkeit setzen&lt;br /&gt;
&lt;br /&gt;
==Links/Credits==&lt;br /&gt;
[http://makezine.com/projects/create-raspberry-pi-smart-beer-fridge/ Make]&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=WiiFit_Waage&amp;diff=13123</id>
		<title>WiiFit Waage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=WiiFit_Waage&amp;diff=13123"/>
		<updated>2015-12-03T07:59:39Z</updated>

		<summary type="html">&lt;p&gt;Rince: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Übersicht==&lt;br /&gt;
Dieses Python Skript baut eine Bluetooth Verbindung mit einem Wii Fit Board auf. Ist dies erledigt, schickt es das ermittelte Gewicht (in einer Dauerschleife) übers Netzwerk an FHEM.&lt;br /&gt;
{{Link2Forum|Topic=44684|LinkText=Forumsthread}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Voraussetzungen==&lt;br /&gt;
* Getestet mit Debian Wheezy.&lt;br /&gt;
* Bluetooth Stick&lt;br /&gt;
* Relais (wenn fhem das Pairing automatisch machen soll)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Konfiguration der Software===&lt;br /&gt;
Das Programm an sich benötigt eine Config-Datei.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Was ist hier einzustellen?&lt;br /&gt;
* &amp;quot;BTAdress&amp;quot;: Bluetoothadresse des Wii Fit Boards&lt;br /&gt;
* &amp;quot;fhem_host_port&amp;quot;: Adresse des fhem Servers, ebenso wie der Port. (Muss man also anpassen)&lt;br /&gt;
* &amp;quot;fhem_request&amp;quot;: (weiß nicht, wie es heißt), sollte aber so passen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Benötigte Pakete installieren&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt-get install python-bluetooth bluez python-gobject&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Um die Adresse in Erfahrung zu bringen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ hcitool dev&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Programmcode==&lt;br /&gt;
z,B. mit&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ nano Gewicht.py&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Direkt im Wunschverzeichnis ablegen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
KOMMT SPÄTER&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ chmod 755 Gewicht.py&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
noch die Flags für Ausführbarkeit setzen&lt;br /&gt;
&lt;br /&gt;
==Links/Credits==&lt;br /&gt;
[http://makezine.com/projects/create-raspberry-pi-smart-beer-fridge/ Make]&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=WiiFit_Waage&amp;diff=13121</id>
		<title>WiiFit Waage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=WiiFit_Waage&amp;diff=13121"/>
		<updated>2015-12-03T06:50:21Z</updated>

		<summary type="html">&lt;p&gt;Rince: Noch nicht fertig&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Übersicht==&lt;br /&gt;
Dieses Python Skript baut eine Bluetooth Verbindung mit einem Wii Fit Board auf. Ist dies erledigt, schickt es das ermittelte Gewicht (in einer Dauerschleife) übers Netzwerk an FHEM.&lt;br /&gt;
{{Link2Forum|Topic=44684|LinkText=Forumsthread}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Voraussetzungen==&lt;br /&gt;
* Getestet mit Debian Wheezy.&lt;br /&gt;
* Bluetooth Stick&lt;br /&gt;
* Relais (wenn fhem das Pairing automatisch machen soll)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Konfiguration der Software===&lt;br /&gt;
Das Programm an sich benötigt eine Config-Datei.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Was ist hier einzustellen?&lt;br /&gt;
* &amp;quot;BTAdress&amp;quot;: Bluetoothadresse des Wii Fit Boards&lt;br /&gt;
* &amp;quot;fhem_host_port&amp;quot;: Adresse des fhem Servers, ebenso wie der Port. (Muss man also anpassen)&lt;br /&gt;
* &amp;quot;fhem_request&amp;quot;: (weiß nicht, wie es heißt), sollte aber so passen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Benötigte Pakete installieren&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt-get install python-bluetooth bluez python-gobject&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Um die Adresse in Erfahrung zu bringen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ hcitool dev&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Programmcode==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
KOMMT SPÄTER&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Links/Credits==&lt;br /&gt;
[http://makezine.com/projects/create-raspberry-pi-smart-beer-fridge/ Make]&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Fremdger%C3%A4te_ignorieren_R%C3%BCckg%C3%A4ngig&amp;diff=12495</id>
		<title>Fremdgeräte ignorieren Rückgängig</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Fremdger%C3%A4te_ignorieren_R%C3%BCckg%C3%A4ngig&amp;diff=12495"/>
		<updated>2015-10-13T20:23:39Z</updated>

		<summary type="html">&lt;p&gt;Rince: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Frage:&#039;&#039;&#039; Ich habe einige Geräte auf &amp;quot;ignore&amp;quot; gesetzt und würde diese jetzt gerne wieder in fhem sehen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Antwort:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Unter fhem eingeben: &lt;br /&gt;
 { join(&amp;quot;\n&amp;quot;, grep { $attr{$_}{ignore} } sort keys %attr ) }&lt;br /&gt;
&lt;br /&gt;
* Beim Arbeiten mit configdb&lt;br /&gt;
  configdb search ignore&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nun kann man das Attribut ignore=1 löschen und das Gerät ist wieder da. Bitte ein save config nicht vergessen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Tip:&lt;br /&gt;
&lt;br /&gt;
Wer es bequemer will, oder öfter braucht, kann das auch mit cmdalias vereinfachen:&lt;br /&gt;
&lt;br /&gt;
 define showignoreddevices cmdalias showignoreddevices AS { join(&amp;quot;\n&amp;quot;, grep { $attr{$_}{ignore} } sort keys %attr ) }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Damit reicht die Eingabe von showignoreddevices in der fhem Befehlszeile aus... (Danke an P.A.Trick)&lt;br /&gt;
[[Kategorie:FAQ]]&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=RFXtrx&amp;diff=12274</id>
		<title>RFXtrx</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=RFXtrx&amp;diff=12274"/>
		<updated>2015-09-26T07:48:44Z</updated>

		<summary type="html">&lt;p&gt;Rince: Oregon MSR939 ergänzt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Fhem unterstützt viele durch einen &#039;&#039;&#039;RFXtrx&#039;&#039;&#039;433 Transceiver erreichbare Geräte durch eigene Module.&lt;br /&gt;
&lt;br /&gt;
== Übersicht ==&lt;br /&gt;
[[File:Rfxtrx433.png|500px|right]]&lt;br /&gt;
&lt;br /&gt;
RFXtrx433 ist ein Transceiver (Funkempfänger und Funksender) mit USB-Anschluss für den Frenzbereich 433,92 MHz. Die Stromversorgung erfolgt über USB.  Das Gerät hat einen FTDI-FT232R-USB-Interface-Chip installiert. Um RFXtrx433 nutzen zu können, muss das Betriebssystem einen entsprechenden Treiber für diesen Chip haben. Genutzt wird RFXtrx433 von Anwendern mit FHEM unter Linux, Fritzbox 7390 oder Windows.&lt;br /&gt;
&lt;br /&gt;
Mit der mitgelieferten Firmware können viele Funksensoren in diesem Frequenzbereich empfangen werden und es ist möglich bestimmte Protokolle auch zu senden. Die unterstützten Protokolle sind von der installierten Firmware abhängig, die über das Windows-Programm [http://www.rfxcom.com/Downloads RFXflash] aktualisiert werden kann. Die neueste Firmware ist unter [http://www.rfxcom.com/Downloads http://www.rfxcom.com/Downloads] zu finden.&lt;br /&gt;
&lt;br /&gt;
Weitere Informationen zu den von diesem Transceiver verfügbaren Protokolle beim Hersteller unter [http://www.rfxcom.com www.rfxcom.com]. Da der Hersteller die Anzahl der Geräte ständig aktualisiert und die FHEM-Treiber in der Freizeit des Autors geschrieben werden, sind in den FHEM-Treibern nur eine Untermenge implementiert. Sollte ein Gerät/Protokoll fehlen, das die Firma RFXCOM unterstützt, können Sie im [http://forum.fhem.de/ FHEM-Forum] in der Untergruppe RFXTRX nachfragen, ob dieses implementiert werden kann.&lt;br /&gt;
&lt;br /&gt;
TRXtrx433 wird derzeit von FHEM mit den Modulen TRX, TRX_LIGHT, TRX-SECURITY und TRX_WEATHER für eine Reihe von Protokollen unterstützt.&lt;br /&gt;
&lt;br /&gt;
Nachfolgend werden nur Geräte aufgezeigt, die bei der Erstellung dieses WIKI-Eintrages eingepflegt werden.&lt;br /&gt;
&lt;br /&gt;
== FHEM-Modul: TRX_WEATHER ==&lt;br /&gt;
Dieses Modul unterstützt Wettersensoren, insbesondere Sensoren des Herstellers Oregon-Scientific. Unter [http://www.rfxcom.com/oregon.htm Wetter-Sensoren] finden Sie eine Liste der von der RFXtrx433-Firmware unterstützten Wetter-Sensoren (Oregon-Scientific, Cresta, La Crosse, TFA, UPM, ...). Das FHEM-Modul TRX_WEATHER implementiert derzeit den Empfang folgender Sensorentypen und Sensoren:&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;Temperatursensoren&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;THR128&amp;quot;: Oregon-Scientific THR128/138, THC138&lt;br /&gt;
* &amp;quot;THGR132N&amp;quot;: Oregon-Scientific THC238/268,THN132,THWR288,THRN122,THN122,AW129/131&lt;br /&gt;
* &amp;quot;THWR800&amp;quot;: Oregon-Scientific THWR800&lt;br /&gt;
* &amp;quot;RTHN318&amp;quot;: Oregon-Scientific RTHN318&lt;br /&gt;
* &amp;quot;TS15C&amp;quot;: TS15C&lt;br /&gt;
* &amp;quot;VIKING_02811&amp;quot; : Viking 02811&lt;br /&gt;
* &amp;quot;WS2300&amp;quot; : La Crosse WS2300&lt;br /&gt;
* &amp;quot;RUBICSON&amp;quot; : RUBiCSON&lt;br /&gt;
* &amp;quot;TFA_303133&amp;quot; : TFA 30.3133&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;Temperatur-/Luftffeuchtigkeitssensoren&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;THGR228N&amp;quot;: Oregon-Scientific THGN122/123, THGN132, THGR122/228/238/268 [[File:Thgr228n.png|92px|right|thumb|THGR228N]]&lt;br /&gt;
* &amp;quot;THGR810&amp;quot;: Oregon-Scientific THGR810&lt;br /&gt;
* &amp;quot;RTGR328&amp;quot;: Oregon-Scientific RTGR328&lt;br /&gt;
* &amp;quot;THGR328&amp;quot;: Oregon-Scientific THGR328&lt;br /&gt;
* &amp;quot;WTGR800_T&amp;quot;: Oregon-Scientific WTGR800&lt;br /&gt;
* &amp;quot;THGR918&amp;quot;: Oregon-Scientific THGR918, THGRN228, THGN500&lt;br /&gt;
* &amp;quot;TFATS34C&amp;quot;: TFA TS34C (Kat. Nr. 30.3150)&lt;br /&gt;
* &amp;quot;WT450H&amp;quot;: UPM WT450H&lt;br /&gt;
* &amp;quot;TX3_T&amp;quot;: LaCrosse TX3, TX4, TX17&lt;br /&gt;
[[File:TX3TH.jpg|92px|right|thumb|TX3TH]]&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Nicht unterstützt werden von der RFXCOM-Firmware:&#039;&#039;&#039; TFA 30.3166&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;Temperatur-/Luftffeuchtigkeits-/Luftdrucksensoren&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;BTHR918&amp;quot;: Oregon-Scientific BTHR918&lt;br /&gt;
* &amp;quot;BTHR918N&amp;quot;: Oregon-Scientific/Huger BTHR918N, BTHR968 [[File:Bthr918n.png|96px|right|thumb|BTHR918N]]&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;Regensensoren&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;RGR918&amp;quot;: Oregon-Scientific RGR126/682/918&lt;br /&gt;
* &amp;quot;PCR800&amp;quot;: Oregon-Scientific PCR800&lt;br /&gt;
* &amp;quot;TFA_RAIN&amp;quot;: TFA-Regensensor (Kat. Nr. 30.3148)&lt;br /&gt;
* &amp;quot;RG700&amp;quot;: UPM RG700&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;Windsensoren&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;WTGR800_A&amp;quot;: Oregon-Scientific WTGR800&lt;br /&gt;
* &amp;quot;WGR800_A&amp;quot;: Oregon-Scientific WGR800&lt;br /&gt;
* &amp;quot;WGR918&amp;quot;: Oregon-Scientific STR918, WGR918&lt;br /&gt;
* &amp;quot;TFA_WIND&amp;quot;: TFA-Windsensor (Kat. Nr. 30.3149)&lt;br /&gt;
* &amp;quot;WDS500&amp;quot; : UPM WDS500&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;UV-Sensoren&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;UVN128&amp;quot;: Oregon UVN128, UV138&lt;br /&gt;
* &amp;quot;UVN800&amp;quot;: Oregon UVN800&lt;br /&gt;
* &amp;quot;TFA_UV&amp;quot;: TFA_UV-Sensor&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;Waagen&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;BWR101&amp;quot;: Oregon Scientific BWR101&lt;br /&gt;
* &amp;quot;GR101&amp;quot;: Oregon Scientific GR101&lt;br /&gt;
&lt;br /&gt;
- &#039;&#039;&#039;Energiesensoren&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;CM160&amp;quot;: OWL CM119 und CM160&lt;br /&gt;
* &amp;quot;CM180&amp;quot;: OWL CM180&lt;br /&gt;
&lt;br /&gt;
Der Autor des Module setzt derzeit folgende Sensoren ein:&lt;br /&gt;
&lt;br /&gt;
* Oregon Scientific: BTHR918, BTHR918N, PCR800, RGR918, THGR228N, THR128, THWR288A, WTGR800, WGR918&lt;br /&gt;
&lt;br /&gt;
Von Nutzern wurde die Funktion folgender weiterer Sensoren gemeldet:&lt;br /&gt;
&lt;br /&gt;
* Oregon Scientific GR101&lt;br /&gt;
* Oregon Scientific RTGR-328 (T/H)&lt;br /&gt;
* Honeywell TF-ATS34C (T/H)&lt;br /&gt;
* TFA Regensender 433 MHz, Kat. Nr. 30.3148, siehe [http://tfa-dostmann.de/index.php?id=57 TFA]&lt;br /&gt;
* TFA Windsender 433 MHz, Kat. Nr. 30.3149, siehe [http://tfa-dostmann.de/index.php?id=57 TFA]&lt;br /&gt;
* TFA T/H-Sender 433 MHz, Kat. Nr. 30.3150, siehe [http://tfa-dostmann.de/index.php?id=57 TFA]&lt;br /&gt;
* OWL CM160&lt;br /&gt;
&lt;br /&gt;
=== FAQ: Wie bringe ich FHEM dazu nicht alle paar Sekunden den Zustand der Sensoren zu loggen? ===&lt;br /&gt;
&lt;br /&gt;
Den ein oder anderen hat es schon genervt, dass die Oregon-Sensoren sehr gesprächig sind und damit das Filelog sehr groß wird.&lt;br /&gt;
&lt;br /&gt;
Abhilfe: Hierzu kann man event-min-interval verwenden, um festzulegen, dass Events nur alle x Minuten generiert werden. event-on-change-reading kann man verwenden, dass Änderungen trotzdem sofort bemerkt werden.&lt;br /&gt;
&lt;br /&gt;
Nachfolgend wird ein Oregon-Sensor BTHR918 so konfiguriert, dass er nur alle 10 Minuten loggt, aber beim State die Änderungen sofort geloggt werden.&lt;br /&gt;
&lt;br /&gt;
 define Alte_Garage TRX_WEATHER BTHR918&lt;br /&gt;
 attr Alte_Garage event-min-interval state:600&lt;br /&gt;
 attr Alte_Garage event-on-change-reading state&lt;br /&gt;
 attr Alte_Garage event-on-update-reading .*&lt;br /&gt;
&lt;br /&gt;
Damit man nicht alles loggt, kann man das Logging auf die Zeilen beschränken, die mit T: beginnen:&lt;br /&gt;
&lt;br /&gt;
 define FileLog_Alte_Garage FileLog /var/log/fhem/Alte_Garage-%Y.log Alte_Garage:T\x3a.*&lt;br /&gt;
 attr FileLog_Alte_Garage logtype temp4press8:Temp/Press,temp4hum6dew10:Temp/Hum,text&lt;br /&gt;
&lt;br /&gt;
Damit hat man dann folgendes im Log:&lt;br /&gt;
&lt;br /&gt;
 2013-08-27_12:21:29 Alte_Garage T: 19.9 H: 69 P: 1005 BAT: low&lt;br /&gt;
 2013-08-27_12:31:37 Alte_Garage T: 19.9 H: 69 P: 1005 BAT: low&lt;br /&gt;
 2013-08-27_12:41:45 Alte_Garage T: 19.9 H: 69 P: 1005 BAT: low&lt;br /&gt;
 2013-08-27_12:47:27 Alte_Garage T: 20 H: 68 P: 1005 D: BAT: low&lt;br /&gt;
 2013-08-27_12:57:35 Alte_Garage T: 20 H: 68 P: 1005 D: BAT: low&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wie man sieht, wird normalerweise alle 10 Minuten geloggt. Um 12:47:27 hat sich die Temperatur verändert und damit wurde ausserhalb der Reihe sofort ein Event generiert.&lt;br /&gt;
&lt;br /&gt;
Ja, stimmt, ich muss noch die Batterie des Sensors wechseln (BAT: low) ;-)&lt;br /&gt;
&lt;br /&gt;
== FHEM-Modul: TRX_SECURITY ==&lt;br /&gt;
Empfängt Security-Sensoren der Protokolle X10-Security, KD101 und Visonic. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;KD101 kompatible Rauchmelder&#039;&#039;&#039;&lt;br /&gt;
Es wurden folgende KD101-Versionen gemeldet, die mit RXFtrx433 empfangen werden können:&lt;br /&gt;
&lt;br /&gt;
* KD101LD&lt;br /&gt;
* KD101LA&lt;br /&gt;
* Flamingo FA20RF&lt;br /&gt;
* Elro RM150RF&lt;br /&gt;
* Unitec 46779&lt;br /&gt;
&lt;br /&gt;
Die Rauchmelder KD101 (KD101LD, KD101LA, Flamingo FA20RF, Elro RM150RF) haben folgendes Verhalten:&lt;br /&gt;
&lt;br /&gt;
* Wenn der KD101 selbst Rauch feststellt, kann man diesen Alarm über Funk nicht stoppen. Er sendet &amp;quot;alert&amp;quot; über Funk.&lt;br /&gt;
* Wenn man &amp;quot;alarm&amp;quot; über Funk an einen Rauchmelder sendet, dauert der Alarm nur wenige Sekunden. Für einen dauerhaften Alarm muss man also &amp;quot;alert&amp;quot; immer wieder senden.&lt;br /&gt;
* Wenn man die KD101 pairt, bekommen alle gepairten KD101 dieselbe ID.&lt;br /&gt;
* Wenn einer Rauch erkennt, triggert er alle KD101 mit derselben ID (also die gepairten).&lt;br /&gt;
* Nach Drücken der Taste &amp;quot;Test&amp;quot; am Rauchmelder sendet dieser &amp;quot;alert&amp;quot;. Dadurch wird per autocreate der Rauchmelder angelegt.&lt;br /&gt;
* Ein KD101 sendet kein Keepalive-Signal. Man kann also nur testen, ob ein Rauchmelder noch funktioniert, indem man die Test-Taste drückt.&lt;br /&gt;
&lt;br /&gt;
Mittels RFXtrx433 kann man die Befehle &amp;quot;alert&amp;quot; und &amp;quot;pair&amp;quot; an einen Rauchmelder senden.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
* set TRX_KD101_a5ca00 alert&lt;br /&gt;
&lt;br /&gt;
Dies sendet den panic-Befehl an den Rauchmelder. Damit hört man ca. 3 Sekunden lang den nervigen Ton des Rauchmelders. Wer diesen länger haben will, muss das set nach ca. 3 Sekunden erneut auslösen.&lt;br /&gt;
Wer man also ein &amp;quot;set DEVICE alert&amp;quot; an einen Rauchmelder schickt, der mit anderen gepairt ist, dann wird der Alarm bei allen gepairten Rauchmeldern ausgelöst.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;X10-Security-Sensoren&#039;&#039;&#039;&lt;br /&gt;
Folgende X10-Security-Sensoren werden erfolgreich eingesetzt:&lt;br /&gt;
&lt;br /&gt;
* Türsensoren:&lt;br /&gt;
** X10 Türsensor Powerhouse DS10A ([http://www.domotica.famschenk.eu/DS10A_op_433Mhz.html Umbau auf 433 Mhz])&lt;br /&gt;
** Marmitek Türsensor DS90&lt;br /&gt;
* Bewegungssensoren: &lt;br /&gt;
** X10 Bewegungssensor Powerhouse MS10A ([http://www.domotica.famschenk.eu/MS10A-433.html Umbau auf 433 Mhz])[[File:Ms10a.png|70px|right|thumb|MS10A]]&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[File:Ms90.png|82px|mini|ohne|MS90]]&amp;lt;/div&amp;gt;&lt;br /&gt;
** Marmitek Bewegungssensor MS10E/BNL (kompatibel mit X10 MS10)&lt;br /&gt;
** Marmitek Bewegungssensor MS90 &lt;br /&gt;
* Rauchmelder:&lt;br /&gt;
** Marmitek Rauchmelder SD90&lt;br /&gt;
&lt;br /&gt;
Die oben genannten Sensoren können auch parallel zum RFXtrx433 mit der Marmitek-Alarmanlage SC9000 eingesetzt werden.&lt;br /&gt;
&lt;br /&gt;
* Fernbedienungen:&lt;br /&gt;
** Marmitek KR21E [[File:Kr21e.png|60px|right|thumb|KR21E]]&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[File:Sh624.png|75px|mini|ohne|SH624]]&amp;lt;/div&amp;gt;&lt;br /&gt;
** Marmitek SH624 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
X10-Security-Sensoren senden etwa jede Stunde ein Keepalive-Paket, welches auch Informationen über den Batterieladestand enthält.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Bewegungsmelder&lt;br /&gt;
** Oregon MSR939 (benötigt den RFXtrx433e), theoretisch 32 Adressen möglich, 5 Stück erfolgreich eingebunden (mehr Sensoren hatte ich nicht zur Hand)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== FHEM-Modul: TRX_LIGHT.pm ==&lt;br /&gt;
Empfängt die Protokolle X10, ARC, ELRO AB400D, Waveman, Chacon EMW200, IMPULS, RisingSun, Philips SBC, AC, HomeEasy EU sowie ANSLUT lighting devices (switches and remote control). &lt;br /&gt;
&lt;br /&gt;
ARC ist ein a Protokoll, welches von Geräten HomeEasy, KlikAanKlikUit, ByeByeStandBy, Intertechno, ELRO, AB600, Duewi, DomiaLite und COCO genutzt wird. Typisch ist, dass diese Geräte einen Drehschalter haben, um die Protkolladresse einzustellen.&lt;br /&gt;
&lt;br /&gt;
Das ARC-Protokoll kennt keinen Dim-Befehl. Daher hat die Firmware vom RFXtrx433 und auch das FHEM-Modul TRX_LIGHT keinen solchen Befehl. Die verkauften Dimmer mit ARC-Protokoll starten gemäß meiner Information das Hoch-Dimmen nach Empfang zweier ON-Kommandos. Sobald dann das nächste ON oder OFF Kommando empfangen wird, wird das Dimmen beendet.&lt;br /&gt;
Das ganze ist also zeitabhängig und eigentlich nicht für die Hausautomatisierung gedacht, sondern für den Menschen, der sieht, ob der Dim-Level ok ist. Automatisiert bekommt man keine exakte prozentuale Dimmung hin, da man Dimmen nur über Timing erreichen kann.&lt;br /&gt;
Da FHEM nicht sehen kann wie weit gedimmt wurde, ist das allerdings nicht wirklich praktikabel und auch vom Gerät abhängig.&lt;br /&gt;
Unterschiedliche Geräte auch unterschiedliches Zeitverhalten.&lt;br /&gt;
&lt;br /&gt;
AC ist ein Protokoll, welches verschiedene Hersteller nutzen, die die Adresse über einen LEARN-Button lernen: KlikAanKlikUit, NEXA, CHACON, HomeEasy UK.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Achtung:&#039;&#039;Es sollte beachtet werden, dass Tür- und Bewegungssensoren des AC-Protokolls (HomeEasy alt, Chacon, KlikAanKlikUit, NEXA...) teilweise für 3-5 Sekunden etwa 50 Funkpakete generieren, was zu Kollisionen mit anderen Paketen führen kann. Siehe [http://www.domoticaforum.eu/viewtopic.php?f=7&amp;amp;amp;t=7276 Hinweis zur Nutzung von Bewegungssensoren]. Ich rate daher vom Einsatz von Bewegungssensoren mit dem AC-Protokoll ab.&lt;br /&gt;
&lt;br /&gt;
Der Autor des Moduls setzt derzeit folgende Geräte ein:&lt;br /&gt;
&lt;br /&gt;
* Eagle EyeMS14a Bewegungssensor ([http://www.domotica.famschenk.eu/MS14A_OP_433.92.html Umbau auf 433 Mhz])&lt;br /&gt;
* Elro AB600 Funksender und Steckdosen&lt;br /&gt;
&lt;br /&gt;
Nutzer haben die Funktion folgender Geräte gemeldet:&lt;br /&gt;
&lt;br /&gt;
* KAKU AWST-6000 (Bewegungsmelder, sendet on/off)&lt;br /&gt;
* KAKU AMST-606 (Tür-/Fenster-Kontakt, sendet all_level/off)&lt;br /&gt;
* KAKU AWMT-230 (Unterputzsender, sendet on/off)&lt;br /&gt;
* KAKU APA3-1500R (Schalter &amp;amp;amp; Handsender, nur on/off/all_off)&lt;br /&gt;
* KAKU CDB-6500AC (Türklingel, sendet nur chime)&lt;br /&gt;
&lt;br /&gt;
== PT2262 empfangen und senden mit TRX_LIGHT.pm ==&lt;br /&gt;
&#039;&#039;&#039;WARNUNG:&#039;&#039;&#039;PT2262-Codes sollten nur verwendet werden, wenn unbedingt erforderlich. Normalerweise reicht die Nutzung der von RFXCOM vordefinierten Dekodierungen wie das ARC-Protokoll aus. Bei manchen Geräten mit dem Chip PT2262 kann dies evtl. nicht ausreichen. Sinnvollerweise sollte man prüfen, ob das Gerät wirklich einen Funk-Encoder-IC PT2262 oder SC2262 enthält. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ACHTUNG:&#039;&#039;&#039; Es können nur PT2262-Codes empfangen werden, wenn das Pulse-Timung 350 usec ist (Siehe Kapitel 8 im RFXtrx User Guide). Gemäß Seite 6 im Dokument http://www.escol.com.my/Datasheets_specs/pt2262_1.pdf‎ sollte für den Oszillator normalerweise ein 3,3 Mega-Ohm-Widerstand eingebaut sein.&lt;br /&gt;
&lt;br /&gt;
=== PT2262-Format empfangen ===&lt;br /&gt;
Das Funk-Encoder-IC PT2262 der Firma PTC Taiwan (siehe [http://pdf.dzsc.com/88889/21967.pdf http://pdf.dzsc.com/88889/21967.pdf]) wird häufig in Fernbedienungen von Funksteckdosen und auch anderen Funkgeräten im 433-Mhz-Bereich verwendet. Es gibt viele PIN kompatible ICs wie z.B. der SC2262.&lt;br /&gt;
&lt;br /&gt;
Es werden hierbei 12 Zeichen im Tristate-Format (0, 1, 2 bzw. f) übertragen. Der erste Teil der Zeichen stellt die Adresse und die darauffolgenden Zeichen die Datenbits (Zeichen 0 oder 1) dar.&lt;br /&gt;
Die verwendeten Fernbedienungen haben häufig Dip-Schalter mit drei Zuständen (also 0,1,2), mit denen sich die Adressen einstellen lassen.&lt;br /&gt;
&lt;br /&gt;
Das Protokoll ist vom Aufbau ähnlich zum ARC-Protokoll. &lt;br /&gt;
&lt;br /&gt;
Dabei lassen sich die ersten 6-12 Zeichen als Adressen (A0 bis A11) und die letzten 0-6 Zeichen (D5-D0) als Datenbits nutzen. Es sind damit insgesamt folgende Kombinationen der Bits möglich:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 A11&lt;br /&gt;
A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 D0 &lt;br /&gt;
A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 D1 D0&lt;br /&gt;
A0 A1 A2 A3 A4 A5 A6 A7 A8 D2 D1 D0&lt;br /&gt;
A0 A1 A2 A3 A4 A5 A6 A7 D3 D2 D1 D0 &lt;br /&gt;
A0 A1 A2 A3 A4 A5 A6 D4 D3 D2 D1 D0 &lt;br /&gt;
A0 A1 A2 A3 A4 A5 D5 D4 D3 D2 D1 D0&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Damit lassen sich also maximal 6-Bit-Daten übertragen. Dies reicht für einfache Schaltaufgaben, aber nicht für Anwendungen wie beispielsweise Thermometer.&lt;br /&gt;
&lt;br /&gt;
RFXtrx433 läßt sich über RFXmngr so konfigurieren, dass die 12-Zeichen-Datagramme des PT2262-Formats als 24-Bit-Nutzdaten bzw. 3 Bytes empfangen werden können. Dazu kann man in RFXmngr das Protokoll Lighting4 einschalten, wodurch gleichzeitig die Verarbeitung des ARC-Protokolls ausgeschaltet wird.&lt;br /&gt;
Hinweise zur Nutzung sind in [http://www.rfxcom.com/Documents/RFXtrx%20User%20Guide.pdf http://www.rfxcom.com/Documents/RFXtrx%20User%20Guide.pdf] (Kapitel &amp;quot;8. Transmit undecoded ARC commands&amp;quot;) zu finden.&lt;br /&gt;
&lt;br /&gt;
Das FHEM-Modul TRX_LIGHT erlaubt die Verarbeitung des PT2262-Formates.&lt;br /&gt;
&lt;br /&gt;
Sobald Lighting4 eingeschaltet wird, werden die einzelnen Bits dem Gerät TRX_PT2262 zugeordnet. Sofern dieses noch nicht vorhanden ist, wird diesen per Autocreate definiert und ein entsprechendes Filelog angelegt.&lt;br /&gt;
&lt;br /&gt;
Wenn beispielsweise ein Nutzer einen Taster einer ELRO AB600 Fernbedienung drückt, werden je nach Codierung der Adresse folgende Codes im Filelog generiert:&lt;br /&gt;
&lt;br /&gt;
* Drücken der Taste &amp;quot;on&amp;quot;:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;2012-12-30_21:40:42 TRX_PT2262 111101110111&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Drücken von &amp;quot;off&amp;quot;:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;2012-12-30_21:40:47 TRX_PT2262 111101110110&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Auf diese Weise kann ein Nutzer sehen, welche PT2262-Codes von RFXtrx433 empfangen werden.&lt;br /&gt;
&lt;br /&gt;
Der Nutzer muss danach selbst entscheiden, welche Zeichen Adressen und welche Daten darstellen und was die Daten bedeuten. Im oben genannten Beispiel ist dies relativ einfach. Man sieht, dass sich nur das letzte Bit ändern und die Zustände 0 und 1 annimmt. Es ist daher anzunehmen, dass die ersten 11 Zeichen die Adresse repräsentieren.&lt;br /&gt;
&lt;br /&gt;
TRX_LIGHT bietet die Möglichkeit den Adressprefix, die sogenannte deviceid selbst in einem define-Statement festzulegen.&lt;br /&gt;
Die Konvention ist dabei, dass die einzelnen Zeichen der Base4-Codierung angegeben werden müssen:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define &amp;amp;lt;name&amp;amp;gt; TRX_LIGHT PT2262 &amp;amp;lt;deviceid&amp;amp;gt; &amp;amp;lt;devicelog&amp;amp;gt; [&amp;amp;lt;commandcodes&amp;amp;gt;]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
In commandcodes gibt man optional an wie die Ziffern Strings wie beispielsweise &amp;quot;on&amp;quot; oder &amp;quot;off&amp;quot; zugeordnet werden sollen. Dabei können über Komma getrennt wie die Ziffern den einzelnen Strings zugeordnet werden sollen. Jede einzelne Zuordnung wird über&amp;amp;#160;: angegeben. Zusätzlich sollte ein entsprechendes FileLog definiert werden.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
 define TRX_MYREMOTE1 TRX_LIGHT PT2262 11110111011 light 0:off,1:on&lt;br /&gt;
&lt;br /&gt;
 define FileLog_TRX_MYREMOTE1 FileLog /var/log/fhem/TRX_MYREMOTE1-%Y.log TRX_MYREMOTE1&lt;br /&gt;
&lt;br /&gt;
In diesem Fall wird die Ziffer 0 &amp;quot;off&amp;quot; und die Ziffer 1 &amp;quot;on&amp;quot; zugeordnet.&lt;br /&gt;
&lt;br /&gt;
Damit werden nach Drücken der Tasten on und off folgende Einträge im Filelog wie folgt generiert:&lt;br /&gt;
&lt;br /&gt;
   ==&amp;amp;gt; TRX_MYREMOTE1-2012.log &amp;amp;lt;==&lt;br /&gt;
   2012-12-30_21:54:56 TRX_MYREMOTE1 light: on&lt;br /&gt;
   2012-12-30_21:54:56 TRX_MYREMOTE1 on&lt;br /&gt;
&lt;br /&gt;
   ==&amp;amp;gt; TRX_MYREMOTE1-2012.log &amp;amp;lt;==&lt;br /&gt;
   2012-12-30_21:54:59 TRX_MYREMOTE1 light: off&lt;br /&gt;
   2012-12-30_21:54:59 TRX_MYREMOTE1 off&lt;br /&gt;
&lt;br /&gt;
=== PT2262-Format senden ===&lt;br /&gt;
Mit dem Funk-Decoder-IC PT2272 lassen sich Signale von PT2262-Sendern empfangen.&lt;br /&gt;
RFXtrx433 ist in der Lage Funksignale im PT2262-Format zu senden, die dann mit Geräten empfangen werden können, die über den Funk-Decoder-IC PT2272 verfügen. Dazu ist es nicht erforderlich in RFXmngr das Protokoll Lighting4 einzuschalten.&lt;br /&gt;
&lt;br /&gt;
PT2262-Codes können über ein set-Kommando des vorher zu definierenden PT2262-Devices gesendet werden. Die Definition wurde auch schon bei &amp;quot;PT2262-Format empfangen&amp;quot; beschrieben.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define &amp;amp;lt;name&amp;amp;gt; TRX_LIGHT PT2262 &amp;amp;lt;deviceid&amp;amp;gt; &amp;amp;lt;devicelog&amp;amp;gt; [&amp;amp;lt;commandcodes&amp;amp;gt;]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define TRX_MYREMOTE1 TRX_LIGHT PT2262 11110111011 light 0:off,1:on&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Sobald das Device definiert wurde, kann der Code mittels set gesendet werden. Dabei kann man entweder der Base4-Code direkt angegeben werden oder der String der in &amp;amp;lt;commandcodes&amp;amp;gt; definiert wurde.&lt;br /&gt;
&lt;br /&gt;
Beispiele (senden von 1):&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;set TRX_MYREMOTE1 1&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;set TRX_MYREMOTE1 on&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&amp;lt;nowiki&amp;gt;set TRX_MYREMOTE1 off&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Damit ein PT2262 Code gesendet werden kann, muss der Base4-Code bestehend aus &amp;amp;lt;deviceid&amp;amp;gt; und den Daten genau 12 Base4-Zeichen haben.&lt;br /&gt;
&lt;br /&gt;
Die mittels &amp;amp;lt;commandcodes&amp;amp;gt; definierten Strings werden in der Auswahlliste von set in der Weboberfläche von FHEM berücksichtigt.&lt;br /&gt;
&lt;br /&gt;
== Fragen und Antworten (FAQ) ==&lt;br /&gt;
&lt;br /&gt;
=== Warum wird mein RFXtrx433 nicht erkannt? ===&lt;br /&gt;
&lt;br /&gt;
Das Gerät hat einen FTDI-FT232R-USB-Interface-Chip installiert. Um RFXtrx433 nutzen zu können, muss das Betriebssystem einen entsprechenden Treiber für diesen Chip haben. Dies ist normalerweise bei Linux oder Fritzbox 7390 der Fall. Bei Windows muss ein entsprechender Treiber installiert werden. Siehe auch http://www.rfxcom.com/Documents/RFXtrx%20User%20Guide.pdf .&lt;br /&gt;
&lt;br /&gt;
Bei Fritzbox 7270 und 7170 werden vom Hersteller AVM mit der Firmware keine Treiber für den FTDI-FT232R-USB-Interface-Chip mitgeliefert. &lt;br /&gt;
&lt;br /&gt;
=== Warum werden die Tasten meiner Fernbedienung nicht alle erkannt? ===&lt;br /&gt;
Ist geklärt, dass die Fernbedienung von der Firmware supportet wird? Gerade beim ARC-Protokoll ist es häufig so, dass die Hersteller unterschiedliche Codierungen verwenden. &lt;br /&gt;
&lt;br /&gt;
Es wurde berichtet, dass die Tasten folgende Fernbedienungen von der Firnware des RFXtrx433 nicht alle richtig erkannt werden:&lt;br /&gt;
* ELRO AB440RA&lt;br /&gt;
Bei folgende Fernbedienungen wurden berichtet, dass diese richtig erkannt werden:&lt;br /&gt;
* ELRO AB600RA&lt;br /&gt;
&lt;br /&gt;
Bitte weitere Fernbedienungen melden!&lt;br /&gt;
[[Kategorie:Interfaces]]&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Optischer_Sensor,_Software&amp;diff=11917</id>
		<title>Optischer Sensor, Software</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Optischer_Sensor,_Software&amp;diff=11917"/>
		<updated>2015-08-06T19:14:11Z</updated>

		<summary type="html">&lt;p&gt;Rince: /* Windows */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- hier nicht erforderlich; verwirrt derzeit nur {{SEITENTITEL:Optischer Sensor, Software}} --&amp;gt;&lt;br /&gt;
&amp;lt;!-- stattdessen: evtl gleich {{Infobox Modul}} einbauen und füllen (und vielleicht auch an der darin vorgeschlagenen Gliederung orientieren) --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Hier wäre eine &amp;quot;Unterschrift&amp;quot; nicht schlecht, auch wenn in Artikeln/Seiten eigentlich unüblich. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Was ich noch nicht weiß==&lt;br /&gt;
* soll das Programm regelmäßig per Cron ausgeführt werden, oder ist es schlauer einen WebSocket zu öffnen, so dass fhem dem Programm sagen kann, wenn es ein Bild bearbeiten soll&lt;br /&gt;
* &amp;lt;s&amp;gt;Treshold für Farben im Programm anwenden,&amp;lt;/s&amp;gt; oder nackten Zähler direkt an fhem senden&lt;br /&gt;
** besser, eine Weiterverarbeitung der Werte in fhem&lt;br /&gt;
** fhem ist diesbezüglich viel mächtiger&lt;br /&gt;
&lt;br /&gt;
==Übersicht==&lt;br /&gt;
Das kleine Programm liest ein Farbbild ein. Anschließend werden (in definierbaren Bereichen) Farbwerte ermittelt. Das Resultat wird dann an fhem gesendet.&lt;br /&gt;
&lt;br /&gt;
Wozu ist das gut?&lt;br /&gt;
&lt;br /&gt;
Mein Anwendungsfall:&lt;br /&gt;
&lt;br /&gt;
Eine USB Kamera am Raspberry macht regelmäßig Bilder meiner Küche. Darin sind insbesondere die Geschirrspülmaschine und der Herd zu sehen. Wenn meine Geschirrspülmaschine Dinge wie Salz oder Klarspüler benötigt, leuchtet eine entsprechende LED rot auf. Das kann das Programm erkennen und fhem mitteilen. &lt;br /&gt;
Ähnlich beim Herd: ist der an, leuchtet es gelb. Beim Verlassen des Hauses kann mir fhem sagen, dass der Herd noch an ist...&lt;br /&gt;
&lt;br /&gt;
Wichtig:&lt;br /&gt;
Die Kamera darf nicht bewegt werden, sonst funktionieren die Masken nicht mehr! Also z.B. festschrauben...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anderer Anwendungsfall:&lt;br /&gt;
&lt;br /&gt;
Ein Bild (z.B. Bodenfeuchte) vom DWD runterladen (das müsst ihr selbst!), dann analysieren lassen, welche Bodenfeuchte bei euch ist. Selbiges wird an fhem gesendet.&lt;br /&gt;
&lt;br /&gt;
Einfach für jede mögliche Farbe eine eigene Maske erstellen (die ist natürlich identisch), in die conf die Farbwerte und die setreadings schreiben, fertig...&lt;br /&gt;
&lt;br /&gt;
{{Link2Forum|Topic=39678|LinkText=Forumsthread}}&lt;br /&gt;
&lt;br /&gt;
==Beschreibung==&lt;br /&gt;
Ein bisschen mehr ins Detail gehend:&lt;br /&gt;
&lt;br /&gt;
Das Programm erwartet ein farbiges Bitmap Bild. Anschließend werden Masken über das Bild gelegt. Was übrig bleibt (idealerweise also der Bildausschnitt wo die entsprechende LED zu sehen ist) wird in den HSV Farbraum konvertiert. Eine Beschreibung warum und wie er funktioniert, folgt noch. Dann werden Die gewünschten Farben gefiltert. Intern übrig bleiben dann einige weiße Pixel auf schwarzem Grund. Die werden schlicht gezählt. Der Wert wird an fhem gesendet.&lt;br /&gt;
&lt;br /&gt;
===Konfiguration der Software===&lt;br /&gt;
Das Programm an sich benötigt eine Config-Datei.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;fhem_host_port&amp;quot;: &amp;quot;http://192.168.5.31:8083&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_request&amp;quot;: &amp;quot;/fhem?cmd=&amp;quot;,&lt;br /&gt;
	&amp;quot;different_ROI&amp;quot;: &amp;quot;5&amp;quot;,&lt;br /&gt;
	&amp;quot;path_to_picture&amp;quot;: &amp;quot;./Picture&amp;quot;,&lt;br /&gt;
	&amp;quot;picture&amp;quot;: &amp;quot;picture_kitchen&amp;quot;,&lt;br /&gt;
	&amp;quot;type&amp;quot;: &amp;quot;jpg&amp;quot;,&lt;br /&gt;
	&amp;quot;mask&amp;quot;: &amp;quot;dishwasher&amp;quot;,&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Was ist hier einzustellen?&lt;br /&gt;
* &amp;quot;fhem_host_port&amp;quot;: Adresse des fhem Servers, ebenso wie der Port. (Muss man also anpassen)&lt;br /&gt;
* &amp;quot;fhem_request&amp;quot;: (weiß nicht, wie es heißt), sollte aber so passen&lt;br /&gt;
* &amp;quot;different_ROI&amp;quot;: ist spannend: hier sagt man, wie viele LEDs (ROI = region of interesst) man überwachen will. (für jede ROI muss genau 1 Maske existieren)&lt;br /&gt;
* &amp;quot;path_to_picture&amp;quot;: logisch, wo liegt das Bild? In diesem Fall in einem Unterordner Namens Picture&lt;br /&gt;
* &amp;quot;picture&amp;quot;: der Name des Bildes (aufgemerkt: das Programm geht also immer vom gleichen Dateinamen aus!) (Quellbild)&lt;br /&gt;
* &amp;quot;type&amp;quot;: bitte mit angeben; jpg, png...&lt;br /&gt;
* &amp;quot;mask&amp;quot;: der erste Teil des Maskennamens&lt;br /&gt;
** die Dateiendung nicht angeben, bitte die gleiche wie beim Quellbild verwenden&lt;br /&gt;
** so kann man bei einem Quellbild verschiedene Masken angeben (in verschiedenen Config Dateien)&lt;br /&gt;
** bei Karten vom DWD z.B. kann man so aus einem Quellbild Werte für verschiedene Regionen ermitteln&lt;br /&gt;
** munic.conf, berlin.conf&lt;br /&gt;
** bei mehr Küchengeräten z.B. dishwasher.conf und waterboiler.conf&lt;br /&gt;
&lt;br /&gt;
===Was sind diese Masken?===&lt;br /&gt;
Die sind cool. Einfache schwarz/weiß Bilder.&lt;br /&gt;
&lt;br /&gt;
Zum erstellen:&lt;br /&gt;
Ein Musterbild von der Kamera besorgen. In Gimp öffnen, den Bereich um eine der gewünschten LEDs ein Viereck oder ein Kreis, ist egal) markieren. Löschen, Füllfarbe weiß. Markierung umdrehen, löschen, Füllfarbe schwarz. Fertig.&lt;br /&gt;
&lt;br /&gt;
Stellt euch vor, die Maske wäre aus Tonpapier. Da wo weiß ist, ist ein Loch drin. Die Maske wird über das Bild gelegt. Nun seht ihr nur noch die gewünschte LED...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wichtig:&lt;br /&gt;
&lt;br /&gt;
Die Maske braucht nun einen festen Dateinamen, damit sie gefunden werden kann! Hängt an den in der Config angegebenen Dateinamen ein _mask_1 an, für eure erste Maske. Hättet ihr ROI = 1, ist das alles. Bei ROI = 2 wollen wir 2 Masken abarbeiten.&lt;br /&gt;
&lt;br /&gt;
Also, bei ROI = 3&lt;br /&gt;
* quellbild.jpg (das, was eure Kamera immer generiert, oder euch der DWD zur Verfügung stellt)&lt;br /&gt;
* &amp;lt;AngegebenerName&amp;gt;_mask_1.jpg (die Dateiendung bitte wie beim Quellbild)&lt;br /&gt;
* &amp;lt;AngegebenerName&amp;gt;_mask_2.jpg&lt;br /&gt;
* &amp;lt;AngegebenerName&amp;gt;_mask_3.jpg&lt;br /&gt;
&lt;br /&gt;
===Benötigte Frameworks===&lt;br /&gt;
folgt noch&lt;br /&gt;
&lt;br /&gt;
====Linux====&lt;br /&gt;
[http://www.pyimagesearch.com/2015/02/23/install-opencv-and-python-on-your-raspberry-pi-2-and-b/ Diese] Anleitung ist wirklich gut. Habe es auf meinem RasPi auch so gemacht. Wer das nicht alles von Hand installieren will, kann es sich (jedenfalls mit Debian 8) auch einfacher machen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt-get install libopencv-dev python-opencv&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Windows====&lt;br /&gt;
Folgende Programme runterladen und in die vorgeschlagenen (!) Ordner installieren&lt;br /&gt;
*[http://sourceforge.net/projects/opencvlibrary/files/opencv-win/2.4.11/opencv-2.4.11.exe/download OpenCV]&lt;br /&gt;
*[http://python.org/ftp/python/2.7.5/python-2.7.5.msi Python]&lt;br /&gt;
*[https://downloads.sourceforge.net/project/numpy/NumPy/1.8.0/numpy-1.8.0-win32-superpack-python2.7.exe NumPy]&lt;br /&gt;
*[https://downloads.sourceforge.net/project/matplotlib/matplotlib/matplotlib-1.3.0/matplotlib-1.3.0.win32-py2.7.exe Matplotlib] (hierfür nicht nöTig)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Jetzt bitte alles von C:\opencv\build\python\x86\2.7\ (vermutlich nur cv2.pyd) in den Ordner C:\Python27\Lib\site-packages\ kopieren. Das ist wichtig, damit Python OpenCV findet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zum Test kann man unter Windows eimfach maal Python starten und&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import cv2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Eingeben... gibt es keinen Fehler, hat es geklappt.&lt;br /&gt;
&lt;br /&gt;
===Kalibrierung des Sensors===&lt;br /&gt;
Das Programm kennt zwei verschiedene Betriebsmodi:&lt;br /&gt;
&lt;br /&gt;
====RGB / BGR====&lt;br /&gt;
RGB (dafür in der json den Wert &amp;quot;hsv&amp;quot; auf false setzen)&lt;br /&gt;
RGB eignet sich gut, um Grafiken zu untersuchen. Siehe das DWD Beispiel. Bitte als B G R die Werte eingeben (nicht RGB).&lt;br /&gt;
&lt;br /&gt;
Wenn es jeweils nur eine Farbe ist, die gesucht werden soll, so ist der upper/lower Wert natürlich identisch.&lt;br /&gt;
&lt;br /&gt;
Die Werte kann man schlicht mit Gimp auslesen (Pipette, auf die gewünschte Farbe klicken, im Werkzeugfenster auf die Farbe klicken, dann stehen die Werte da...)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====HSV====&lt;br /&gt;
Das ist etwas tricky.&lt;br /&gt;
&lt;br /&gt;
Obacht: didaktische Reduktion!&lt;br /&gt;
&lt;br /&gt;
Prinzipiell kann man sich HSV zunächst mal als einen Farbkreis vorstellen. Damit bekommt jede Farbe einen Winkel. Der Witz an der Sache ist, dass die Helligkeit hier keine Rolle spielt. Die versteckt sich nämlich nicht auf unserem Farbkreis! Diese wird durch die Tiefe repräsentiert. Dazu legen wir jetzt unseren Farbkreis auf eine Papprolle (und knippsen oben ein imaginäres Licht an).&lt;br /&gt;
&lt;br /&gt;
Wenn wir uns jetzt die Farbe &amp;quot;Rot&amp;quot; vorstellen, dann gibt es davon ziemlich viele verschiedene. Von sehr hell, bis sehr dunkel. Der Winkel für helles und der für dunkles Rot ist im HSV Farbkreis der gleiche. Das macht diesen Farbraum für die Auswertung von Fotos sehr praktisch. Man kann schön mit zwei Werten quasi alle Rot-Töne abdecken.&lt;br /&gt;
&lt;br /&gt;
Der Haken:&lt;br /&gt;
&lt;br /&gt;
OpenCV sieht leider HSV anders, als GIMP. Daher ist es nicht ganz trivial, die passenden Werte für die Farben rauszufinden.&lt;br /&gt;
&lt;br /&gt;
Gebe im Forum dazu gerne Hilfestellung.&lt;br /&gt;
&lt;br /&gt;
==Programmcode==&lt;br /&gt;
Der Programmcode ist im ersten Forumsthread mit einigen Beispielen zum Download.&lt;br /&gt;
[http://forum.fhem.de/index.php/topic,39678.msg318865.html#msg318865 Download]&lt;br /&gt;
&lt;br /&gt;
===Sensor===&lt;br /&gt;
Anmerkung:&lt;br /&gt;
&lt;br /&gt;
Ich bin kein Programmierer. Wenn das jemand durchliest der Ahnung hat, sich totlacht =&amp;gt; ich übernehme keine Verantwortung&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# Optical Sensor&lt;br /&gt;
# using Python 2.7 and OpenCV 2.4.11&lt;br /&gt;
# do not use german umlauts, not even in description&lt;br /&gt;
# ver 0.2 first public release&lt;br /&gt;
import cv2&lt;br /&gt;
import argparse&lt;br /&gt;
import json&lt;br /&gt;
import urllib&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
#cv2 importiert OpenCV&lt;br /&gt;
#argparse wird benoetigt fuer die Parameteruebergabe&lt;br /&gt;
#json zum lesen des Config-Files&lt;br /&gt;
#urllib um uns mit fhem zu unterhalten&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# construct the argument parse and parse the arguments&lt;br /&gt;
ap = argparse.ArgumentParser()&lt;br /&gt;
ap.add_argument(&amp;quot;-c&amp;quot;, &amp;quot;--conf&amp;quot;, required=True,&lt;br /&gt;
	help=&amp;quot;path to the JSON configuration file; eg try: &amp;gt;sensor.py --conf dishwasher.json&amp;quot;)&lt;br /&gt;
args = vars(ap.parse_args())&lt;br /&gt;
&lt;br /&gt;
#ConfigFile laden&lt;br /&gt;
conf = json.load(open(args[&amp;quot;conf&amp;quot;]))&lt;br /&gt;
client = None&lt;br /&gt;
&lt;br /&gt;
#Gespeichertes Bild mit Pfad in Variable&lt;br /&gt;
path = (conf[&amp;quot;path_to_picture&amp;quot;])&lt;br /&gt;
picture = (conf[&amp;quot;picture&amp;quot;])&lt;br /&gt;
type = (conf[&amp;quot;type&amp;quot;])&lt;br /&gt;
first_picture = path + &amp;quot;/&amp;quot; + picture + &amp;quot;.&amp;quot; + type&lt;br /&gt;
&lt;br /&gt;
#Namen der Maske auslesen&lt;br /&gt;
first_mask = (conf[&amp;quot;mask&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
#Laden des Bildes&lt;br /&gt;
image = cv2.imread(first_picture)&lt;br /&gt;
&lt;br /&gt;
# Bild anzeigen&lt;br /&gt;
#cv2.imshow(&amp;quot;Originalbild&amp;quot;, image)&lt;br /&gt;
&lt;br /&gt;
# Schleife erzeugen&lt;br /&gt;
ROI = int(conf[&amp;quot;different_ROI&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
print &amp;quot;Soll-Durchlaeufe &amp;quot; + str(ROI)&lt;br /&gt;
&lt;br /&gt;
i = 0&lt;br /&gt;
while i &amp;lt; ROI:&lt;br /&gt;
	i = i + 1&lt;br /&gt;
	&lt;br /&gt;
	# Maskenpfad und Dateinamen generieren&lt;br /&gt;
	mask = path + &amp;quot;/&amp;quot; + first_mask + &amp;quot;_mask_&amp;quot; + str(i) + &amp;quot;.&amp;quot; + type&lt;br /&gt;
	&lt;br /&gt;
	# Maske laden&lt;br /&gt;
	mask = cv2.imread(mask,0)&lt;br /&gt;
	&lt;br /&gt;
	# Maske anwenden&lt;br /&gt;
	masked = cv2.bitwise_and(image, image, mask = mask)&lt;br /&gt;
	#cv2.imshow(&amp;quot;Maske&amp;quot;, masked)&lt;br /&gt;
	&lt;br /&gt;
	# BGR in HSV konvertieren wenn gewollt&lt;br /&gt;
	if conf[&amp;quot;hsv&amp;quot;]: &lt;br /&gt;
		masked = cv2.cvtColor(masked, cv2.COLOR_BGR2HSV)&lt;br /&gt;
		#cv2.imshow(&amp;quot;HSV&amp;quot;, masked)&lt;br /&gt;
	&lt;br /&gt;
	# Grenzwerte aus Config auslesen&lt;br /&gt;
	lower_col_value = tuple(conf[&amp;quot;lower_col&amp;quot; + &amp;quot;_&amp;quot; + str(i)])&lt;br /&gt;
	upper_col_value = tuple(conf[&amp;quot;upper_col&amp;quot; + &amp;quot;_&amp;quot; + str(i)])&lt;br /&gt;
	#print lower_col&lt;br /&gt;
	#print upper_col&lt;br /&gt;
	&lt;br /&gt;
	# Range definieren&lt;br /&gt;
	lower_col = np.array([(lower_col_value)], dtype=np.uint8)&lt;br /&gt;
	upper_col = np.array([(upper_col_value)], dtype=np.uint8)&lt;br /&gt;
&lt;br /&gt;
	# Threshold the image to get only selected colors&lt;br /&gt;
	mask = cv2.inRange(masked, lower_col, upper_col)&lt;br /&gt;
	#cv2.imshow(&amp;quot;Maske&amp;quot;, mask)&lt;br /&gt;
&lt;br /&gt;
	# Pixel zaehlen&lt;br /&gt;
	white = cv2.countNonZero(mask)&lt;br /&gt;
	print(&#039;The number of positive pixels is: &#039; + str(white))&lt;br /&gt;
	&lt;br /&gt;
	# Pixelanzahl an fhem senden&lt;br /&gt;
	# fhem Kommando erzeugen&lt;br /&gt;
	url = (conf[&amp;quot;fhem_host_port&amp;quot;])&lt;br /&gt;
	request = (conf[&amp;quot;fhem_request&amp;quot;])&lt;br /&gt;
	command = (conf[&amp;quot;fhem_command&amp;quot; + &amp;quot;_&amp;quot; + str(i)])&lt;br /&gt;
	value =  &amp;quot;%20&amp;quot; + str(white)&lt;br /&gt;
	fhem = url + request + command + value&lt;br /&gt;
	#print fhem&lt;br /&gt;
	urllib.urlopen(fhem)&lt;br /&gt;
	&lt;br /&gt;
	#cv2.waitKey(0)&lt;br /&gt;
	&lt;br /&gt;
print &amp;quot;Fertig&amp;quot;	&lt;br /&gt;
#cv2.waitKey(0)&lt;br /&gt;
cv2.destroyAllWindows()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config-File===&lt;br /&gt;
So kann ein Config File aussehen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
5seenland.json (könnte ein guter Dateinname sein...)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;config_version&amp;quot;: &amp;quot;0.2&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_host_port&amp;quot;: &amp;quot;http://192.168.5.31:8083&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_request&amp;quot;: &amp;quot;/fhem?cmd=&amp;quot;,&lt;br /&gt;
	&amp;quot;different_ROI&amp;quot;: &amp;quot;8&amp;quot;,&lt;br /&gt;
	&amp;quot;path_to_picture&amp;quot;: &amp;quot;./Picture&amp;quot;,&lt;br /&gt;
	&amp;quot;picture&amp;quot;: &amp;quot;bodenfeuchte&amp;quot;,&lt;br /&gt;
	&amp;quot;type&amp;quot;: &amp;quot;png&amp;quot;,&lt;br /&gt;
	&amp;quot;mask&amp;quot;: &amp;quot;5seenland&amp;quot;,&lt;br /&gt;
	&amp;quot;hsv&amp;quot;: false,&lt;br /&gt;
	&amp;quot;lower_col_1&amp;quot;: [45,100,200],&lt;br /&gt;
	&amp;quot;upper_col_1&amp;quot;: [45,100,200],&lt;br /&gt;
	&amp;quot;lower_col_2&amp;quot;: [60,200,250],&lt;br /&gt;
	&amp;quot;upper_col_2&amp;quot;: [60,200,250],&lt;br /&gt;
	&amp;quot;lower_col_3&amp;quot;: [75,250,250],&lt;br /&gt;
	&amp;quot;upper_col_3&amp;quot;: [75,250,250],&lt;br /&gt;
	&amp;quot;lower_col_4&amp;quot;: [75,250,200],&lt;br /&gt;
	&amp;quot;upper_col_4&amp;quot;: [75,250,200],&lt;br /&gt;
	&amp;quot;lower_col_5&amp;quot;: [75,220,150],&lt;br /&gt;
	&amp;quot;upper_col_5&amp;quot;: [75,220,150],&lt;br /&gt;
	&amp;quot;lower_col_6&amp;quot;: [75,150,75],&lt;br /&gt;
	&amp;quot;upper_col_6&amp;quot;: [75,150,75],&lt;br /&gt;
	&amp;quot;lower_col_7&amp;quot;: [250,200,50],&lt;br /&gt;
	&amp;quot;upper_col_7&amp;quot;: [250,200,50],&lt;br /&gt;
	&amp;quot;lower_col_8&amp;quot;: [250,0,0],&lt;br /&gt;
	&amp;quot;upper_col_8&amp;quot;: [250,0,0],&lt;br /&gt;
	&amp;quot;fhem_command_1&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%200-10&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_2&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2010-30&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_3&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2030-50&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_4&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2050-80&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_5&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2080-95&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_6&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2095-100&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_7&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%20100-105&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_8&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%20105-&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Eigentlich ganz einfach. Für jede ROI benötigt man lower_col_?, upper_col_? und fhem_command_?&lt;br /&gt;
&lt;br /&gt;
Die  lower/upper cols definieren für jede ROI den zu suchenden Farbbereich... das Ergebnis wird dann an den fhem_command_? angehängt.&lt;br /&gt;
&lt;br /&gt;
Hat man nur 2 ROI, kann man die Werte 3-8 natürlich rauswerfen; andernfalls werden sie schlicht ignoriert, tun also nicht weh. Sind nur eben sinnbefreit.&lt;br /&gt;
&lt;br /&gt;
===Beispiel mit Bildern===&lt;br /&gt;
Ist denke ich im Forumsthread schon ganz schön beschrieben.&lt;br /&gt;
&lt;br /&gt;
Wer eigene Beispiele hat, immer her damit :)&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Optischer_Sensor,_Software&amp;diff=11907</id>
		<title>Optischer Sensor, Software</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Optischer_Sensor,_Software&amp;diff=11907"/>
		<updated>2015-08-06T09:39:30Z</updated>

		<summary type="html">&lt;p&gt;Rince: /* Linux */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- hier nicht erforderlich; verwirrt derzeit nur {{SEITENTITEL:Optischer Sensor, Software}} --&amp;gt;&lt;br /&gt;
&amp;lt;!-- stattdessen: evtl gleich {{Infobox Modul}} einbauen und füllen (und vielleicht auch an der darin vorgeschlagenen Gliederung orientieren) --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Hier wäre eine &amp;quot;Unterschrift&amp;quot; nicht schlecht, auch wenn in Artikeln/Seiten eigentlich unüblich. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Was ich noch nicht weiß==&lt;br /&gt;
* soll das Programm regelmäßig per Cron ausgeführt werden, oder ist es schlauer einen WebSocket zu öffnen, so dass fhem dem Programm sagen kann, wenn es ein Bild bearbeiten soll&lt;br /&gt;
* &amp;lt;s&amp;gt;Treshold für Farben im Programm anwenden,&amp;lt;/s&amp;gt; oder nackten Zähler direkt an fhem senden&lt;br /&gt;
** besser, eine Weiterverarbeitung der Werte in fhem&lt;br /&gt;
** fhem ist diesbezüglich viel mächtiger&lt;br /&gt;
&lt;br /&gt;
==Übersicht==&lt;br /&gt;
Das kleine Programm liest ein Farbbild ein. Anschließend werden (in definierbaren Bereichen) Farbwerte ermittelt. Das Resultat wird dann an fhem gesendet.&lt;br /&gt;
&lt;br /&gt;
Wozu ist das gut?&lt;br /&gt;
&lt;br /&gt;
Mein Anwendungsfall:&lt;br /&gt;
&lt;br /&gt;
Eine USB Kamera am Raspberry macht regelmäßig Bilder meiner Küche. Darin sind insbesondere die Geschirrspülmaschine und der Herd zu sehen. Wenn meine Geschirrspülmaschine Dinge wie Salz oder Klarspüler benötigt, leuchtet eine entsprechende LED rot auf. Das kann das Programm erkennen und fhem mitteilen. &lt;br /&gt;
Ähnlich beim Herd: ist der an, leuchtet es gelb. Beim Verlassen des Hauses kann mir fhem sagen, dass der Herd noch an ist...&lt;br /&gt;
&lt;br /&gt;
Wichtig:&lt;br /&gt;
Die Kamera darf nicht bewegt werden, sonst funktionieren die Masken nicht mehr! Also z.B. festschrauben...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anderer Anwendungsfall:&lt;br /&gt;
&lt;br /&gt;
Ein Bild (z.B. Bodenfeuchte) vom DWD runterladen (das müsst ihr selbst!), dann analysieren lassen, welche Bodenfeuchte bei euch ist. Selbiges wird an fhem gesendet.&lt;br /&gt;
&lt;br /&gt;
Einfach für jede mögliche Farbe eine eigene Maske erstellen (die ist natürlich identisch), in die conf die Farbwerte und die setreadings schreiben, fertig...&lt;br /&gt;
&lt;br /&gt;
{{Link2Forum|Topic=39678|LinkText=Forumsthread}}&lt;br /&gt;
&lt;br /&gt;
==Beschreibung==&lt;br /&gt;
Ein bisschen mehr ins Detail gehend:&lt;br /&gt;
&lt;br /&gt;
Das Programm erwartet ein farbiges Bitmap Bild. Anschließend werden Masken über das Bild gelegt. Was übrig bleibt (idealerweise also der Bildausschnitt wo die entsprechende LED zu sehen ist) wird in den HSV Farbraum konvertiert. Eine Beschreibung warum und wie er funktioniert, folgt noch. Dann werden Die gewünschten Farben gefiltert. Intern übrig bleiben dann einige weiße Pixel auf schwarzem Grund. Die werden schlicht gezählt. Der Wert wird an fhem gesendet.&lt;br /&gt;
&lt;br /&gt;
===Konfiguration der Software===&lt;br /&gt;
Das Programm an sich benötigt eine Config-Datei.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;fhem_host_port&amp;quot;: &amp;quot;http://192.168.5.31:8083&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_request&amp;quot;: &amp;quot;/fhem?cmd=&amp;quot;,&lt;br /&gt;
	&amp;quot;different_ROI&amp;quot;: &amp;quot;5&amp;quot;,&lt;br /&gt;
	&amp;quot;path_to_picture&amp;quot;: &amp;quot;./Picture&amp;quot;,&lt;br /&gt;
	&amp;quot;picture&amp;quot;: &amp;quot;picture_kitchen&amp;quot;,&lt;br /&gt;
	&amp;quot;type&amp;quot;: &amp;quot;jpg&amp;quot;,&lt;br /&gt;
	&amp;quot;mask&amp;quot;: &amp;quot;dishwasher&amp;quot;,&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Was ist hier einzustellen?&lt;br /&gt;
* &amp;quot;fhem_host_port&amp;quot;: Adresse des fhem Servers, ebenso wie der Port. (Muss man also anpassen)&lt;br /&gt;
* &amp;quot;fhem_request&amp;quot;: (weiß nicht, wie es heißt), sollte aber so passen&lt;br /&gt;
* &amp;quot;different_ROI&amp;quot;: ist spannend: hier sagt man, wie viele LEDs (ROI = region of interesst) man überwachen will. (für jede ROI muss genau 1 Maske existieren)&lt;br /&gt;
* &amp;quot;path_to_picture&amp;quot;: logisch, wo liegt das Bild? In diesem Fall in einem Unterordner Namens Picture&lt;br /&gt;
* &amp;quot;picture&amp;quot;: der Name des Bildes (aufgemerkt: das Programm geht also immer vom gleichen Dateinamen aus!) (Quellbild)&lt;br /&gt;
* &amp;quot;type&amp;quot;: bitte mit angeben; jpg, png...&lt;br /&gt;
* &amp;quot;mask&amp;quot;: der erste Teil des Maskennamens&lt;br /&gt;
** die Dateiendung nicht angeben, bitte die gleiche wie beim Quellbild verwenden&lt;br /&gt;
** so kann man bei einem Quellbild verschiedene Masken angeben (in verschiedenen Config Dateien)&lt;br /&gt;
** bei Karten vom DWD z.B. kann man so aus einem Quellbild Werte für verschiedene Regionen ermitteln&lt;br /&gt;
** munic.conf, berlin.conf&lt;br /&gt;
** bei mehr Küchengeräten z.B. dishwasher.conf und waterboiler.conf&lt;br /&gt;
&lt;br /&gt;
===Was sind diese Masken?===&lt;br /&gt;
Die sind cool. Einfache schwarz/weiß Bilder.&lt;br /&gt;
&lt;br /&gt;
Zum erstellen:&lt;br /&gt;
Ein Musterbild von der Kamera besorgen. In Gimp öffnen, den Bereich um eine der gewünschten LEDs ein Viereck oder ein Kreis, ist egal) markieren. Löschen, Füllfarbe weiß. Markierung umdrehen, löschen, Füllfarbe schwarz. Fertig.&lt;br /&gt;
&lt;br /&gt;
Stellt euch vor, die Maske wäre aus Tonpapier. Da wo weiß ist, ist ein Loch drin. Die Maske wird über das Bild gelegt. Nun seht ihr nur noch die gewünschte LED...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wichtig:&lt;br /&gt;
&lt;br /&gt;
Die Maske braucht nun einen festen Dateinamen, damit sie gefunden werden kann! Hängt an den in der Config angegebenen Dateinamen ein _mask_1 an, für eure erste Maske. Hättet ihr ROI = 1, ist das alles. Bei ROI = 2 wollen wir 2 Masken abarbeiten.&lt;br /&gt;
&lt;br /&gt;
Also, bei ROI = 3&lt;br /&gt;
* quellbild.jpg (das, was eure Kamera immer generiert, oder euch der DWD zur Verfügung stellt)&lt;br /&gt;
* &amp;lt;AngegebenerName&amp;gt;_mask_1.jpg (die Dateiendung bitte wie beim Quellbild)&lt;br /&gt;
* &amp;lt;AngegebenerName&amp;gt;_mask_2.jpg&lt;br /&gt;
* &amp;lt;AngegebenerName&amp;gt;_mask_3.jpg&lt;br /&gt;
&lt;br /&gt;
===Benötigte Frameworks===&lt;br /&gt;
folgt noch&lt;br /&gt;
&lt;br /&gt;
====Linux====&lt;br /&gt;
[http://www.pyimagesearch.com/2015/02/23/install-opencv-and-python-on-your-raspberry-pi-2-and-b/ Diese] Anleitung ist wirklich gut. Habe es auf meinem RasPi auch so gemacht. Wer das nicht alles von Hand installieren will, kann es sich (jedenfalls mit Debian 8) auch einfacher machen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt-get install libopencv-dev python-opencv&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Windows====&lt;br /&gt;
Folgende Programme runterladen und in die vorgeschlagenen (!) Ordner installieren&lt;br /&gt;
*[http://sourceforge.net/projects/opencvlibrary/files/opencv-win/2.4.11/opencv-2.4.11.exe/download OpenCV]&lt;br /&gt;
*[http://python.org/ftp/python/2.7.5/python-2.7.5.msi Python]&lt;br /&gt;
*[https://downloads.sourceforge.net/project/numpy/NumPy/1.8.0/numpy-1.8.0-win32-superpack-python2.7.exe NumPy]&lt;br /&gt;
*[https://downloads.sourceforge.net/project/matplotlib/matplotlib/matplotlib-1.3.0/matplotlib-1.3.0.win32-py2.7.exe Matplotlib] (hierfür nicht nötig)&lt;br /&gt;
&lt;br /&gt;
===Kalibrierung des Sensors===&lt;br /&gt;
Das Programm kennt zwei verschiedene Betriebsmodi:&lt;br /&gt;
&lt;br /&gt;
====RGB / BGR====&lt;br /&gt;
RGB (dafür in der json den Wert &amp;quot;hsv&amp;quot; auf false setzen)&lt;br /&gt;
RGB eignet sich gut, um Grafiken zu untersuchen. Siehe das DWD Beispiel. Bitte als B G R die Werte eingeben (nicht RGB).&lt;br /&gt;
&lt;br /&gt;
Wenn es jeweils nur eine Farbe ist, die gesucht werden soll, so ist der upper/lower Wert natürlich identisch.&lt;br /&gt;
&lt;br /&gt;
Die Werte kann man schlicht mit Gimp auslesen (Pipette, auf die gewünschte Farbe klicken, im Werkzeugfenster auf die Farbe klicken, dann stehen die Werte da...)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====HSV====&lt;br /&gt;
Das ist etwas tricky.&lt;br /&gt;
&lt;br /&gt;
Obacht: didaktische Reduktion!&lt;br /&gt;
&lt;br /&gt;
Prinzipiell kann man sich HSV zunächst mal als einen Farbkreis vorstellen. Damit bekommt jede Farbe einen Winkel. Der Witz an der Sache ist, dass die Helligkeit hier keine Rolle spielt. Die versteckt sich nämlich nicht auf unserem Farbkreis! Diese wird durch die Tiefe repräsentiert. Dazu legen wir jetzt unseren Farbkreis auf eine Papprolle (und knippsen oben ein imaginäres Licht an).&lt;br /&gt;
&lt;br /&gt;
Wenn wir uns jetzt die Farbe &amp;quot;Rot&amp;quot; vorstellen, dann gibt es davon ziemlich viele verschiedene. Von sehr hell, bis sehr dunkel. Der Winkel für helles und der für dunkles Rot ist im HSV Farbkreis der gleiche. Das macht diesen Farbraum für die Auswertung von Fotos sehr praktisch. Man kann schön mit zwei Werten quasi alle Rot-Töne abdecken.&lt;br /&gt;
&lt;br /&gt;
Der Haken:&lt;br /&gt;
&lt;br /&gt;
OpenCV sieht leider HSV anders, als GIMP. Daher ist es nicht ganz trivial, die passenden Werte für die Farben rauszufinden.&lt;br /&gt;
&lt;br /&gt;
Gebe im Forum dazu gerne Hilfestellung.&lt;br /&gt;
&lt;br /&gt;
==Programmcode==&lt;br /&gt;
Der Programmcode ist im ersten Forumsthread mit einigen Beispielen zum Download.&lt;br /&gt;
[http://forum.fhem.de/index.php/topic,39678.msg318865.html#msg318865 Download]&lt;br /&gt;
&lt;br /&gt;
===Sensor===&lt;br /&gt;
Anmerkung:&lt;br /&gt;
&lt;br /&gt;
Ich bin kein Programmierer. Wenn das jemand durchliest der Ahnung hat, sich totlacht =&amp;gt; ich übernehme keine Verantwortung&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# Optical Sensor&lt;br /&gt;
# using Python 2.7 and OpenCV 2.4.11&lt;br /&gt;
# do not use german umlauts, not even in description&lt;br /&gt;
# ver 0.2 first public release&lt;br /&gt;
import cv2&lt;br /&gt;
import argparse&lt;br /&gt;
import json&lt;br /&gt;
import urllib&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
#cv2 importiert OpenCV&lt;br /&gt;
#argparse wird benoetigt fuer die Parameteruebergabe&lt;br /&gt;
#json zum lesen des Config-Files&lt;br /&gt;
#urllib um uns mit fhem zu unterhalten&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# construct the argument parse and parse the arguments&lt;br /&gt;
ap = argparse.ArgumentParser()&lt;br /&gt;
ap.add_argument(&amp;quot;-c&amp;quot;, &amp;quot;--conf&amp;quot;, required=True,&lt;br /&gt;
	help=&amp;quot;path to the JSON configuration file; eg try: &amp;gt;sensor.py --conf dishwasher.json&amp;quot;)&lt;br /&gt;
args = vars(ap.parse_args())&lt;br /&gt;
&lt;br /&gt;
#ConfigFile laden&lt;br /&gt;
conf = json.load(open(args[&amp;quot;conf&amp;quot;]))&lt;br /&gt;
client = None&lt;br /&gt;
&lt;br /&gt;
#Gespeichertes Bild mit Pfad in Variable&lt;br /&gt;
path = (conf[&amp;quot;path_to_picture&amp;quot;])&lt;br /&gt;
picture = (conf[&amp;quot;picture&amp;quot;])&lt;br /&gt;
type = (conf[&amp;quot;type&amp;quot;])&lt;br /&gt;
first_picture = path + &amp;quot;/&amp;quot; + picture + &amp;quot;.&amp;quot; + type&lt;br /&gt;
&lt;br /&gt;
#Namen der Maske auslesen&lt;br /&gt;
first_mask = (conf[&amp;quot;mask&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
#Laden des Bildes&lt;br /&gt;
image = cv2.imread(first_picture)&lt;br /&gt;
&lt;br /&gt;
# Bild anzeigen&lt;br /&gt;
#cv2.imshow(&amp;quot;Originalbild&amp;quot;, image)&lt;br /&gt;
&lt;br /&gt;
# Schleife erzeugen&lt;br /&gt;
ROI = int(conf[&amp;quot;different_ROI&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
print &amp;quot;Soll-Durchlaeufe &amp;quot; + str(ROI)&lt;br /&gt;
&lt;br /&gt;
i = 0&lt;br /&gt;
while i &amp;lt; ROI:&lt;br /&gt;
	i = i + 1&lt;br /&gt;
	&lt;br /&gt;
	# Maskenpfad und Dateinamen generieren&lt;br /&gt;
	mask = path + &amp;quot;/&amp;quot; + first_mask + &amp;quot;_mask_&amp;quot; + str(i) + &amp;quot;.&amp;quot; + type&lt;br /&gt;
	&lt;br /&gt;
	# Maske laden&lt;br /&gt;
	mask = cv2.imread(mask,0)&lt;br /&gt;
	&lt;br /&gt;
	# Maske anwenden&lt;br /&gt;
	masked = cv2.bitwise_and(image, image, mask = mask)&lt;br /&gt;
	#cv2.imshow(&amp;quot;Maske&amp;quot;, masked)&lt;br /&gt;
	&lt;br /&gt;
	# BGR in HSV konvertieren wenn gewollt&lt;br /&gt;
	if conf[&amp;quot;hsv&amp;quot;]: &lt;br /&gt;
		masked = cv2.cvtColor(masked, cv2.COLOR_BGR2HSV)&lt;br /&gt;
		#cv2.imshow(&amp;quot;HSV&amp;quot;, masked)&lt;br /&gt;
	&lt;br /&gt;
	# Grenzwerte aus Config auslesen&lt;br /&gt;
	lower_col_value = tuple(conf[&amp;quot;lower_col&amp;quot; + &amp;quot;_&amp;quot; + str(i)])&lt;br /&gt;
	upper_col_value = tuple(conf[&amp;quot;upper_col&amp;quot; + &amp;quot;_&amp;quot; + str(i)])&lt;br /&gt;
	#print lower_col&lt;br /&gt;
	#print upper_col&lt;br /&gt;
	&lt;br /&gt;
	# Range definieren&lt;br /&gt;
	lower_col = np.array([(lower_col_value)], dtype=np.uint8)&lt;br /&gt;
	upper_col = np.array([(upper_col_value)], dtype=np.uint8)&lt;br /&gt;
&lt;br /&gt;
	# Threshold the image to get only selected colors&lt;br /&gt;
	mask = cv2.inRange(masked, lower_col, upper_col)&lt;br /&gt;
	#cv2.imshow(&amp;quot;Maske&amp;quot;, mask)&lt;br /&gt;
&lt;br /&gt;
	# Pixel zaehlen&lt;br /&gt;
	white = cv2.countNonZero(mask)&lt;br /&gt;
	print(&#039;The number of positive pixels is: &#039; + str(white))&lt;br /&gt;
	&lt;br /&gt;
	# Pixelanzahl an fhem senden&lt;br /&gt;
	# fhem Kommando erzeugen&lt;br /&gt;
	url = (conf[&amp;quot;fhem_host_port&amp;quot;])&lt;br /&gt;
	request = (conf[&amp;quot;fhem_request&amp;quot;])&lt;br /&gt;
	command = (conf[&amp;quot;fhem_command&amp;quot; + &amp;quot;_&amp;quot; + str(i)])&lt;br /&gt;
	value =  &amp;quot;%20&amp;quot; + str(white)&lt;br /&gt;
	fhem = url + request + command + value&lt;br /&gt;
	#print fhem&lt;br /&gt;
	urllib.urlopen(fhem)&lt;br /&gt;
	&lt;br /&gt;
	#cv2.waitKey(0)&lt;br /&gt;
	&lt;br /&gt;
print &amp;quot;Fertig&amp;quot;	&lt;br /&gt;
#cv2.waitKey(0)&lt;br /&gt;
cv2.destroyAllWindows()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config-File===&lt;br /&gt;
So kann ein Config File aussehen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
5seenland.json (könnte ein guter Dateinname sein...)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;config_version&amp;quot;: &amp;quot;0.2&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_host_port&amp;quot;: &amp;quot;http://192.168.5.31:8083&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_request&amp;quot;: &amp;quot;/fhem?cmd=&amp;quot;,&lt;br /&gt;
	&amp;quot;different_ROI&amp;quot;: &amp;quot;8&amp;quot;,&lt;br /&gt;
	&amp;quot;path_to_picture&amp;quot;: &amp;quot;./Picture&amp;quot;,&lt;br /&gt;
	&amp;quot;picture&amp;quot;: &amp;quot;bodenfeuchte&amp;quot;,&lt;br /&gt;
	&amp;quot;type&amp;quot;: &amp;quot;png&amp;quot;,&lt;br /&gt;
	&amp;quot;mask&amp;quot;: &amp;quot;5seenland&amp;quot;,&lt;br /&gt;
	&amp;quot;hsv&amp;quot;: false,&lt;br /&gt;
	&amp;quot;lower_col_1&amp;quot;: [45,100,200],&lt;br /&gt;
	&amp;quot;upper_col_1&amp;quot;: [45,100,200],&lt;br /&gt;
	&amp;quot;lower_col_2&amp;quot;: [60,200,250],&lt;br /&gt;
	&amp;quot;upper_col_2&amp;quot;: [60,200,250],&lt;br /&gt;
	&amp;quot;lower_col_3&amp;quot;: [75,250,250],&lt;br /&gt;
	&amp;quot;upper_col_3&amp;quot;: [75,250,250],&lt;br /&gt;
	&amp;quot;lower_col_4&amp;quot;: [75,250,200],&lt;br /&gt;
	&amp;quot;upper_col_4&amp;quot;: [75,250,200],&lt;br /&gt;
	&amp;quot;lower_col_5&amp;quot;: [75,220,150],&lt;br /&gt;
	&amp;quot;upper_col_5&amp;quot;: [75,220,150],&lt;br /&gt;
	&amp;quot;lower_col_6&amp;quot;: [75,150,75],&lt;br /&gt;
	&amp;quot;upper_col_6&amp;quot;: [75,150,75],&lt;br /&gt;
	&amp;quot;lower_col_7&amp;quot;: [250,200,50],&lt;br /&gt;
	&amp;quot;upper_col_7&amp;quot;: [250,200,50],&lt;br /&gt;
	&amp;quot;lower_col_8&amp;quot;: [250,0,0],&lt;br /&gt;
	&amp;quot;upper_col_8&amp;quot;: [250,0,0],&lt;br /&gt;
	&amp;quot;fhem_command_1&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%200-10&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_2&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2010-30&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_3&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2030-50&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_4&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2050-80&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_5&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2080-95&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_6&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2095-100&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_7&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%20100-105&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_8&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%20105-&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Eigentlich ganz einfach. Für jede ROI benötigt man lower_col_?, upper_col_? und fhem_command_?&lt;br /&gt;
&lt;br /&gt;
Die  lower/upper cols definieren für jede ROI den zu suchenden Farbbereich... das Ergebnis wird dann an den fhem_command_? angehängt.&lt;br /&gt;
&lt;br /&gt;
Hat man nur 2 ROI, kann man die Werte 3-8 natürlich rauswerfen; andernfalls werden sie schlicht ignoriert, tun also nicht weh. Sind nur eben sinnbefreit.&lt;br /&gt;
&lt;br /&gt;
===Beispiel mit Bildern===&lt;br /&gt;
Ist denke ich im Forumsthread schon ganz schön beschrieben.&lt;br /&gt;
&lt;br /&gt;
Wer eigene Beispiele hat, immer her damit :)&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Optischer_Sensor,_Software&amp;diff=11893</id>
		<title>Optischer Sensor, Software</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Optischer_Sensor,_Software&amp;diff=11893"/>
		<updated>2015-08-04T19:49:23Z</updated>

		<summary type="html">&lt;p&gt;Rince: Soweit fertig; warte auf Wünsche und Verbesserungsvorschläge&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- hier nicht erforderlich; verwirrt derzeit nur {{SEITENTITEL:Optischer Sensor, Software}} --&amp;gt;&lt;br /&gt;
&amp;lt;!-- stattdessen: evtl gleich {{Infobox Modul}} einbauen und füllen (und vielleicht auch an der darin vorgeschlagenen Gliederung orientieren) --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Hier wäre eine &amp;quot;Unterschrift&amp;quot; nicht schlecht, auch wenn in Artikeln/Seiten eigentlich unüblich. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Was ich noch nicht weiß==&lt;br /&gt;
* soll das Programm regelmäßig per Cron ausgeführt werden, oder ist es schlauer einen WebSocket zu öffnen, so dass fhem dem Programm sagen kann, wenn es ein Bild bearbeiten soll&lt;br /&gt;
* &amp;lt;s&amp;gt;Treshold für Farben im Programm anwenden,&amp;lt;/s&amp;gt; oder nackten Zähler direkt an fhem senden&lt;br /&gt;
** besser, eine Weiterverarbeitung der Werte in fhem&lt;br /&gt;
** fhem ist diesbezüglich viel mächtiger&lt;br /&gt;
&lt;br /&gt;
==Übersicht==&lt;br /&gt;
Das kleine Programm liest ein Farbbild ein. Anschließend werden (in definierbaren Bereichen) Farbwerte ermittelt. Das Resultat wird dann an fhem gesendet.&lt;br /&gt;
&lt;br /&gt;
Wozu ist das gut?&lt;br /&gt;
&lt;br /&gt;
Mein Anwendungsfall:&lt;br /&gt;
&lt;br /&gt;
Eine USB Kamera am Raspberry macht regelmäßig Bilder meiner Küche. Darin sind insbesondere die Geschirrspülmaschine und der Herd zu sehen. Wenn meine Geschirrspülmaschine Dinge wie Salz oder Klarspüler benötigt, leuchtet eine entsprechende LED rot auf. Das kann das Programm erkennen und fhem mitteilen. &lt;br /&gt;
Ähnlich beim Herd: ist der an, leuchtet es gelb. Beim Verlassen des Hauses kann mir fhem sagen, dass der Herd noch an ist...&lt;br /&gt;
&lt;br /&gt;
Wichtig:&lt;br /&gt;
Die Kamera darf nicht bewegt werden, sonst funktionieren die Masken nicht mehr! Also z.B. festschrauben...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anderer Anwendungsfall:&lt;br /&gt;
&lt;br /&gt;
Ein Bild (z.B. Bodenfeuchte) vom DWD runterladen (das müsst ihr selbst!), dann analysieren lassen, welche Bodenfeuchte bei euch ist. Selbiges wird an fhem gesendet.&lt;br /&gt;
&lt;br /&gt;
Einfach für jede mögliche Farbe eine eigene Maske erstellen (die ist natürlich identisch), in die conf die Farbwerte und die setreadings schreiben, fertig...&lt;br /&gt;
&lt;br /&gt;
{{Link2Forum|Topic=39678|LinkText=Forumsthread}}&lt;br /&gt;
&lt;br /&gt;
==Beschreibung==&lt;br /&gt;
Ein bisschen mehr ins Detail gehend:&lt;br /&gt;
&lt;br /&gt;
Das Programm erwartet ein farbiges Bitmap Bild. Anschließend werden Masken über das Bild gelegt. Was übrig bleibt (idealerweise also der Bildausschnitt wo die entsprechende LED zu sehen ist) wird in den HSV Farbraum konvertiert. Eine Beschreibung warum und wie er funktioniert, folgt noch. Dann werden Die gewünschten Farben gefiltert. Intern übrig bleiben dann einige weiße Pixel auf schwarzem Grund. Die werden schlicht gezählt. Der Wert wird an fhem gesendet.&lt;br /&gt;
&lt;br /&gt;
===Konfiguration der Software===&lt;br /&gt;
Das Programm an sich benötigt eine Config-Datei.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;fhem_host_port&amp;quot;: &amp;quot;http://192.168.5.31:8083&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_request&amp;quot;: &amp;quot;/fhem?cmd=&amp;quot;,&lt;br /&gt;
	&amp;quot;different_ROI&amp;quot;: &amp;quot;5&amp;quot;,&lt;br /&gt;
	&amp;quot;path_to_picture&amp;quot;: &amp;quot;./Picture&amp;quot;,&lt;br /&gt;
	&amp;quot;picture&amp;quot;: &amp;quot;picture_kitchen&amp;quot;,&lt;br /&gt;
	&amp;quot;type&amp;quot;: &amp;quot;jpg&amp;quot;,&lt;br /&gt;
	&amp;quot;mask&amp;quot;: &amp;quot;dishwasher&amp;quot;,&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Was ist hier einzustellen?&lt;br /&gt;
* &amp;quot;fhem_host_port&amp;quot;: Adresse des fhem Servers, ebenso wie der Port. (Muss man also anpassen)&lt;br /&gt;
* &amp;quot;fhem_request&amp;quot;: (weiß nicht, wie es heißt), sollte aber so passen&lt;br /&gt;
* &amp;quot;different_ROI&amp;quot;: ist spannend: hier sagt man, wie viele LEDs (ROI = region of interesst) man überwachen will. (für jede ROI muss genau 1 Maske existieren)&lt;br /&gt;
* &amp;quot;path_to_picture&amp;quot;: logisch, wo liegt das Bild? In diesem Fall in einem Unterordner Namens Picture&lt;br /&gt;
* &amp;quot;picture&amp;quot;: der Name des Bildes (aufgemerkt: das Programm geht also immer vom gleichen Dateinamen aus!) (Quellbild)&lt;br /&gt;
* &amp;quot;type&amp;quot;: bitte mit angeben; jpg, png...&lt;br /&gt;
* &amp;quot;mask&amp;quot;: der erste Teil des Maskennamens&lt;br /&gt;
** die Dateiendung nicht angeben, bitte die gleiche wie beim Quellbild verwenden&lt;br /&gt;
** so kann man bei einem Quellbild verschiedene Masken angeben (in verschiedenen Config Dateien)&lt;br /&gt;
** bei Karten vom DWD z.B. kann man so aus einem Quellbild Werte für verschiedene Regionen ermitteln&lt;br /&gt;
** munic.conf, berlin.conf&lt;br /&gt;
** bei mehr Küchengeräten z.B. dishwasher.conf und waterboiler.conf&lt;br /&gt;
&lt;br /&gt;
===Was sind diese Masken?===&lt;br /&gt;
Die sind cool. Einfache schwarz/weiß Bilder.&lt;br /&gt;
&lt;br /&gt;
Zum erstellen:&lt;br /&gt;
Ein Musterbild von der Kamera besorgen. In Gimp öffnen, den Bereich um eine der gewünschten LEDs ein Viereck oder ein Kreis, ist egal) markieren. Löschen, Füllfarbe weiß. Markierung umdrehen, löschen, Füllfarbe schwarz. Fertig.&lt;br /&gt;
&lt;br /&gt;
Stellt euch vor, die Maske wäre aus Tonpapier. Da wo weiß ist, ist ein Loch drin. Die Maske wird über das Bild gelegt. Nun seht ihr nur noch die gewünschte LED...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wichtig:&lt;br /&gt;
&lt;br /&gt;
Die Maske braucht nun einen festen Dateinamen, damit sie gefunden werden kann! Hängt an den in der Config angegebenen Dateinamen ein _mask_1 an, für eure erste Maske. Hättet ihr ROI = 1, ist das alles. Bei ROI = 2 wollen wir 2 Masken abarbeiten.&lt;br /&gt;
&lt;br /&gt;
Also, bei ROI = 3&lt;br /&gt;
* quellbild.jpg (das, was eure Kamera immer generiert, oder euch der DWD zur Verfügung stellt)&lt;br /&gt;
* &amp;lt;AngegebenerName&amp;gt;_mask_1.jpg (die Dateiendung bitte wie beim Quellbild)&lt;br /&gt;
* &amp;lt;AngegebenerName&amp;gt;_mask_2.jpg&lt;br /&gt;
* &amp;lt;AngegebenerName&amp;gt;_mask_3.jpg&lt;br /&gt;
&lt;br /&gt;
===Benötigte Frameworks===&lt;br /&gt;
folgt noch&lt;br /&gt;
&lt;br /&gt;
====Linux====&lt;br /&gt;
[http://www.pyimagesearch.com/2015/02/23/install-opencv-and-python-on-your-raspberry-pi-2-and-b/ Diese] Anleitung ist wirklich gut. Habe es auf meinem RasPi auch so gemacht.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Windows====&lt;br /&gt;
Folgende Programme runterladen und in die vorgeschlagenen (!) Ordner installieren&lt;br /&gt;
*[http://sourceforge.net/projects/opencvlibrary/files/opencv-win/2.4.11/opencv-2.4.11.exe/download OpenCV]&lt;br /&gt;
*[http://python.org/ftp/python/2.7.5/python-2.7.5.msi Python]&lt;br /&gt;
*[https://downloads.sourceforge.net/project/numpy/NumPy/1.8.0/numpy-1.8.0-win32-superpack-python2.7.exe NumPy]&lt;br /&gt;
*[https://downloads.sourceforge.net/project/matplotlib/matplotlib/matplotlib-1.3.0/matplotlib-1.3.0.win32-py2.7.exe Matplotlib] (hierfür nicht nötig)&lt;br /&gt;
&lt;br /&gt;
===Kalibrierung des Sensors===&lt;br /&gt;
Das Programm kennt zwei verschiedene Betriebsmodi:&lt;br /&gt;
&lt;br /&gt;
====RGB / BGR====&lt;br /&gt;
RGB (dafür in der json den Wert &amp;quot;hsv&amp;quot; auf false setzen)&lt;br /&gt;
RGB eignet sich gut, um Grafiken zu untersuchen. Siehe das DWD Beispiel. Bitte als B G R die Werte eingeben (nicht RGB).&lt;br /&gt;
&lt;br /&gt;
Wenn es jeweils nur eine Farbe ist, die gesucht werden soll, so ist der upper/lower Wert natürlich identisch.&lt;br /&gt;
&lt;br /&gt;
Die Werte kann man schlicht mit Gimp auslesen (Pipette, auf die gewünschte Farbe klicken, im Werkzeugfenster auf die Farbe klicken, dann stehen die Werte da...)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====HSV====&lt;br /&gt;
Das ist etwas tricky.&lt;br /&gt;
&lt;br /&gt;
Obacht: didaktische Reduktion!&lt;br /&gt;
&lt;br /&gt;
Prinzipiell kann man sich HSV zunächst mal als einen Farbkreis vorstellen. Damit bekommt jede Farbe einen Winkel. Der Witz an der Sache ist, dass die Helligkeit hier keine Rolle spielt. Die versteckt sich nämlich nicht auf unserem Farbkreis! Diese wird durch die Tiefe repräsentiert. Dazu legen wir jetzt unseren Farbkreis auf eine Papprolle (und knippsen oben ein imaginäres Licht an).&lt;br /&gt;
&lt;br /&gt;
Wenn wir uns jetzt die Farbe &amp;quot;Rot&amp;quot; vorstellen, dann gibt es davon ziemlich viele verschiedene. Von sehr hell, bis sehr dunkel. Der Winkel für helles und der für dunkles Rot ist im HSV Farbkreis der gleiche. Das macht diesen Farbraum für die Auswertung von Fotos sehr praktisch. Man kann schön mit zwei Werten quasi alle Rot-Töne abdecken.&lt;br /&gt;
&lt;br /&gt;
Der Haken:&lt;br /&gt;
&lt;br /&gt;
OpenCV sieht leider HSV anders, als GIMP. Daher ist es nicht ganz trivial, die passenden Werte für die Farben rauszufinden.&lt;br /&gt;
&lt;br /&gt;
Gebe im Forum dazu gerne Hilfestellung.&lt;br /&gt;
&lt;br /&gt;
==Programmcode==&lt;br /&gt;
Der Programmcode ist im ersten Forumsthread mit einigen Beispielen zum Download.&lt;br /&gt;
[http://forum.fhem.de/index.php/topic,39678.msg318865.html#msg318865 Download]&lt;br /&gt;
&lt;br /&gt;
===Sensor===&lt;br /&gt;
Anmerkung:&lt;br /&gt;
&lt;br /&gt;
Ich bin kein Programmierer. Wenn das jemand durchliest der Ahnung hat, sich totlacht =&amp;gt; ich übernehme keine Verantwortung&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# Optical Sensor&lt;br /&gt;
# using Python 2.7 and OpenCV 2.4.11&lt;br /&gt;
# do not use german umlauts, not even in description&lt;br /&gt;
# ver 0.2 first public release&lt;br /&gt;
import cv2&lt;br /&gt;
import argparse&lt;br /&gt;
import json&lt;br /&gt;
import urllib&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
#cv2 importiert OpenCV&lt;br /&gt;
#argparse wird benoetigt fuer die Parameteruebergabe&lt;br /&gt;
#json zum lesen des Config-Files&lt;br /&gt;
#urllib um uns mit fhem zu unterhalten&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# construct the argument parse and parse the arguments&lt;br /&gt;
ap = argparse.ArgumentParser()&lt;br /&gt;
ap.add_argument(&amp;quot;-c&amp;quot;, &amp;quot;--conf&amp;quot;, required=True,&lt;br /&gt;
	help=&amp;quot;path to the JSON configuration file; eg try: &amp;gt;sensor.py --conf dishwasher.json&amp;quot;)&lt;br /&gt;
args = vars(ap.parse_args())&lt;br /&gt;
&lt;br /&gt;
#ConfigFile laden&lt;br /&gt;
conf = json.load(open(args[&amp;quot;conf&amp;quot;]))&lt;br /&gt;
client = None&lt;br /&gt;
&lt;br /&gt;
#Gespeichertes Bild mit Pfad in Variable&lt;br /&gt;
path = (conf[&amp;quot;path_to_picture&amp;quot;])&lt;br /&gt;
picture = (conf[&amp;quot;picture&amp;quot;])&lt;br /&gt;
type = (conf[&amp;quot;type&amp;quot;])&lt;br /&gt;
first_picture = path + &amp;quot;/&amp;quot; + picture + &amp;quot;.&amp;quot; + type&lt;br /&gt;
&lt;br /&gt;
#Namen der Maske auslesen&lt;br /&gt;
first_mask = (conf[&amp;quot;mask&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
#Laden des Bildes&lt;br /&gt;
image = cv2.imread(first_picture)&lt;br /&gt;
&lt;br /&gt;
# Bild anzeigen&lt;br /&gt;
#cv2.imshow(&amp;quot;Originalbild&amp;quot;, image)&lt;br /&gt;
&lt;br /&gt;
# Schleife erzeugen&lt;br /&gt;
ROI = int(conf[&amp;quot;different_ROI&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
print &amp;quot;Soll-Durchlaeufe &amp;quot; + str(ROI)&lt;br /&gt;
&lt;br /&gt;
i = 0&lt;br /&gt;
while i &amp;lt; ROI:&lt;br /&gt;
	i = i + 1&lt;br /&gt;
	&lt;br /&gt;
	# Maskenpfad und Dateinamen generieren&lt;br /&gt;
	mask = path + &amp;quot;/&amp;quot; + first_mask + &amp;quot;_mask_&amp;quot; + str(i) + &amp;quot;.&amp;quot; + type&lt;br /&gt;
	&lt;br /&gt;
	# Maske laden&lt;br /&gt;
	mask = cv2.imread(mask,0)&lt;br /&gt;
	&lt;br /&gt;
	# Maske anwenden&lt;br /&gt;
	masked = cv2.bitwise_and(image, image, mask = mask)&lt;br /&gt;
	#cv2.imshow(&amp;quot;Maske&amp;quot;, masked)&lt;br /&gt;
	&lt;br /&gt;
	# BGR in HSV konvertieren wenn gewollt&lt;br /&gt;
	if conf[&amp;quot;hsv&amp;quot;]: &lt;br /&gt;
		masked = cv2.cvtColor(masked, cv2.COLOR_BGR2HSV)&lt;br /&gt;
		#cv2.imshow(&amp;quot;HSV&amp;quot;, masked)&lt;br /&gt;
	&lt;br /&gt;
	# Grenzwerte aus Config auslesen&lt;br /&gt;
	lower_col_value = tuple(conf[&amp;quot;lower_col&amp;quot; + &amp;quot;_&amp;quot; + str(i)])&lt;br /&gt;
	upper_col_value = tuple(conf[&amp;quot;upper_col&amp;quot; + &amp;quot;_&amp;quot; + str(i)])&lt;br /&gt;
	#print lower_col&lt;br /&gt;
	#print upper_col&lt;br /&gt;
	&lt;br /&gt;
	# Range definieren&lt;br /&gt;
	lower_col = np.array([(lower_col_value)], dtype=np.uint8)&lt;br /&gt;
	upper_col = np.array([(upper_col_value)], dtype=np.uint8)&lt;br /&gt;
&lt;br /&gt;
	# Threshold the image to get only selected colors&lt;br /&gt;
	mask = cv2.inRange(masked, lower_col, upper_col)&lt;br /&gt;
	#cv2.imshow(&amp;quot;Maske&amp;quot;, mask)&lt;br /&gt;
&lt;br /&gt;
	# Pixel zaehlen&lt;br /&gt;
	white = cv2.countNonZero(mask)&lt;br /&gt;
	print(&#039;The number of positive pixels is: &#039; + str(white))&lt;br /&gt;
	&lt;br /&gt;
	# Pixelanzahl an fhem senden&lt;br /&gt;
	# fhem Kommando erzeugen&lt;br /&gt;
	url = (conf[&amp;quot;fhem_host_port&amp;quot;])&lt;br /&gt;
	request = (conf[&amp;quot;fhem_request&amp;quot;])&lt;br /&gt;
	command = (conf[&amp;quot;fhem_command&amp;quot; + &amp;quot;_&amp;quot; + str(i)])&lt;br /&gt;
	value =  &amp;quot;%20&amp;quot; + str(white)&lt;br /&gt;
	fhem = url + request + command + value&lt;br /&gt;
	#print fhem&lt;br /&gt;
	urllib.urlopen(fhem)&lt;br /&gt;
	&lt;br /&gt;
	#cv2.waitKey(0)&lt;br /&gt;
	&lt;br /&gt;
print &amp;quot;Fertig&amp;quot;	&lt;br /&gt;
#cv2.waitKey(0)&lt;br /&gt;
cv2.destroyAllWindows()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config-File===&lt;br /&gt;
So kann ein Config File aussehen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
5seenland.json (könnte ein guter Dateinname sein...)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;config_version&amp;quot;: &amp;quot;0.2&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_host_port&amp;quot;: &amp;quot;http://192.168.5.31:8083&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_request&amp;quot;: &amp;quot;/fhem?cmd=&amp;quot;,&lt;br /&gt;
	&amp;quot;different_ROI&amp;quot;: &amp;quot;8&amp;quot;,&lt;br /&gt;
	&amp;quot;path_to_picture&amp;quot;: &amp;quot;./Picture&amp;quot;,&lt;br /&gt;
	&amp;quot;picture&amp;quot;: &amp;quot;bodenfeuchte&amp;quot;,&lt;br /&gt;
	&amp;quot;type&amp;quot;: &amp;quot;png&amp;quot;,&lt;br /&gt;
	&amp;quot;mask&amp;quot;: &amp;quot;5seenland&amp;quot;,&lt;br /&gt;
	&amp;quot;hsv&amp;quot;: false,&lt;br /&gt;
	&amp;quot;lower_col_1&amp;quot;: [45,100,200],&lt;br /&gt;
	&amp;quot;upper_col_1&amp;quot;: [45,100,200],&lt;br /&gt;
	&amp;quot;lower_col_2&amp;quot;: [60,200,250],&lt;br /&gt;
	&amp;quot;upper_col_2&amp;quot;: [60,200,250],&lt;br /&gt;
	&amp;quot;lower_col_3&amp;quot;: [75,250,250],&lt;br /&gt;
	&amp;quot;upper_col_3&amp;quot;: [75,250,250],&lt;br /&gt;
	&amp;quot;lower_col_4&amp;quot;: [75,250,200],&lt;br /&gt;
	&amp;quot;upper_col_4&amp;quot;: [75,250,200],&lt;br /&gt;
	&amp;quot;lower_col_5&amp;quot;: [75,220,150],&lt;br /&gt;
	&amp;quot;upper_col_5&amp;quot;: [75,220,150],&lt;br /&gt;
	&amp;quot;lower_col_6&amp;quot;: [75,150,75],&lt;br /&gt;
	&amp;quot;upper_col_6&amp;quot;: [75,150,75],&lt;br /&gt;
	&amp;quot;lower_col_7&amp;quot;: [250,200,50],&lt;br /&gt;
	&amp;quot;upper_col_7&amp;quot;: [250,200,50],&lt;br /&gt;
	&amp;quot;lower_col_8&amp;quot;: [250,0,0],&lt;br /&gt;
	&amp;quot;upper_col_8&amp;quot;: [250,0,0],&lt;br /&gt;
	&amp;quot;fhem_command_1&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%200-10&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_2&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2010-30&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_3&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2030-50&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_4&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2050-80&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_5&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2080-95&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_6&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2095-100&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_7&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%20100-105&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_8&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%20105-&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Eigentlich ganz einfach. Für jede ROI benötigt man lower_col_?, upper_col_? und fhem_command_?&lt;br /&gt;
&lt;br /&gt;
Die  lower/upper cols definieren für jede ROI den zu suchenden Farbbereich... das Ergebnis wird dann an den fhem_command_? angehängt.&lt;br /&gt;
&lt;br /&gt;
Hat man nur 2 ROI, kann man die Werte 3-8 natürlich rauswerfen; andernfalls werden sie schlicht ignoriert, tun also nicht weh. Sind nur eben sinnbefreit.&lt;br /&gt;
&lt;br /&gt;
===Beispiel mit Bildern===&lt;br /&gt;
Ist denke ich im Forumsthread schon ganz schön beschrieben.&lt;br /&gt;
&lt;br /&gt;
Wer eigene Beispiele hat, immer her damit :)&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Optischer_Sensor,_Software&amp;diff=11892</id>
		<title>Optischer Sensor, Software</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Optischer_Sensor,_Software&amp;diff=11892"/>
		<updated>2015-08-04T17:03:51Z</updated>

		<summary type="html">&lt;p&gt;Rince: /* Windows */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- hier nicht erforderlich; verwirrt derzeit nur {{SEITENTITEL:Optischer Sensor, Software}} --&amp;gt;&lt;br /&gt;
&amp;lt;!-- stattdessen: evtl gleich {{Infobox Modul}} einbauen und füllen (und vielleicht auch an der darin vorgeschlagenen Gliederung orientieren) --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todo|Das wird die Doku für den optischen Sensor. Der Programmcode ist ziemlich weit gediehen. Ich dachte mir, die Doku mal zum Start eines Projekts fertig zu haben, ist auch nicht schlecht}}&lt;br /&gt;
&amp;lt;!-- Hier wäre eine &amp;quot;Unterschrift&amp;quot; nicht schlecht, auch wenn in Artikeln/Seiten eigentlich unüblich. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Was ich noch nicht weiß==&lt;br /&gt;
* soll das Programm regelmäßig per Cron ausgeführt werden, oder ist es schlauer einen WebSocket zu öffnen, so dass fhem dem Programm sagen kann, wenn es ein Bild bearbeiten soll&lt;br /&gt;
* &amp;lt;s&amp;gt;Treshold für Farben im Programm anwenden,&amp;lt;/s&amp;gt; oder nackten Zähler direkt an fhem senden&lt;br /&gt;
** besser, eine Weiterverarbeitung der Werte in fhem&lt;br /&gt;
** fhem ist diesbezüglich viel mächtiger&lt;br /&gt;
&lt;br /&gt;
==Übersicht==&lt;br /&gt;
Das kleine Programm liest ein Farbbild ein. Anschließend werden (in definierbaren Bereichen) Farbwerte ermittelt. Das Resultat wird dann an fhem gesendet.&lt;br /&gt;
&lt;br /&gt;
Wozu ist das gut?&lt;br /&gt;
&lt;br /&gt;
Mein Anwendungsfall:&lt;br /&gt;
&lt;br /&gt;
Eine USB Kamera am Raspberry macht regelmäßig Bilder meiner Küche. Darin sind insbesondere die Geschirrspülmaschine und der Herd zu sehen. Wenn meine Geschirrspülmaschine Dinge wie Salz oder Klarspüler benötigt, leuchtet eine entsprechende LED rot auf. Das kann das Programm erkennen und fhem mitteilen. &lt;br /&gt;
Ähnlich beim Herd: ist der an, leuchtet es gelb. Beim Verlassen des Hauses kann mir fhem sagen, dass der Herd noch an ist...&lt;br /&gt;
&lt;br /&gt;
Wichtig:&lt;br /&gt;
Die Kamera darf nicht bewegt werden, sonst funktionieren die Masken nicht mehr! Also z.B. festschrauben...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anderer Anwendungsfall:&lt;br /&gt;
&lt;br /&gt;
Ein Bild (z.B. Bodenfeuchte) vom DWD runterladen (das müsst ihr selbst!), dann analysieren lassen, welche Bodenfeuchte bei euch ist. Selbiges wird an fhem gesendet.&lt;br /&gt;
&lt;br /&gt;
Einfach für jede mögliche Farbe eine eigene Maske erstellen (die ist natürlich identisch), in die conf die Farbwerte und die setreadings schreiben, fertig...&lt;br /&gt;
&lt;br /&gt;
{{Link2Forum|Topic=39678|LinkText=Forumsthread}}&lt;br /&gt;
&lt;br /&gt;
==Beschreibung==&lt;br /&gt;
Ein bisschen mehr ins Detail gehend:&lt;br /&gt;
&lt;br /&gt;
Das Programm erwartet ein farbiges Bitmap Bild. Anschließend werden Masken über das Bild gelegt. Was übrig bleibt (idealerweise also der Bildausschnitt wo die entsprechende LED zu sehen ist) wird in den HSV Farbraum konvertiert. Eine Beschreibung warum und wie er funktioniert, folgt noch. Dann werden Die gewünschten Farben gefiltert. Intern übrig bleiben dann einige weiße Pixel auf schwarzem Grund. Die werden schlicht gezählt. Der Wert wird an fhem gesendet.&lt;br /&gt;
&lt;br /&gt;
===Konfiguration der Software===&lt;br /&gt;
Das Programm an sich benötigt eine Config-Datei.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;fhem_host_port&amp;quot;: &amp;quot;http://192.168.5.31:8083&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_request&amp;quot;: &amp;quot;/fhem?cmd=&amp;quot;,&lt;br /&gt;
	&amp;quot;different_ROI&amp;quot;: &amp;quot;5&amp;quot;,&lt;br /&gt;
	&amp;quot;path_to_picture&amp;quot;: &amp;quot;./Picture&amp;quot;,&lt;br /&gt;
	&amp;quot;picture&amp;quot;: &amp;quot;picture_kitchen&amp;quot;,&lt;br /&gt;
	&amp;quot;type&amp;quot;: &amp;quot;jpg&amp;quot;,&lt;br /&gt;
	&amp;quot;mask&amp;quot;: &amp;quot;dishwasher&amp;quot;,&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Was ist hier einzustellen?&lt;br /&gt;
* &amp;quot;fhem_host_port&amp;quot;: Adresse des fhem Servers, ebenso wie der Port. (Muss man also anpassen)&lt;br /&gt;
* &amp;quot;fhem_request&amp;quot;: (weiß nicht, wie es heißt), sollte aber so passen&lt;br /&gt;
* &amp;quot;different_ROI&amp;quot;: ist spannend: hier sagt man, wie viele LEDs (ROI = region of interesst) man überwachen will. (für jede ROI muss genau 1 Maske existieren)&lt;br /&gt;
* &amp;quot;path_to_picture&amp;quot;: logisch, wo liegt das Bild? In diesem Fall in einem Unterordner Namens Picture&lt;br /&gt;
* &amp;quot;picture&amp;quot;: der Name des Bildes (aufgemerkt: das Programm geht also immer vom gleichen Dateinamen aus!) (Quellbild)&lt;br /&gt;
* &amp;quot;type&amp;quot;: bitte mit angeben; jpg, png...&lt;br /&gt;
* &amp;quot;mask&amp;quot;: der erste Teil des Maskennamens&lt;br /&gt;
** die Dateiendung nicht angeben, bitte die gleiche wie beim Quellbild verwenden&lt;br /&gt;
** so kann man bei einem Quellbild verschiedene Masken angeben (in verschiedenen Config Dateien)&lt;br /&gt;
** bei Karten vom DWD z.B. kann man so aus einem Quellbild Werte für verschiedene Regionen ermitteln&lt;br /&gt;
** munic.conf, berlin.conf&lt;br /&gt;
** bei mehr Küchengeräten z.B. dishwasher.conf und waterboiler.conf&lt;br /&gt;
&lt;br /&gt;
===Was sind diese Masken?===&lt;br /&gt;
Die sind cool. Einfache schwarz/weiß Bilder.&lt;br /&gt;
&lt;br /&gt;
Zum erstellen:&lt;br /&gt;
Ein Musterbild von der Kamera besorgen. In Gimp öffnen, den Bereich um eine der gewünschten LEDs ein Viereck oder ein Kreis, ist egal) markieren. Löschen, Füllfarbe weiß. Markierung umdrehen, löschen, Füllfarbe schwarz. Fertig.&lt;br /&gt;
&lt;br /&gt;
Stellt euch vor, die Maske wäre aus Tonpapier. Da wo weiß ist, ist ein Loch drin. Die Maske wird über das Bild gelegt. Nun seht ihr nur noch die gewünschte LED...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wichtig:&lt;br /&gt;
&lt;br /&gt;
Die Maske braucht nun einen festen Dateinamen, damit sie gefunden werden kann! Hängt an den in der Config angegebenen Dateinamen ein _mask_1 an, für eure erste Maske. Hättet ihr ROI = 1, ist das alles. Bei ROI = 2 wollen wir 2 Masken abarbeiten.&lt;br /&gt;
&lt;br /&gt;
Also, bei ROI = 3&lt;br /&gt;
* quellbild.jpg (das, was eure Kamera immer generiert, oder euch der DWD zur Verfügung stellt)&lt;br /&gt;
* &amp;lt;AngegebenerName&amp;gt;_mask_1.jpg (die Dateiendung bitte wie beim Quellbild)&lt;br /&gt;
* &amp;lt;AngegebenerName&amp;gt;_mask_2.jpg&lt;br /&gt;
* &amp;lt;AngegebenerName&amp;gt;_mask_3.jpg&lt;br /&gt;
&lt;br /&gt;
===Benötigte Frameworks===&lt;br /&gt;
folgt noch&lt;br /&gt;
&lt;br /&gt;
====Linux====&lt;br /&gt;
[http://www.pyimagesearch.com/2015/02/23/install-opencv-and-python-on-your-raspberry-pi-2-and-b/ Diese] Anleitung ist wirklich gut. Habe es auf meinem RasPi auch so gemacht.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Windows====&lt;br /&gt;
Folgende Programme runterladen und in die vorgeschlagenen (!) Ordner installieren&lt;br /&gt;
*[http://sourceforge.net/projects/opencvlibrary/files/opencv-win/2.4.11/opencv-2.4.11.exe/download OpenCV]&lt;br /&gt;
*[http://python.org/ftp/python/2.7.5/python-2.7.5.msi Python]&lt;br /&gt;
*[https://downloads.sourceforge.net/project/numpy/NumPy/1.8.0/numpy-1.8.0-win32-superpack-python2.7.exe NumPy]&lt;br /&gt;
*[https://downloads.sourceforge.net/project/matplotlib/matplotlib/matplotlib-1.3.0/matplotlib-1.3.0.win32-py2.7.exe Matplotlib] (hierfür nicht nötig)&lt;br /&gt;
&lt;br /&gt;
===Kalibrierung des Sensors===&lt;br /&gt;
Das Programm kennt zwei verschiedene Betriebsmodi:&lt;br /&gt;
&lt;br /&gt;
====RGB / BGR====&lt;br /&gt;
RGB (dafür in der json den Wert &amp;quot;hsv&amp;quot; auf false setzen)&lt;br /&gt;
RGB eignet sich gut, um Grafiken zu untersuchen. Siehe das DWD Beispiel. Bitte als B G R die Werte eingeben (nicht RGB).&lt;br /&gt;
&lt;br /&gt;
Wenn es jeweils nur eine Farbe ist, die gesucht werden soll, so ist der upper/lower Wert natürlich identisch.&lt;br /&gt;
&lt;br /&gt;
Die Werte kann man schlicht mit Gimp auslesen (Pipette, auf die gewünschte Farbe klicken, im Werkzeugfenster auf die Farbe klicken, dann stehen die Werte da...)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====HSV====&lt;br /&gt;
Das ist etwas tricky.&lt;br /&gt;
&lt;br /&gt;
Obacht: didaktische Reduktion!&lt;br /&gt;
&lt;br /&gt;
Prinzipiell kann man sich HSV zunächst mal als einen Farbkreis vorstellen. Damit bekommt jede Farbe einen Winkel. Der Witz an der Sache ist, dass die Helligkeit hier keine Rolle spielt. Die versteckt sich nämlich nicht auf unserem Farbkreis! Diese wird durch die Tiefe repräsentiert. Dazu legen wir jetzt unseren Farbkreis auf eine Papprolle (und knippsen oben ein imaginäres Licht an).&lt;br /&gt;
&lt;br /&gt;
Wenn wir uns jetzt die Farbe &amp;quot;Rot&amp;quot; vorstellen, dann gibt es davon ziemlich viele verschiedene. Von sehr hell, bis sehr dunkel. Der Winkel für helles und der für dunkles Rot ist im HSV Farbkreis der gleiche. Das macht diesen Farbraum für die Auswertung von Fotos sehr praktisch. Man kann schön mit zwei Werten quasi alle Rot-Töne abdecken.&lt;br /&gt;
&lt;br /&gt;
Der Haken:&lt;br /&gt;
&lt;br /&gt;
OpenCV sieht leider HSV anders, als GIMP. Daher ist es nicht ganz trivial, die passenden Werte für die Farben rauszufinden.&lt;br /&gt;
&lt;br /&gt;
Gebe im Forum dazu gerne Hilfestellung.&lt;br /&gt;
&lt;br /&gt;
==Programmcode==&lt;br /&gt;
Der Programmcode ist im ersten Forumsthread mit einigen Beispielen zum Download.&lt;br /&gt;
[http://forum.fhem.de/index.php/topic,39678.msg318865.html#msg318865 Download]&lt;br /&gt;
&lt;br /&gt;
===Sensor===&lt;br /&gt;
Anmerkung:&lt;br /&gt;
&lt;br /&gt;
Ich bin kein Programmierer. Wenn das jemand durchliest der Ahnung hat, sich totlacht =&amp;gt; ich übernehme keine Verantwortung&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# Optical Sensor&lt;br /&gt;
# using Python 2.7 and OpenCV 2.4.11&lt;br /&gt;
# do not use german umlauts, not even in description&lt;br /&gt;
# ver 0.2 first public release&lt;br /&gt;
import cv2&lt;br /&gt;
import argparse&lt;br /&gt;
import json&lt;br /&gt;
import urllib&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
#cv2 importiert OpenCV&lt;br /&gt;
#argparse wird benoetigt fuer die Parameteruebergabe&lt;br /&gt;
#json zum lesen des Config-Files&lt;br /&gt;
#urllib um uns mit fhem zu unterhalten&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# construct the argument parse and parse the arguments&lt;br /&gt;
ap = argparse.ArgumentParser()&lt;br /&gt;
ap.add_argument(&amp;quot;-c&amp;quot;, &amp;quot;--conf&amp;quot;, required=True,&lt;br /&gt;
	help=&amp;quot;path to the JSON configuration file; eg try: &amp;gt;sensor.py --conf dishwasher.json&amp;quot;)&lt;br /&gt;
args = vars(ap.parse_args())&lt;br /&gt;
&lt;br /&gt;
#ConfigFile laden&lt;br /&gt;
conf = json.load(open(args[&amp;quot;conf&amp;quot;]))&lt;br /&gt;
client = None&lt;br /&gt;
&lt;br /&gt;
#Gespeichertes Bild mit Pfad in Variable&lt;br /&gt;
path = (conf[&amp;quot;path_to_picture&amp;quot;])&lt;br /&gt;
picture = (conf[&amp;quot;picture&amp;quot;])&lt;br /&gt;
type = (conf[&amp;quot;type&amp;quot;])&lt;br /&gt;
first_picture = path + &amp;quot;/&amp;quot; + picture + &amp;quot;.&amp;quot; + type&lt;br /&gt;
&lt;br /&gt;
#Namen der Maske auslesen&lt;br /&gt;
first_mask = (conf[&amp;quot;mask&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
#Laden des Bildes&lt;br /&gt;
image = cv2.imread(first_picture)&lt;br /&gt;
&lt;br /&gt;
# Bild anzeigen&lt;br /&gt;
#cv2.imshow(&amp;quot;Originalbild&amp;quot;, image)&lt;br /&gt;
&lt;br /&gt;
# Schleife erzeugen&lt;br /&gt;
ROI = int(conf[&amp;quot;different_ROI&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
print &amp;quot;Soll-Durchlaeufe &amp;quot; + str(ROI)&lt;br /&gt;
&lt;br /&gt;
i = 0&lt;br /&gt;
while i &amp;lt; ROI:&lt;br /&gt;
	i = i + 1&lt;br /&gt;
	&lt;br /&gt;
	# Maskenpfad und Dateinamen generieren&lt;br /&gt;
	mask = path + &amp;quot;/&amp;quot; + first_mask + &amp;quot;_mask_&amp;quot; + str(i) + &amp;quot;.&amp;quot; + type&lt;br /&gt;
	&lt;br /&gt;
	# Maske laden&lt;br /&gt;
	mask = cv2.imread(mask,0)&lt;br /&gt;
	&lt;br /&gt;
	# Maske anwenden&lt;br /&gt;
	masked = cv2.bitwise_and(image, image, mask = mask)&lt;br /&gt;
	#cv2.imshow(&amp;quot;Maske&amp;quot;, masked)&lt;br /&gt;
	&lt;br /&gt;
	# BGR in HSV konvertieren wenn gewollt&lt;br /&gt;
	if conf[&amp;quot;hsv&amp;quot;]: &lt;br /&gt;
		masked = cv2.cvtColor(masked, cv2.COLOR_BGR2HSV)&lt;br /&gt;
		#cv2.imshow(&amp;quot;HSV&amp;quot;, masked)&lt;br /&gt;
	&lt;br /&gt;
	# Grenzwerte aus Config auslesen&lt;br /&gt;
	lower_col_value = tuple(conf[&amp;quot;lower_col&amp;quot; + &amp;quot;_&amp;quot; + str(i)])&lt;br /&gt;
	upper_col_value = tuple(conf[&amp;quot;upper_col&amp;quot; + &amp;quot;_&amp;quot; + str(i)])&lt;br /&gt;
	#print lower_col&lt;br /&gt;
	#print upper_col&lt;br /&gt;
	&lt;br /&gt;
	# Range definieren&lt;br /&gt;
	lower_col = np.array([(lower_col_value)], dtype=np.uint8)&lt;br /&gt;
	upper_col = np.array([(upper_col_value)], dtype=np.uint8)&lt;br /&gt;
&lt;br /&gt;
	# Threshold the image to get only selected colors&lt;br /&gt;
	mask = cv2.inRange(masked, lower_col, upper_col)&lt;br /&gt;
	#cv2.imshow(&amp;quot;Maske&amp;quot;, mask)&lt;br /&gt;
&lt;br /&gt;
	# Pixel zaehlen&lt;br /&gt;
	white = cv2.countNonZero(mask)&lt;br /&gt;
	print(&#039;The number of positive pixels is: &#039; + str(white))&lt;br /&gt;
	&lt;br /&gt;
	# Pixelanzahl an fhem senden&lt;br /&gt;
	# fhem Kommando erzeugen&lt;br /&gt;
	url = (conf[&amp;quot;fhem_host_port&amp;quot;])&lt;br /&gt;
	request = (conf[&amp;quot;fhem_request&amp;quot;])&lt;br /&gt;
	command = (conf[&amp;quot;fhem_command&amp;quot; + &amp;quot;_&amp;quot; + str(i)])&lt;br /&gt;
	value =  &amp;quot;%20&amp;quot; + str(white)&lt;br /&gt;
	fhem = url + request + command + value&lt;br /&gt;
	#print fhem&lt;br /&gt;
	urllib.urlopen(fhem)&lt;br /&gt;
	&lt;br /&gt;
	#cv2.waitKey(0)&lt;br /&gt;
	&lt;br /&gt;
print &amp;quot;Fertig&amp;quot;	&lt;br /&gt;
#cv2.waitKey(0)&lt;br /&gt;
cv2.destroyAllWindows()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config-File===&lt;br /&gt;
So kann ein Config File aussehen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
5seenland.json (könnte ein guter Dateinname sein...)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;config_version&amp;quot;: &amp;quot;0.2&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_host_port&amp;quot;: &amp;quot;http://192.168.5.31:8083&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_request&amp;quot;: &amp;quot;/fhem?cmd=&amp;quot;,&lt;br /&gt;
	&amp;quot;different_ROI&amp;quot;: &amp;quot;8&amp;quot;,&lt;br /&gt;
	&amp;quot;path_to_picture&amp;quot;: &amp;quot;./Picture&amp;quot;,&lt;br /&gt;
	&amp;quot;picture&amp;quot;: &amp;quot;bodenfeuchte&amp;quot;,&lt;br /&gt;
	&amp;quot;type&amp;quot;: &amp;quot;png&amp;quot;,&lt;br /&gt;
	&amp;quot;mask&amp;quot;: &amp;quot;5seenland&amp;quot;,&lt;br /&gt;
	&amp;quot;hsv&amp;quot;: false,&lt;br /&gt;
	&amp;quot;lower_col_1&amp;quot;: [45,100,200],&lt;br /&gt;
	&amp;quot;upper_col_1&amp;quot;: [45,100,200],&lt;br /&gt;
	&amp;quot;lower_col_2&amp;quot;: [60,200,250],&lt;br /&gt;
	&amp;quot;upper_col_2&amp;quot;: [60,200,250],&lt;br /&gt;
	&amp;quot;lower_col_3&amp;quot;: [75,250,250],&lt;br /&gt;
	&amp;quot;upper_col_3&amp;quot;: [75,250,250],&lt;br /&gt;
	&amp;quot;lower_col_4&amp;quot;: [75,250,200],&lt;br /&gt;
	&amp;quot;upper_col_4&amp;quot;: [75,250,200],&lt;br /&gt;
	&amp;quot;lower_col_5&amp;quot;: [75,220,150],&lt;br /&gt;
	&amp;quot;upper_col_5&amp;quot;: [75,220,150],&lt;br /&gt;
	&amp;quot;lower_col_6&amp;quot;: [75,150,75],&lt;br /&gt;
	&amp;quot;upper_col_6&amp;quot;: [75,150,75],&lt;br /&gt;
	&amp;quot;lower_col_7&amp;quot;: [250,200,50],&lt;br /&gt;
	&amp;quot;upper_col_7&amp;quot;: [250,200,50],&lt;br /&gt;
	&amp;quot;lower_col_8&amp;quot;: [250,0,0],&lt;br /&gt;
	&amp;quot;upper_col_8&amp;quot;: [250,0,0],&lt;br /&gt;
	&amp;quot;fhem_command_1&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%200-10&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_2&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2010-30&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_3&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2030-50&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_4&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2050-80&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_5&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2080-95&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_6&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2095-100&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_7&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%20100-105&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_8&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%20105-&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Eigentlich ganz einfach. Für jede ROI benötigt man lower_col_?, upper_col_? und fhem_command_?&lt;br /&gt;
&lt;br /&gt;
Die  lower/upper cols definieren für jede ROI den zu suchenden Farbbereich... das Ergebnis wird dann an den fhem_command_? angehängt.&lt;br /&gt;
&lt;br /&gt;
Hat man nur 2 ROI, kann man die Werte 3-8 natürlich rauswerfen; andernfalls werden sie schlicht ignoriert, tun also nicht weh. Sind nur eben sinnbefreit.&lt;br /&gt;
&lt;br /&gt;
===Beispiel mit Bildern===&lt;br /&gt;
Ist denke ich im Forumsthread schon ganz schön beschrieben.&lt;br /&gt;
&lt;br /&gt;
Wer eigene Beispiele hat, immer her damit :)&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Optischer_Sensor,_Software&amp;diff=11890</id>
		<title>Optischer Sensor, Software</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Optischer_Sensor,_Software&amp;diff=11890"/>
		<updated>2015-08-04T14:01:31Z</updated>

		<summary type="html">&lt;p&gt;Rince: /* Benötigte Frameworks */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- hier nicht erforderlich; verwirrt derzeit nur {{SEITENTITEL:Optischer Sensor, Software}} --&amp;gt;&lt;br /&gt;
&amp;lt;!-- stattdessen: evtl gleich {{Infobox Modul}} einbauen und füllen (und vielleicht auch an der darin vorgeschlagenen Gliederung orientieren) --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todo|Das wird die Doku für den optischen Sensor. Der Programmcode ist ziemlich weit gediehen. Ich dachte mir, die Doku mal zum Start eines Projekts fertig zu haben, ist auch nicht schlecht}}&lt;br /&gt;
&amp;lt;!-- Hier wäre eine &amp;quot;Unterschrift&amp;quot; nicht schlecht, auch wenn in Artikeln/Seiten eigentlich unüblich. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Was ich noch nicht weiß==&lt;br /&gt;
* soll das Programm regelmäßig per Cron ausgeführt werden, oder ist es schlauer einen WebSocket zu öffnen, so dass fhem dem Programm sagen kann, wenn es ein Bild bearbeiten soll&lt;br /&gt;
* &amp;lt;s&amp;gt;Treshold für Farben im Programm anwenden,&amp;lt;/s&amp;gt; oder nackten Zähler direkt an fhem senden&lt;br /&gt;
** besser, eine Weiterverarbeitung der Werte in fhem&lt;br /&gt;
** fhem ist diesbezüglich viel mächtiger&lt;br /&gt;
&lt;br /&gt;
==Übersicht==&lt;br /&gt;
Das kleine Programm liest ein Farbbild ein. Anschließend werden (in definierbaren Bereichen) Farbwerte ermittelt. Das Resultat wird dann an fhem gesendet.&lt;br /&gt;
&lt;br /&gt;
Wozu ist das gut?&lt;br /&gt;
&lt;br /&gt;
Mein Anwendungsfall:&lt;br /&gt;
&lt;br /&gt;
Eine USB Kamera am Raspberry macht regelmäßig Bilder meiner Küche. Darin sind insbesondere die Geschirrspülmaschine und der Herd zu sehen. Wenn meine Geschirrspülmaschine Dinge wie Salz oder Klarspüler benötigt, leuchtet eine entsprechende LED rot auf. Das kann das Programm erkennen und fhem mitteilen. &lt;br /&gt;
Ähnlich beim Herd: ist der an, leuchtet es gelb. Beim Verlassen des Hauses kann mir fhem sagen, dass der Herd noch an ist...&lt;br /&gt;
&lt;br /&gt;
Wichtig:&lt;br /&gt;
Die Kamera darf nicht bewegt werden, sonst funktionieren die Masken nicht mehr! Also z.B. festschrauben...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anderer Anwendungsfall:&lt;br /&gt;
&lt;br /&gt;
Ein Bild (z.B. Bodenfeuchte) vom DWD runterladen (das müsst ihr selbst!), dann analysieren lassen, welche Bodenfeuchte bei euch ist. Selbiges wird an fhem gesendet.&lt;br /&gt;
&lt;br /&gt;
Einfach für jede mögliche Farbe eine eigene Maske erstellen (die ist natürlich identisch), in die conf die Farbwerte und die setreadings schreiben, fertig...&lt;br /&gt;
&lt;br /&gt;
{{Link2Forum|Topic=39678|LinkText=Forumsthread}}&lt;br /&gt;
&lt;br /&gt;
==Beschreibung==&lt;br /&gt;
Ein bisschen mehr ins Detail gehend:&lt;br /&gt;
&lt;br /&gt;
Das Programm erwartet ein farbiges Bitmap Bild. Anschließend werden Masken über das Bild gelegt. Was übrig bleibt (idealerweise also der Bildausschnitt wo die entsprechende LED zu sehen ist) wird in den HSV Farbraum konvertiert. Eine Beschreibung warum und wie er funktioniert, folgt noch. Dann werden Die gewünschten Farben gefiltert. Intern übrig bleiben dann einige weiße Pixel auf schwarzem Grund. Die werden schlicht gezählt. Der Wert wird an fhem gesendet.&lt;br /&gt;
&lt;br /&gt;
===Konfiguration der Software===&lt;br /&gt;
Das Programm an sich benötigt eine Config-Datei.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;fhem_host_port&amp;quot;: &amp;quot;http://192.168.5.31:8083&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_request&amp;quot;: &amp;quot;/fhem?cmd=&amp;quot;,&lt;br /&gt;
	&amp;quot;different_ROI&amp;quot;: &amp;quot;5&amp;quot;,&lt;br /&gt;
	&amp;quot;path_to_picture&amp;quot;: &amp;quot;./Picture&amp;quot;,&lt;br /&gt;
	&amp;quot;picture&amp;quot;: &amp;quot;picture_kitchen&amp;quot;,&lt;br /&gt;
	&amp;quot;type&amp;quot;: &amp;quot;jpg&amp;quot;,&lt;br /&gt;
	&amp;quot;mask&amp;quot;: &amp;quot;dishwasher&amp;quot;,&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Was ist hier einzustellen?&lt;br /&gt;
* &amp;quot;fhem_host_port&amp;quot;: Adresse des fhem Servers, ebenso wie der Port. (Muss man also anpassen)&lt;br /&gt;
* &amp;quot;fhem_request&amp;quot;: (weiß nicht, wie es heißt), sollte aber so passen&lt;br /&gt;
* &amp;quot;different_ROI&amp;quot;: ist spannend: hier sagt man, wie viele LEDs (ROI = region of interesst) man überwachen will. (für jede ROI muss genau 1 Maske existieren)&lt;br /&gt;
* &amp;quot;path_to_picture&amp;quot;: logisch, wo liegt das Bild? In diesem Fall in einem Unterordner Namens Picture&lt;br /&gt;
* &amp;quot;picture&amp;quot;: der Name des Bildes (aufgemerkt: das Programm geht also immer vom gleichen Dateinamen aus!) (Quellbild)&lt;br /&gt;
* &amp;quot;type&amp;quot;: bitte mit angeben; jpg, png...&lt;br /&gt;
* &amp;quot;mask&amp;quot;: der erste Teil des Maskennamens&lt;br /&gt;
** die Dateiendung nicht angeben, bitte die gleiche wie beim Quellbild verwenden&lt;br /&gt;
** so kann man bei einem Quellbild verschiedene Masken angeben (in verschiedenen Config Dateien)&lt;br /&gt;
** bei Karten vom DWD z.B. kann man so aus einem Quellbild Werte für verschiedene Regionen ermitteln&lt;br /&gt;
** munic.conf, berlin.conf&lt;br /&gt;
** bei mehr Küchengeräten z.B. dishwasher.conf und waterboiler.conf&lt;br /&gt;
&lt;br /&gt;
===Was sind diese Masken?===&lt;br /&gt;
Die sind cool. Einfache schwarz/weiß Bilder.&lt;br /&gt;
&lt;br /&gt;
Zum erstellen:&lt;br /&gt;
Ein Musterbild von der Kamera besorgen. In Gimp öffnen, den Bereich um eine der gewünschten LEDs ein Viereck oder ein Kreis, ist egal) markieren. Löschen, Füllfarbe weiß. Markierung umdrehen, löschen, Füllfarbe schwarz. Fertig.&lt;br /&gt;
&lt;br /&gt;
Stellt euch vor, die Maske wäre aus Tonpapier. Da wo weiß ist, ist ein Loch drin. Die Maske wird über das Bild gelegt. Nun seht ihr nur noch die gewünschte LED...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wichtig:&lt;br /&gt;
&lt;br /&gt;
Die Maske braucht nun einen festen Dateinamen, damit sie gefunden werden kann! Hängt an den in der Config angegebenen Dateinamen ein _mask_1 an, für eure erste Maske. Hättet ihr ROI = 1, ist das alles. Bei ROI = 2 wollen wir 2 Masken abarbeiten.&lt;br /&gt;
&lt;br /&gt;
Also, bei ROI = 3&lt;br /&gt;
* quellbild.jpg (das, was eure Kamera immer generiert, oder euch der DWD zur Verfügung stellt)&lt;br /&gt;
* &amp;lt;AngegebenerName&amp;gt;_mask_1.jpg (die Dateiendung bitte wie beim Quellbild)&lt;br /&gt;
* &amp;lt;AngegebenerName&amp;gt;_mask_2.jpg&lt;br /&gt;
* &amp;lt;AngegebenerName&amp;gt;_mask_3.jpg&lt;br /&gt;
&lt;br /&gt;
===Benötigte Frameworks===&lt;br /&gt;
folgt noch&lt;br /&gt;
&lt;br /&gt;
====Linux====&lt;br /&gt;
[http://www.pyimagesearch.com/2015/02/23/install-opencv-and-python-on-your-raspberry-pi-2-and-b/ Diese] Anleitung ist wirklich gut. Habe es auf meinem RasPi auch so gemacht.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Windows====&lt;br /&gt;
Folgende Programme runterladen und in die vorgeschlagenen (!) Ordner installieren&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*[http://sourceforge.net/projects/opencvlibrary/files/opencv-win/2.4.11/opencv-2.4.11.exe/download OpenCV]&lt;br /&gt;
*[http://python.org/ftp/python/2.7.5/python-2.7.5.msi Pythomn]&lt;br /&gt;
*[https://downloads.sourceforge.net/project/numpy/NumPy/1.8.0/numpy-1.8.0-win32-superpack-python2.7.exe NumPy]&lt;br /&gt;
*[https://downloads.sourceforge.net/project/matplotlib/matplotlib/matplotlib-1.3.0/matplotlib-1.3.0.win32-py2.7.exe Matplotlib] (hierfür nicht nötig)&lt;br /&gt;
&lt;br /&gt;
===Kalibrierung des Sensors===&lt;br /&gt;
Das Programm kennt zwei verschiedene Betriebsmodi:&lt;br /&gt;
&lt;br /&gt;
====RGB / BGR====&lt;br /&gt;
RGB (dafür in der json den Wert &amp;quot;hsv&amp;quot; auf false setzen)&lt;br /&gt;
RGB eignet sich gut, um Grafiken zu untersuchen. Siehe das DWD Beispiel. Bitte als B G R die Werte eingeben (nicht RGB).&lt;br /&gt;
&lt;br /&gt;
Wenn es jeweils nur eine Farbe ist, die gesucht werden soll, so ist der upper/lower Wert natürlich identisch.&lt;br /&gt;
&lt;br /&gt;
Die Werte kann man schlicht mit Gimp auslesen (Pipette, auf die gewünschte Farbe klicken, im Werkzeugfenster auf die Farbe klicken, dann stehen die Werte da...)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====HSV====&lt;br /&gt;
Das ist etwas tricky.&lt;br /&gt;
&lt;br /&gt;
Obacht: didaktische Reduktion!&lt;br /&gt;
&lt;br /&gt;
Prinzipiell kann man sich HSV zunächst mal als einen Farbkreis vorstellen. Damit bekommt jede Farbe einen Winkel. Der Witz an der Sache ist, dass die Helligkeit hier keine Rolle spielt. Die versteckt sich nämlich nicht auf unserem Farbkreis! Diese wird durch die Tiefe repräsentiert. Dazu legen wir jetzt unseren Farbkreis auf eine Papprolle (und knippsen oben ein imaginäres Licht an).&lt;br /&gt;
&lt;br /&gt;
Wenn wir uns jetzt die Farbe &amp;quot;Rot&amp;quot; vorstellen, dann gibt es davon ziemlich viele verschiedene. Von sehr hell, bis sehr dunkel. Der Winkel für helles und der für dunkles Rot ist im HSV Farbkreis der gleiche. Das macht diesen Farbraum für die Auswertung von Fotos sehr praktisch. Man kann schön mit zwei Werten quasi alle Rot-Töne abdecken.&lt;br /&gt;
&lt;br /&gt;
Der Haken:&lt;br /&gt;
&lt;br /&gt;
OpenCV sieht leider HSV anders, als GIMP. Daher ist es nicht ganz trivial, die passenden Werte für die Farben rauszufinden.&lt;br /&gt;
&lt;br /&gt;
Gebe im Forum dazu gerne Hilfestellung.&lt;br /&gt;
&lt;br /&gt;
==Programmcode==&lt;br /&gt;
Der Programmcode ist im ersten Forumsthread mit einigen Beispielen zum Download.&lt;br /&gt;
[http://forum.fhem.de/index.php/topic,39678.msg318865.html#msg318865 Download]&lt;br /&gt;
&lt;br /&gt;
===Sensor===&lt;br /&gt;
Anmerkung:&lt;br /&gt;
&lt;br /&gt;
Ich bin kein Programmierer. Wenn das jemand durchliest der Ahnung hat, sich totlacht =&amp;gt; ich übernehme keine Verantwortung&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# Optical Sensor&lt;br /&gt;
# using Python 2.7 and OpenCV 2.4.11&lt;br /&gt;
# do not use german umlauts, not even in description&lt;br /&gt;
# ver 0.2 first public release&lt;br /&gt;
import cv2&lt;br /&gt;
import argparse&lt;br /&gt;
import json&lt;br /&gt;
import urllib&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
#cv2 importiert OpenCV&lt;br /&gt;
#argparse wird benoetigt fuer die Parameteruebergabe&lt;br /&gt;
#json zum lesen des Config-Files&lt;br /&gt;
#urllib um uns mit fhem zu unterhalten&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# construct the argument parse and parse the arguments&lt;br /&gt;
ap = argparse.ArgumentParser()&lt;br /&gt;
ap.add_argument(&amp;quot;-c&amp;quot;, &amp;quot;--conf&amp;quot;, required=True,&lt;br /&gt;
	help=&amp;quot;path to the JSON configuration file; eg try: &amp;gt;sensor.py --conf dishwasher.json&amp;quot;)&lt;br /&gt;
args = vars(ap.parse_args())&lt;br /&gt;
&lt;br /&gt;
#ConfigFile laden&lt;br /&gt;
conf = json.load(open(args[&amp;quot;conf&amp;quot;]))&lt;br /&gt;
client = None&lt;br /&gt;
&lt;br /&gt;
#Gespeichertes Bild mit Pfad in Variable&lt;br /&gt;
path = (conf[&amp;quot;path_to_picture&amp;quot;])&lt;br /&gt;
picture = (conf[&amp;quot;picture&amp;quot;])&lt;br /&gt;
type = (conf[&amp;quot;type&amp;quot;])&lt;br /&gt;
first_picture = path + &amp;quot;/&amp;quot; + picture + &amp;quot;.&amp;quot; + type&lt;br /&gt;
&lt;br /&gt;
#Namen der Maske auslesen&lt;br /&gt;
first_mask = (conf[&amp;quot;mask&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
#Laden des Bildes&lt;br /&gt;
image = cv2.imread(first_picture)&lt;br /&gt;
&lt;br /&gt;
# Bild anzeigen&lt;br /&gt;
#cv2.imshow(&amp;quot;Originalbild&amp;quot;, image)&lt;br /&gt;
&lt;br /&gt;
# Schleife erzeugen&lt;br /&gt;
ROI = int(conf[&amp;quot;different_ROI&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
print &amp;quot;Soll-Durchlaeufe &amp;quot; + str(ROI)&lt;br /&gt;
&lt;br /&gt;
i = 0&lt;br /&gt;
while i &amp;lt; ROI:&lt;br /&gt;
	i = i + 1&lt;br /&gt;
	&lt;br /&gt;
	# Maskenpfad und Dateinamen generieren&lt;br /&gt;
	mask = path + &amp;quot;/&amp;quot; + first_mask + &amp;quot;_mask_&amp;quot; + str(i) + &amp;quot;.&amp;quot; + type&lt;br /&gt;
	&lt;br /&gt;
	# Maske laden&lt;br /&gt;
	mask = cv2.imread(mask,0)&lt;br /&gt;
	&lt;br /&gt;
	# Maske anwenden&lt;br /&gt;
	masked = cv2.bitwise_and(image, image, mask = mask)&lt;br /&gt;
	#cv2.imshow(&amp;quot;Maske&amp;quot;, masked)&lt;br /&gt;
	&lt;br /&gt;
	# BGR in HSV konvertieren wenn gewollt&lt;br /&gt;
	if conf[&amp;quot;hsv&amp;quot;]: &lt;br /&gt;
		masked = cv2.cvtColor(masked, cv2.COLOR_BGR2HSV)&lt;br /&gt;
		#cv2.imshow(&amp;quot;HSV&amp;quot;, masked)&lt;br /&gt;
	&lt;br /&gt;
	# Grenzwerte aus Config auslesen&lt;br /&gt;
	lower_col_value = tuple(conf[&amp;quot;lower_col&amp;quot; + &amp;quot;_&amp;quot; + str(i)])&lt;br /&gt;
	upper_col_value = tuple(conf[&amp;quot;upper_col&amp;quot; + &amp;quot;_&amp;quot; + str(i)])&lt;br /&gt;
	#print lower_col&lt;br /&gt;
	#print upper_col&lt;br /&gt;
	&lt;br /&gt;
	# Range definieren&lt;br /&gt;
	lower_col = np.array([(lower_col_value)], dtype=np.uint8)&lt;br /&gt;
	upper_col = np.array([(upper_col_value)], dtype=np.uint8)&lt;br /&gt;
&lt;br /&gt;
	# Threshold the image to get only selected colors&lt;br /&gt;
	mask = cv2.inRange(masked, lower_col, upper_col)&lt;br /&gt;
	#cv2.imshow(&amp;quot;Maske&amp;quot;, mask)&lt;br /&gt;
&lt;br /&gt;
	# Pixel zaehlen&lt;br /&gt;
	white = cv2.countNonZero(mask)&lt;br /&gt;
	print(&#039;The number of positive pixels is: &#039; + str(white))&lt;br /&gt;
	&lt;br /&gt;
	# Pixelanzahl an fhem senden&lt;br /&gt;
	# fhem Kommando erzeugen&lt;br /&gt;
	url = (conf[&amp;quot;fhem_host_port&amp;quot;])&lt;br /&gt;
	request = (conf[&amp;quot;fhem_request&amp;quot;])&lt;br /&gt;
	command = (conf[&amp;quot;fhem_command&amp;quot; + &amp;quot;_&amp;quot; + str(i)])&lt;br /&gt;
	value =  &amp;quot;%20&amp;quot; + str(white)&lt;br /&gt;
	fhem = url + request + command + value&lt;br /&gt;
	#print fhem&lt;br /&gt;
	urllib.urlopen(fhem)&lt;br /&gt;
	&lt;br /&gt;
	#cv2.waitKey(0)&lt;br /&gt;
	&lt;br /&gt;
print &amp;quot;Fertig&amp;quot;	&lt;br /&gt;
#cv2.waitKey(0)&lt;br /&gt;
cv2.destroyAllWindows()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config-File===&lt;br /&gt;
So kann ein Config File aussehen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
5seenland.json (könnte ein guter Dateinname sein...)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;config_version&amp;quot;: &amp;quot;0.2&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_host_port&amp;quot;: &amp;quot;http://192.168.5.31:8083&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_request&amp;quot;: &amp;quot;/fhem?cmd=&amp;quot;,&lt;br /&gt;
	&amp;quot;different_ROI&amp;quot;: &amp;quot;8&amp;quot;,&lt;br /&gt;
	&amp;quot;path_to_picture&amp;quot;: &amp;quot;./Picture&amp;quot;,&lt;br /&gt;
	&amp;quot;picture&amp;quot;: &amp;quot;bodenfeuchte&amp;quot;,&lt;br /&gt;
	&amp;quot;type&amp;quot;: &amp;quot;png&amp;quot;,&lt;br /&gt;
	&amp;quot;mask&amp;quot;: &amp;quot;5seenland&amp;quot;,&lt;br /&gt;
	&amp;quot;hsv&amp;quot;: false,&lt;br /&gt;
	&amp;quot;lower_col_1&amp;quot;: [45,100,200],&lt;br /&gt;
	&amp;quot;upper_col_1&amp;quot;: [45,100,200],&lt;br /&gt;
	&amp;quot;lower_col_2&amp;quot;: [60,200,250],&lt;br /&gt;
	&amp;quot;upper_col_2&amp;quot;: [60,200,250],&lt;br /&gt;
	&amp;quot;lower_col_3&amp;quot;: [75,250,250],&lt;br /&gt;
	&amp;quot;upper_col_3&amp;quot;: [75,250,250],&lt;br /&gt;
	&amp;quot;lower_col_4&amp;quot;: [75,250,200],&lt;br /&gt;
	&amp;quot;upper_col_4&amp;quot;: [75,250,200],&lt;br /&gt;
	&amp;quot;lower_col_5&amp;quot;: [75,220,150],&lt;br /&gt;
	&amp;quot;upper_col_5&amp;quot;: [75,220,150],&lt;br /&gt;
	&amp;quot;lower_col_6&amp;quot;: [75,150,75],&lt;br /&gt;
	&amp;quot;upper_col_6&amp;quot;: [75,150,75],&lt;br /&gt;
	&amp;quot;lower_col_7&amp;quot;: [250,200,50],&lt;br /&gt;
	&amp;quot;upper_col_7&amp;quot;: [250,200,50],&lt;br /&gt;
	&amp;quot;lower_col_8&amp;quot;: [250,0,0],&lt;br /&gt;
	&amp;quot;upper_col_8&amp;quot;: [250,0,0],&lt;br /&gt;
	&amp;quot;fhem_command_1&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%200-10&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_2&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2010-30&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_3&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2030-50&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_4&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2050-80&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_5&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2080-95&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_6&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2095-100&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_7&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%20100-105&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_8&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%20105-&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Eigentlich ganz einfach. Für jede ROI benötigt man lower_col_?, upper_col_? und fhem_command_?&lt;br /&gt;
&lt;br /&gt;
Die  lower/upper cols definieren für jede ROI den zu suchenden Farbbereich... das Ergebnis wird dann an den fhem_command_? angehängt.&lt;br /&gt;
&lt;br /&gt;
Hat man nur 2 ROI, kann man die Werte 3-8 natürlich rauswerfen; andernfalls werden sie schlicht ignoriert, tun also nicht weh. Sind nur eben sinnbefreit.&lt;br /&gt;
&lt;br /&gt;
===Beispiel mit Bildern===&lt;br /&gt;
Ist denke ich im Forumsthread schon ganz schön beschrieben.&lt;br /&gt;
&lt;br /&gt;
Wer eigene Beispiele hat, immer her damit :)&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Optischer_Sensor,_Software&amp;diff=11887</id>
		<title>Optischer Sensor, Software</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Optischer_Sensor,_Software&amp;diff=11887"/>
		<updated>2015-08-04T12:44:52Z</updated>

		<summary type="html">&lt;p&gt;Rince: /* Config-File */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- hier nicht erforderlich; verwirrt derzeit nur {{SEITENTITEL:Optischer Sensor, Software}} --&amp;gt;&lt;br /&gt;
&amp;lt;!-- stattdessen: evtl gleich {{Infobox Modul}} einbauen und füllen (und vielleicht auch an der darin vorgeschlagenen Gliederung orientieren) --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todo|Das wird die Doku für den optischen Sensor. Der Programmcode ist ziemlich weit gediehen. Ich dachte mir, die Doku mal zum Start eines Projekts fertig zu haben, ist auch nicht schlecht}}&lt;br /&gt;
&amp;lt;!-- Hier wäre eine &amp;quot;Unterschrift&amp;quot; nicht schlecht, auch wenn in Artikeln/Seiten eigentlich unüblich. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Was ich noch nicht weiß==&lt;br /&gt;
* soll das Programm regelmäßig per Cron ausgeführt werden, oder ist es schlauer einen WebSocket zu öffnen, so dass fhem dem Programm sagen kann, wenn es ein Bild bearbeiten soll&lt;br /&gt;
* &amp;lt;s&amp;gt;Treshold für Farben im Programm anwenden,&amp;lt;/s&amp;gt; oder nackten Zähler direkt an fhem senden&lt;br /&gt;
** besser, eine Weiterverarbeitung der Werte in fhem&lt;br /&gt;
** fhem ist diesbezüglich viel mächtiger&lt;br /&gt;
&lt;br /&gt;
==Übersicht==&lt;br /&gt;
Das kleine Programm liest ein Farbbild ein. Anschließend werden (in definierbaren Bereichen) Farbwerte ermittelt. Das Resultat wird dann an fhem gesendet.&lt;br /&gt;
&lt;br /&gt;
Wozu ist das gut?&lt;br /&gt;
&lt;br /&gt;
Mein Anwendungsfall:&lt;br /&gt;
&lt;br /&gt;
Eine USB Kamera am Raspberry macht regelmäßig Bilder meiner Küche. Darin sind insbesondere die Geschirrspülmaschine und der Herd zu sehen. Wenn meine Geschirrspülmaschine Dinge wie Salz oder Klarspüler benötigt, leuchtet eine entsprechende LED rot auf. Das kann das Programm erkennen und fhem mitteilen. &lt;br /&gt;
Ähnlich beim Herd: ist der an, leuchtet es gelb. Beim Verlassen des Hauses kann mir fhem sagen, dass der Herd noch an ist...&lt;br /&gt;
&lt;br /&gt;
Wichtig:&lt;br /&gt;
Die Kamera darf nicht bewegt werden, sonst funktionieren die Masken nicht mehr! Also z.B. festschrauben...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anderer Anwendungsfall:&lt;br /&gt;
&lt;br /&gt;
Ein Bild (z.B. Bodenfeuchte) vom DWD runterladen (das müsst ihr selbst!), dann analysieren lassen, welche Bodenfeuchte bei euch ist. Selbiges wird an fhem gesendet.&lt;br /&gt;
&lt;br /&gt;
Einfach für jede mögliche Farbe eine eigene Maske erstellen (die ist natürlich identisch), in die conf die Farbwerte und die setreadings schreiben, fertig...&lt;br /&gt;
&lt;br /&gt;
{{Link2Forum|Topic=39678|LinkText=Forumsthread}}&lt;br /&gt;
&lt;br /&gt;
==Beschreibung==&lt;br /&gt;
Ein bisschen mehr ins Detail gehend:&lt;br /&gt;
&lt;br /&gt;
Das Programm erwartet ein farbiges Bitmap Bild. Anschließend werden Masken über das Bild gelegt. Was übrig bleibt (idealerweise also der Bildausschnitt wo die entsprechende LED zu sehen ist) wird in den HSV Farbraum konvertiert. Eine Beschreibung warum und wie er funktioniert, folgt noch. Dann werden Die gewünschten Farben gefiltert. Intern übrig bleiben dann einige weiße Pixel auf schwarzem Grund. Die werden schlicht gezählt. Der Wert wird an fhem gesendet.&lt;br /&gt;
&lt;br /&gt;
===Konfiguration der Software===&lt;br /&gt;
Das Programm an sich benötigt eine Config-Datei.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;fhem_host_port&amp;quot;: &amp;quot;http://192.168.5.31:8083&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_request&amp;quot;: &amp;quot;/fhem?cmd=&amp;quot;,&lt;br /&gt;
	&amp;quot;different_ROI&amp;quot;: &amp;quot;5&amp;quot;,&lt;br /&gt;
	&amp;quot;path_to_picture&amp;quot;: &amp;quot;./Picture&amp;quot;,&lt;br /&gt;
	&amp;quot;picture&amp;quot;: &amp;quot;picture_kitchen&amp;quot;,&lt;br /&gt;
	&amp;quot;type&amp;quot;: &amp;quot;jpg&amp;quot;,&lt;br /&gt;
	&amp;quot;mask&amp;quot;: &amp;quot;dishwasher&amp;quot;,&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Was ist hier einzustellen?&lt;br /&gt;
* &amp;quot;fhem_host_port&amp;quot;: Adresse des fhem Servers, ebenso wie der Port. (Muss man also anpassen)&lt;br /&gt;
* &amp;quot;fhem_request&amp;quot;: (weiß nicht, wie es heißt), sollte aber so passen&lt;br /&gt;
* &amp;quot;different_ROI&amp;quot;: ist spannend: hier sagt man, wie viele LEDs (ROI = region of interesst) man überwachen will. (für jede ROI muss genau 1 Maske existieren)&lt;br /&gt;
* &amp;quot;path_to_picture&amp;quot;: logisch, wo liegt das Bild? In diesem Fall in einem Unterordner Namens Picture&lt;br /&gt;
* &amp;quot;picture&amp;quot;: der Name des Bildes (aufgemerkt: das Programm geht also immer vom gleichen Dateinamen aus!) (Quellbild)&lt;br /&gt;
* &amp;quot;type&amp;quot;: bitte mit angeben; jpg, png...&lt;br /&gt;
* &amp;quot;mask&amp;quot;: der erste Teil des Maskennamens&lt;br /&gt;
** die Dateiendung nicht angeben, bitte die gleiche wie beim Quellbild verwenden&lt;br /&gt;
** so kann man bei einem Quellbild verschiedene Masken angeben (in verschiedenen Config Dateien)&lt;br /&gt;
** bei Karten vom DWD z.B. kann man so aus einem Quellbild Werte für verschiedene Regionen ermitteln&lt;br /&gt;
** munic.conf, berlin.conf&lt;br /&gt;
** bei mehr Küchengeräten z.B. dishwasher.conf und waterboiler.conf&lt;br /&gt;
&lt;br /&gt;
===Was sind diese Masken?===&lt;br /&gt;
Die sind cool. Einfache schwarz/weiß Bilder.&lt;br /&gt;
&lt;br /&gt;
Zum erstellen:&lt;br /&gt;
Ein Musterbild von der Kamera besorgen. In Gimp öffnen, den Bereich um eine der gewünschten LEDs ein Viereck oder ein Kreis, ist egal) markieren. Löschen, Füllfarbe weiß. Markierung umdrehen, löschen, Füllfarbe schwarz. Fertig.&lt;br /&gt;
&lt;br /&gt;
Stellt euch vor, die Maske wäre aus Tonpapier. Da wo weiß ist, ist ein Loch drin. Die Maske wird über das Bild gelegt. Nun seht ihr nur noch die gewünschte LED...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wichtig:&lt;br /&gt;
&lt;br /&gt;
Die Maske braucht nun einen festen Dateinamen, damit sie gefunden werden kann! Hängt an den in der Config angegebenen Dateinamen ein _mask_1 an, für eure erste Maske. Hättet ihr ROI = 1, ist das alles. Bei ROI = 2 wollen wir 2 Masken abarbeiten.&lt;br /&gt;
&lt;br /&gt;
Also, bei ROI = 3&lt;br /&gt;
* quellbild.jpg (das, was eure Kamera immer generiert, oder euch der DWD zur Verfügung stellt)&lt;br /&gt;
* &amp;lt;AngegebenerName&amp;gt;_mask_1.jpg (die Dateiendung bitte wie beim Quellbild)&lt;br /&gt;
* &amp;lt;AngegebenerName&amp;gt;_mask_2.jpg&lt;br /&gt;
* &amp;lt;AngegebenerName&amp;gt;_mask_3.jpg&lt;br /&gt;
&lt;br /&gt;
===Benötigte Frameworks===&lt;br /&gt;
folgt noch&lt;br /&gt;
&lt;br /&gt;
*Linux&lt;br /&gt;
*[http://www.pyimagesearch.com/2015/02/23/install-opencv-and-python-on-your-raspberry-pi-2-and-b/ Diese] Anleitung ist wirklich gut. Habe es auf meinem RasPi auch so gemacht.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Windows&lt;br /&gt;
*bei Bedarf gerne&lt;br /&gt;
&lt;br /&gt;
===Kalibrierung des Sensors===&lt;br /&gt;
Das Programm kennt zwei verschiedene Betriebsmodi:&lt;br /&gt;
&lt;br /&gt;
====RGB / BGR====&lt;br /&gt;
RGB (dafür in der json den Wert &amp;quot;hsv&amp;quot; auf false setzen)&lt;br /&gt;
RGB eignet sich gut, um Grafiken zu untersuchen. Siehe das DWD Beispiel. Bitte als B G R die Werte eingeben (nicht RGB).&lt;br /&gt;
&lt;br /&gt;
Wenn es jeweils nur eine Farbe ist, die gesucht werden soll, so ist der upper/lower Wert natürlich identisch.&lt;br /&gt;
&lt;br /&gt;
Die Werte kann man schlicht mit Gimp auslesen (Pipette, auf die gewünschte Farbe klicken, im Werkzeugfenster auf die Farbe klicken, dann stehen die Werte da...)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====HSV====&lt;br /&gt;
Das ist etwas tricky.&lt;br /&gt;
&lt;br /&gt;
Obacht: didaktische Reduktion!&lt;br /&gt;
&lt;br /&gt;
Prinzipiell kann man sich HSV zunächst mal als einen Farbkreis vorstellen. Damit bekommt jede Farbe einen Winkel. Der Witz an der Sache ist, dass die Helligkeit hier keine Rolle spielt. Die versteckt sich nämlich nicht auf unserem Farbkreis! Diese wird durch die Tiefe repräsentiert. Dazu legen wir jetzt unseren Farbkreis auf eine Papprolle (und knippsen oben ein imaginäres Licht an).&lt;br /&gt;
&lt;br /&gt;
Wenn wir uns jetzt die Farbe &amp;quot;Rot&amp;quot; vorstellen, dann gibt es davon ziemlich viele verschiedene. Von sehr hell, bis sehr dunkel. Der Winkel für helles und der für dunkles Rot ist im HSV Farbkreis der gleiche. Das macht diesen Farbraum für die Auswertung von Fotos sehr praktisch. Man kann schön mit zwei Werten quasi alle Rot-Töne abdecken.&lt;br /&gt;
&lt;br /&gt;
Der Haken:&lt;br /&gt;
&lt;br /&gt;
OpenCV sieht leider HSV anders, als GIMP. Daher ist es nicht ganz trivial, die passenden Werte für die Farben rauszufinden.&lt;br /&gt;
&lt;br /&gt;
Gebe im Forum dazu gerne Hilfestellung.&lt;br /&gt;
&lt;br /&gt;
==Programmcode==&lt;br /&gt;
Der Programmcode ist im ersten Forumsthread mit einigen Beispielen zum Download.&lt;br /&gt;
[http://forum.fhem.de/index.php/topic,39678.msg318865.html#msg318865 Download]&lt;br /&gt;
&lt;br /&gt;
===Sensor===&lt;br /&gt;
Anmerkung:&lt;br /&gt;
&lt;br /&gt;
Ich bin kein Programmierer. Wenn das jemand durchliest der Ahnung hat, sich totlacht =&amp;gt; ich übernehme keine Verantwortung&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# Optical Sensor&lt;br /&gt;
# using Python 2.7 and OpenCV 2.4.11&lt;br /&gt;
# do not use german umlauts, not even in description&lt;br /&gt;
# ver 0.2 first public release&lt;br /&gt;
import cv2&lt;br /&gt;
import argparse&lt;br /&gt;
import json&lt;br /&gt;
import urllib&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
#cv2 importiert OpenCV&lt;br /&gt;
#argparse wird benoetigt fuer die Parameteruebergabe&lt;br /&gt;
#json zum lesen des Config-Files&lt;br /&gt;
#urllib um uns mit fhem zu unterhalten&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# construct the argument parse and parse the arguments&lt;br /&gt;
ap = argparse.ArgumentParser()&lt;br /&gt;
ap.add_argument(&amp;quot;-c&amp;quot;, &amp;quot;--conf&amp;quot;, required=True,&lt;br /&gt;
	help=&amp;quot;path to the JSON configuration file; eg try: &amp;gt;sensor.py --conf dishwasher.json&amp;quot;)&lt;br /&gt;
args = vars(ap.parse_args())&lt;br /&gt;
&lt;br /&gt;
#ConfigFile laden&lt;br /&gt;
conf = json.load(open(args[&amp;quot;conf&amp;quot;]))&lt;br /&gt;
client = None&lt;br /&gt;
&lt;br /&gt;
#Gespeichertes Bild mit Pfad in Variable&lt;br /&gt;
path = (conf[&amp;quot;path_to_picture&amp;quot;])&lt;br /&gt;
picture = (conf[&amp;quot;picture&amp;quot;])&lt;br /&gt;
type = (conf[&amp;quot;type&amp;quot;])&lt;br /&gt;
first_picture = path + &amp;quot;/&amp;quot; + picture + &amp;quot;.&amp;quot; + type&lt;br /&gt;
&lt;br /&gt;
#Namen der Maske auslesen&lt;br /&gt;
first_mask = (conf[&amp;quot;mask&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
#Laden des Bildes&lt;br /&gt;
image = cv2.imread(first_picture)&lt;br /&gt;
&lt;br /&gt;
# Bild anzeigen&lt;br /&gt;
#cv2.imshow(&amp;quot;Originalbild&amp;quot;, image)&lt;br /&gt;
&lt;br /&gt;
# Schleife erzeugen&lt;br /&gt;
ROI = int(conf[&amp;quot;different_ROI&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
print &amp;quot;Soll-Durchlaeufe &amp;quot; + str(ROI)&lt;br /&gt;
&lt;br /&gt;
i = 0&lt;br /&gt;
while i &amp;lt; ROI:&lt;br /&gt;
	i = i + 1&lt;br /&gt;
	&lt;br /&gt;
	# Maskenpfad und Dateinamen generieren&lt;br /&gt;
	mask = path + &amp;quot;/&amp;quot; + first_mask + &amp;quot;_mask_&amp;quot; + str(i) + &amp;quot;.&amp;quot; + type&lt;br /&gt;
	&lt;br /&gt;
	# Maske laden&lt;br /&gt;
	mask = cv2.imread(mask,0)&lt;br /&gt;
	&lt;br /&gt;
	# Maske anwenden&lt;br /&gt;
	masked = cv2.bitwise_and(image, image, mask = mask)&lt;br /&gt;
	#cv2.imshow(&amp;quot;Maske&amp;quot;, masked)&lt;br /&gt;
	&lt;br /&gt;
	# BGR in HSV konvertieren wenn gewollt&lt;br /&gt;
	if conf[&amp;quot;hsv&amp;quot;]: &lt;br /&gt;
		masked = cv2.cvtColor(masked, cv2.COLOR_BGR2HSV)&lt;br /&gt;
		#cv2.imshow(&amp;quot;HSV&amp;quot;, masked)&lt;br /&gt;
	&lt;br /&gt;
	# Grenzwerte aus Config auslesen&lt;br /&gt;
	lower_col_value = tuple(conf[&amp;quot;lower_col&amp;quot; + &amp;quot;_&amp;quot; + str(i)])&lt;br /&gt;
	upper_col_value = tuple(conf[&amp;quot;upper_col&amp;quot; + &amp;quot;_&amp;quot; + str(i)])&lt;br /&gt;
	#print lower_col&lt;br /&gt;
	#print upper_col&lt;br /&gt;
	&lt;br /&gt;
	# Range definieren&lt;br /&gt;
	lower_col = np.array([(lower_col_value)], dtype=np.uint8)&lt;br /&gt;
	upper_col = np.array([(upper_col_value)], dtype=np.uint8)&lt;br /&gt;
&lt;br /&gt;
	# Threshold the image to get only selected colors&lt;br /&gt;
	mask = cv2.inRange(masked, lower_col, upper_col)&lt;br /&gt;
	#cv2.imshow(&amp;quot;Maske&amp;quot;, mask)&lt;br /&gt;
&lt;br /&gt;
	# Pixel zaehlen&lt;br /&gt;
	white = cv2.countNonZero(mask)&lt;br /&gt;
	print(&#039;The number of positive pixels is: &#039; + str(white))&lt;br /&gt;
	&lt;br /&gt;
	# Pixelanzahl an fhem senden&lt;br /&gt;
	# fhem Kommando erzeugen&lt;br /&gt;
	url = (conf[&amp;quot;fhem_host_port&amp;quot;])&lt;br /&gt;
	request = (conf[&amp;quot;fhem_request&amp;quot;])&lt;br /&gt;
	command = (conf[&amp;quot;fhem_command&amp;quot; + &amp;quot;_&amp;quot; + str(i)])&lt;br /&gt;
	value =  &amp;quot;%20&amp;quot; + str(white)&lt;br /&gt;
	fhem = url + request + command + value&lt;br /&gt;
	#print fhem&lt;br /&gt;
	urllib.urlopen(fhem)&lt;br /&gt;
	&lt;br /&gt;
	#cv2.waitKey(0)&lt;br /&gt;
	&lt;br /&gt;
print &amp;quot;Fertig&amp;quot;	&lt;br /&gt;
#cv2.waitKey(0)&lt;br /&gt;
cv2.destroyAllWindows()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config-File===&lt;br /&gt;
So kann ein Config File aussehen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
5seenland.json (könnte ein guter Dateinname sein...)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;config_version&amp;quot;: &amp;quot;0.2&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_host_port&amp;quot;: &amp;quot;http://192.168.5.31:8083&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_request&amp;quot;: &amp;quot;/fhem?cmd=&amp;quot;,&lt;br /&gt;
	&amp;quot;different_ROI&amp;quot;: &amp;quot;8&amp;quot;,&lt;br /&gt;
	&amp;quot;path_to_picture&amp;quot;: &amp;quot;./Picture&amp;quot;,&lt;br /&gt;
	&amp;quot;picture&amp;quot;: &amp;quot;bodenfeuchte&amp;quot;,&lt;br /&gt;
	&amp;quot;type&amp;quot;: &amp;quot;png&amp;quot;,&lt;br /&gt;
	&amp;quot;mask&amp;quot;: &amp;quot;5seenland&amp;quot;,&lt;br /&gt;
	&amp;quot;hsv&amp;quot;: false,&lt;br /&gt;
	&amp;quot;lower_col_1&amp;quot;: [45,100,200],&lt;br /&gt;
	&amp;quot;upper_col_1&amp;quot;: [45,100,200],&lt;br /&gt;
	&amp;quot;lower_col_2&amp;quot;: [60,200,250],&lt;br /&gt;
	&amp;quot;upper_col_2&amp;quot;: [60,200,250],&lt;br /&gt;
	&amp;quot;lower_col_3&amp;quot;: [75,250,250],&lt;br /&gt;
	&amp;quot;upper_col_3&amp;quot;: [75,250,250],&lt;br /&gt;
	&amp;quot;lower_col_4&amp;quot;: [75,250,200],&lt;br /&gt;
	&amp;quot;upper_col_4&amp;quot;: [75,250,200],&lt;br /&gt;
	&amp;quot;lower_col_5&amp;quot;: [75,220,150],&lt;br /&gt;
	&amp;quot;upper_col_5&amp;quot;: [75,220,150],&lt;br /&gt;
	&amp;quot;lower_col_6&amp;quot;: [75,150,75],&lt;br /&gt;
	&amp;quot;upper_col_6&amp;quot;: [75,150,75],&lt;br /&gt;
	&amp;quot;lower_col_7&amp;quot;: [250,200,50],&lt;br /&gt;
	&amp;quot;upper_col_7&amp;quot;: [250,200,50],&lt;br /&gt;
	&amp;quot;lower_col_8&amp;quot;: [250,0,0],&lt;br /&gt;
	&amp;quot;upper_col_8&amp;quot;: [250,0,0],&lt;br /&gt;
	&amp;quot;fhem_command_1&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%200-10&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_2&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2010-30&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_3&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2030-50&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_4&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2050-80&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_5&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2080-95&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_6&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2095-100&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_7&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%20100-105&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_8&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%20105-&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Eigentlich ganz einfach. Für jede ROI benötigt man lower_col_?, upper_col_? und fhem_command_?&lt;br /&gt;
&lt;br /&gt;
Die  lower/upper cols definieren für jede ROI den zu suchenden Farbbereich... das Ergebnis wird dann an den fhem_command_? angehängt.&lt;br /&gt;
&lt;br /&gt;
Hat man nur 2 ROI, kann man die Werte 3-8 natürlich rauswerfen; andernfalls werden sie schlicht ignoriert, tun also nicht weh. Sind nur eben sinnbefreit.&lt;br /&gt;
&lt;br /&gt;
===Beispiel mit Bildern===&lt;br /&gt;
Ist denke ich im Forumsthread schon ganz schön beschrieben.&lt;br /&gt;
&lt;br /&gt;
Wer eigene Beispiele hat, immer her damit :)&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Optischer_Sensor,_Software&amp;diff=11886</id>
		<title>Optischer Sensor, Software</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Optischer_Sensor,_Software&amp;diff=11886"/>
		<updated>2015-08-04T10:56:57Z</updated>

		<summary type="html">&lt;p&gt;Rince: /* Kalibrierung des Sensors */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- hier nicht erforderlich; verwirrt derzeit nur {{SEITENTITEL:Optischer Sensor, Software}} --&amp;gt;&lt;br /&gt;
&amp;lt;!-- stattdessen: evtl gleich {{Infobox Modul}} einbauen und füllen (und vielleicht auch an der darin vorgeschlagenen Gliederung orientieren) --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todo|Das wird die Doku für den optischen Sensor. Der Programmcode ist ziemlich weit gediehen. Ich dachte mir, die Doku mal zum Start eines Projekts fertig zu haben, ist auch nicht schlecht}}&lt;br /&gt;
&amp;lt;!-- Hier wäre eine &amp;quot;Unterschrift&amp;quot; nicht schlecht, auch wenn in Artikeln/Seiten eigentlich unüblich. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Was ich noch nicht weiß==&lt;br /&gt;
* soll das Programm regelmäßig per Cron ausgeführt werden, oder ist es schlauer einen WebSocket zu öffnen, so dass fhem dem Programm sagen kann, wenn es ein Bild bearbeiten soll&lt;br /&gt;
* &amp;lt;s&amp;gt;Treshold für Farben im Programm anwenden,&amp;lt;/s&amp;gt; oder nackten Zähler direkt an fhem senden&lt;br /&gt;
** besser, eine Weiterverarbeitung der Werte in fhem&lt;br /&gt;
** fhem ist diesbezüglich viel mächtiger&lt;br /&gt;
&lt;br /&gt;
==Übersicht==&lt;br /&gt;
Das kleine Programm liest ein Farbbild ein. Anschließend werden (in definierbaren Bereichen) Farbwerte ermittelt. Das Resultat wird dann an fhem gesendet.&lt;br /&gt;
&lt;br /&gt;
Wozu ist das gut?&lt;br /&gt;
&lt;br /&gt;
Mein Anwendungsfall:&lt;br /&gt;
&lt;br /&gt;
Eine USB Kamera am Raspberry macht regelmäßig Bilder meiner Küche. Darin sind insbesondere die Geschirrspülmaschine und der Herd zu sehen. Wenn meine Geschirrspülmaschine Dinge wie Salz oder Klarspüler benötigt, leuchtet eine entsprechende LED rot auf. Das kann das Programm erkennen und fhem mitteilen. &lt;br /&gt;
Ähnlich beim Herd: ist der an, leuchtet es gelb. Beim Verlassen des Hauses kann mir fhem sagen, dass der Herd noch an ist...&lt;br /&gt;
&lt;br /&gt;
Wichtig:&lt;br /&gt;
Die Kamera darf nicht bewegt werden, sonst funktionieren die Masken nicht mehr! Also z.B. festschrauben...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anderer Anwendungsfall:&lt;br /&gt;
&lt;br /&gt;
Ein Bild (z.B. Bodenfeuchte) vom DWD runterladen (das müsst ihr selbst!), dann analysieren lassen, welche Bodenfeuchte bei euch ist. Selbiges wird an fhem gesendet.&lt;br /&gt;
&lt;br /&gt;
Einfach für jede mögliche Farbe eine eigene Maske erstellen (die ist natürlich identisch), in die conf die Farbwerte und die setreadings schreiben, fertig...&lt;br /&gt;
&lt;br /&gt;
{{Link2Forum|Topic=39678|LinkText=Forumsthread}}&lt;br /&gt;
&lt;br /&gt;
==Beschreibung==&lt;br /&gt;
Ein bisschen mehr ins Detail gehend:&lt;br /&gt;
&lt;br /&gt;
Das Programm erwartet ein farbiges Bitmap Bild. Anschließend werden Masken über das Bild gelegt. Was übrig bleibt (idealerweise also der Bildausschnitt wo die entsprechende LED zu sehen ist) wird in den HSV Farbraum konvertiert. Eine Beschreibung warum und wie er funktioniert, folgt noch. Dann werden Die gewünschten Farben gefiltert. Intern übrig bleiben dann einige weiße Pixel auf schwarzem Grund. Die werden schlicht gezählt. Der Wert wird an fhem gesendet.&lt;br /&gt;
&lt;br /&gt;
===Konfiguration der Software===&lt;br /&gt;
Das Programm an sich benötigt eine Config-Datei.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;fhem_host_port&amp;quot;: &amp;quot;http://192.168.5.31:8083&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_request&amp;quot;: &amp;quot;/fhem?cmd=&amp;quot;,&lt;br /&gt;
	&amp;quot;different_ROI&amp;quot;: &amp;quot;5&amp;quot;,&lt;br /&gt;
	&amp;quot;path_to_picture&amp;quot;: &amp;quot;./Picture&amp;quot;,&lt;br /&gt;
	&amp;quot;picture&amp;quot;: &amp;quot;picture_kitchen&amp;quot;,&lt;br /&gt;
	&amp;quot;type&amp;quot;: &amp;quot;jpg&amp;quot;,&lt;br /&gt;
	&amp;quot;mask&amp;quot;: &amp;quot;dishwasher&amp;quot;,&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Was ist hier einzustellen?&lt;br /&gt;
* &amp;quot;fhem_host_port&amp;quot;: Adresse des fhem Servers, ebenso wie der Port. (Muss man also anpassen)&lt;br /&gt;
* &amp;quot;fhem_request&amp;quot;: (weiß nicht, wie es heißt), sollte aber so passen&lt;br /&gt;
* &amp;quot;different_ROI&amp;quot;: ist spannend: hier sagt man, wie viele LEDs (ROI = region of interesst) man überwachen will. (für jede ROI muss genau 1 Maske existieren)&lt;br /&gt;
* &amp;quot;path_to_picture&amp;quot;: logisch, wo liegt das Bild? In diesem Fall in einem Unterordner Namens Picture&lt;br /&gt;
* &amp;quot;picture&amp;quot;: der Name des Bildes (aufgemerkt: das Programm geht also immer vom gleichen Dateinamen aus!) (Quellbild)&lt;br /&gt;
* &amp;quot;type&amp;quot;: bitte mit angeben; jpg, png...&lt;br /&gt;
* &amp;quot;mask&amp;quot;: der erste Teil des Maskennamens&lt;br /&gt;
** die Dateiendung nicht angeben, bitte die gleiche wie beim Quellbild verwenden&lt;br /&gt;
** so kann man bei einem Quellbild verschiedene Masken angeben (in verschiedenen Config Dateien)&lt;br /&gt;
** bei Karten vom DWD z.B. kann man so aus einem Quellbild Werte für verschiedene Regionen ermitteln&lt;br /&gt;
** munic.conf, berlin.conf&lt;br /&gt;
** bei mehr Küchengeräten z.B. dishwasher.conf und waterboiler.conf&lt;br /&gt;
&lt;br /&gt;
===Was sind diese Masken?===&lt;br /&gt;
Die sind cool. Einfache schwarz/weiß Bilder.&lt;br /&gt;
&lt;br /&gt;
Zum erstellen:&lt;br /&gt;
Ein Musterbild von der Kamera besorgen. In Gimp öffnen, den Bereich um eine der gewünschten LEDs ein Viereck oder ein Kreis, ist egal) markieren. Löschen, Füllfarbe weiß. Markierung umdrehen, löschen, Füllfarbe schwarz. Fertig.&lt;br /&gt;
&lt;br /&gt;
Stellt euch vor, die Maske wäre aus Tonpapier. Da wo weiß ist, ist ein Loch drin. Die Maske wird über das Bild gelegt. Nun seht ihr nur noch die gewünschte LED...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wichtig:&lt;br /&gt;
&lt;br /&gt;
Die Maske braucht nun einen festen Dateinamen, damit sie gefunden werden kann! Hängt an den in der Config angegebenen Dateinamen ein _mask_1 an, für eure erste Maske. Hättet ihr ROI = 1, ist das alles. Bei ROI = 2 wollen wir 2 Masken abarbeiten.&lt;br /&gt;
&lt;br /&gt;
Also, bei ROI = 3&lt;br /&gt;
* quellbild.jpg (das, was eure Kamera immer generiert, oder euch der DWD zur Verfügung stellt)&lt;br /&gt;
* &amp;lt;AngegebenerName&amp;gt;_mask_1.jpg (die Dateiendung bitte wie beim Quellbild)&lt;br /&gt;
* &amp;lt;AngegebenerName&amp;gt;_mask_2.jpg&lt;br /&gt;
* &amp;lt;AngegebenerName&amp;gt;_mask_3.jpg&lt;br /&gt;
&lt;br /&gt;
===Benötigte Frameworks===&lt;br /&gt;
folgt noch&lt;br /&gt;
&lt;br /&gt;
*Linux&lt;br /&gt;
*[http://www.pyimagesearch.com/2015/02/23/install-opencv-and-python-on-your-raspberry-pi-2-and-b/ Diese] Anleitung ist wirklich gut. Habe es auf meinem RasPi auch so gemacht.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Windows&lt;br /&gt;
*bei Bedarf gerne&lt;br /&gt;
&lt;br /&gt;
===Kalibrierung des Sensors===&lt;br /&gt;
Das Programm kennt zwei verschiedene Betriebsmodi:&lt;br /&gt;
&lt;br /&gt;
====RGB / BGR====&lt;br /&gt;
RGB (dafür in der json den Wert &amp;quot;hsv&amp;quot; auf false setzen)&lt;br /&gt;
RGB eignet sich gut, um Grafiken zu untersuchen. Siehe das DWD Beispiel. Bitte als B G R die Werte eingeben (nicht RGB).&lt;br /&gt;
&lt;br /&gt;
Wenn es jeweils nur eine Farbe ist, die gesucht werden soll, so ist der upper/lower Wert natürlich identisch.&lt;br /&gt;
&lt;br /&gt;
Die Werte kann man schlicht mit Gimp auslesen (Pipette, auf die gewünschte Farbe klicken, im Werkzeugfenster auf die Farbe klicken, dann stehen die Werte da...)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====HSV====&lt;br /&gt;
Das ist etwas tricky.&lt;br /&gt;
&lt;br /&gt;
Obacht: didaktische Reduktion!&lt;br /&gt;
&lt;br /&gt;
Prinzipiell kann man sich HSV zunächst mal als einen Farbkreis vorstellen. Damit bekommt jede Farbe einen Winkel. Der Witz an der Sache ist, dass die Helligkeit hier keine Rolle spielt. Die versteckt sich nämlich nicht auf unserem Farbkreis! Diese wird durch die Tiefe repräsentiert. Dazu legen wir jetzt unseren Farbkreis auf eine Papprolle (und knippsen oben ein imaginäres Licht an).&lt;br /&gt;
&lt;br /&gt;
Wenn wir uns jetzt die Farbe &amp;quot;Rot&amp;quot; vorstellen, dann gibt es davon ziemlich viele verschiedene. Von sehr hell, bis sehr dunkel. Der Winkel für helles und der für dunkles Rot ist im HSV Farbkreis der gleiche. Das macht diesen Farbraum für die Auswertung von Fotos sehr praktisch. Man kann schön mit zwei Werten quasi alle Rot-Töne abdecken.&lt;br /&gt;
&lt;br /&gt;
Der Haken:&lt;br /&gt;
&lt;br /&gt;
OpenCV sieht leider HSV anders, als GIMP. Daher ist es nicht ganz trivial, die passenden Werte für die Farben rauszufinden.&lt;br /&gt;
&lt;br /&gt;
Gebe im Forum dazu gerne Hilfestellung.&lt;br /&gt;
&lt;br /&gt;
==Programmcode==&lt;br /&gt;
Der Programmcode ist im ersten Forumsthread mit einigen Beispielen zum Download.&lt;br /&gt;
[http://forum.fhem.de/index.php/topic,39678.msg318865.html#msg318865 Download]&lt;br /&gt;
&lt;br /&gt;
===Sensor===&lt;br /&gt;
Anmerkung:&lt;br /&gt;
&lt;br /&gt;
Ich bin kein Programmierer. Wenn das jemand durchliest der Ahnung hat, sich totlacht =&amp;gt; ich übernehme keine Verantwortung&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# Optical Sensor&lt;br /&gt;
# using Python 2.7 and OpenCV 2.4.11&lt;br /&gt;
# do not use german umlauts, not even in description&lt;br /&gt;
# ver 0.2 first public release&lt;br /&gt;
import cv2&lt;br /&gt;
import argparse&lt;br /&gt;
import json&lt;br /&gt;
import urllib&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
#cv2 importiert OpenCV&lt;br /&gt;
#argparse wird benoetigt fuer die Parameteruebergabe&lt;br /&gt;
#json zum lesen des Config-Files&lt;br /&gt;
#urllib um uns mit fhem zu unterhalten&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# construct the argument parse and parse the arguments&lt;br /&gt;
ap = argparse.ArgumentParser()&lt;br /&gt;
ap.add_argument(&amp;quot;-c&amp;quot;, &amp;quot;--conf&amp;quot;, required=True,&lt;br /&gt;
	help=&amp;quot;path to the JSON configuration file; eg try: &amp;gt;sensor.py --conf dishwasher.json&amp;quot;)&lt;br /&gt;
args = vars(ap.parse_args())&lt;br /&gt;
&lt;br /&gt;
#ConfigFile laden&lt;br /&gt;
conf = json.load(open(args[&amp;quot;conf&amp;quot;]))&lt;br /&gt;
client = None&lt;br /&gt;
&lt;br /&gt;
#Gespeichertes Bild mit Pfad in Variable&lt;br /&gt;
path = (conf[&amp;quot;path_to_picture&amp;quot;])&lt;br /&gt;
picture = (conf[&amp;quot;picture&amp;quot;])&lt;br /&gt;
type = (conf[&amp;quot;type&amp;quot;])&lt;br /&gt;
first_picture = path + &amp;quot;/&amp;quot; + picture + &amp;quot;.&amp;quot; + type&lt;br /&gt;
&lt;br /&gt;
#Namen der Maske auslesen&lt;br /&gt;
first_mask = (conf[&amp;quot;mask&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
#Laden des Bildes&lt;br /&gt;
image = cv2.imread(first_picture)&lt;br /&gt;
&lt;br /&gt;
# Bild anzeigen&lt;br /&gt;
#cv2.imshow(&amp;quot;Originalbild&amp;quot;, image)&lt;br /&gt;
&lt;br /&gt;
# Schleife erzeugen&lt;br /&gt;
ROI = int(conf[&amp;quot;different_ROI&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
print &amp;quot;Soll-Durchlaeufe &amp;quot; + str(ROI)&lt;br /&gt;
&lt;br /&gt;
i = 0&lt;br /&gt;
while i &amp;lt; ROI:&lt;br /&gt;
	i = i + 1&lt;br /&gt;
	&lt;br /&gt;
	# Maskenpfad und Dateinamen generieren&lt;br /&gt;
	mask = path + &amp;quot;/&amp;quot; + first_mask + &amp;quot;_mask_&amp;quot; + str(i) + &amp;quot;.&amp;quot; + type&lt;br /&gt;
	&lt;br /&gt;
	# Maske laden&lt;br /&gt;
	mask = cv2.imread(mask,0)&lt;br /&gt;
	&lt;br /&gt;
	# Maske anwenden&lt;br /&gt;
	masked = cv2.bitwise_and(image, image, mask = mask)&lt;br /&gt;
	#cv2.imshow(&amp;quot;Maske&amp;quot;, masked)&lt;br /&gt;
	&lt;br /&gt;
	# BGR in HSV konvertieren wenn gewollt&lt;br /&gt;
	if conf[&amp;quot;hsv&amp;quot;]: &lt;br /&gt;
		masked = cv2.cvtColor(masked, cv2.COLOR_BGR2HSV)&lt;br /&gt;
		#cv2.imshow(&amp;quot;HSV&amp;quot;, masked)&lt;br /&gt;
	&lt;br /&gt;
	# Grenzwerte aus Config auslesen&lt;br /&gt;
	lower_col_value = tuple(conf[&amp;quot;lower_col&amp;quot; + &amp;quot;_&amp;quot; + str(i)])&lt;br /&gt;
	upper_col_value = tuple(conf[&amp;quot;upper_col&amp;quot; + &amp;quot;_&amp;quot; + str(i)])&lt;br /&gt;
	#print lower_col&lt;br /&gt;
	#print upper_col&lt;br /&gt;
	&lt;br /&gt;
	# Range definieren&lt;br /&gt;
	lower_col = np.array([(lower_col_value)], dtype=np.uint8)&lt;br /&gt;
	upper_col = np.array([(upper_col_value)], dtype=np.uint8)&lt;br /&gt;
&lt;br /&gt;
	# Threshold the image to get only selected colors&lt;br /&gt;
	mask = cv2.inRange(masked, lower_col, upper_col)&lt;br /&gt;
	#cv2.imshow(&amp;quot;Maske&amp;quot;, mask)&lt;br /&gt;
&lt;br /&gt;
	# Pixel zaehlen&lt;br /&gt;
	white = cv2.countNonZero(mask)&lt;br /&gt;
	print(&#039;The number of positive pixels is: &#039; + str(white))&lt;br /&gt;
	&lt;br /&gt;
	# Pixelanzahl an fhem senden&lt;br /&gt;
	# fhem Kommando erzeugen&lt;br /&gt;
	url = (conf[&amp;quot;fhem_host_port&amp;quot;])&lt;br /&gt;
	request = (conf[&amp;quot;fhem_request&amp;quot;])&lt;br /&gt;
	command = (conf[&amp;quot;fhem_command&amp;quot; + &amp;quot;_&amp;quot; + str(i)])&lt;br /&gt;
	value =  &amp;quot;%20&amp;quot; + str(white)&lt;br /&gt;
	fhem = url + request + command + value&lt;br /&gt;
	#print fhem&lt;br /&gt;
	urllib.urlopen(fhem)&lt;br /&gt;
	&lt;br /&gt;
	#cv2.waitKey(0)&lt;br /&gt;
	&lt;br /&gt;
print &amp;quot;Fertig&amp;quot;	&lt;br /&gt;
#cv2.waitKey(0)&lt;br /&gt;
cv2.destroyAllWindows()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config-File===&lt;br /&gt;
So kann ein Config File aussehen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
5seenland.json (könnte ein guter Dateinname sein...)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;config_version&amp;quot;: &amp;quot;0.2&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_host_port&amp;quot;: &amp;quot;http://192.168.5.31:8083&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_request&amp;quot;: &amp;quot;/fhem?cmd=&amp;quot;,&lt;br /&gt;
	&amp;quot;different_ROI&amp;quot;: &amp;quot;8&amp;quot;,&lt;br /&gt;
	&amp;quot;path_to_picture&amp;quot;: &amp;quot;./Picture&amp;quot;,&lt;br /&gt;
	&amp;quot;picture&amp;quot;: &amp;quot;bodenfeuchte&amp;quot;,&lt;br /&gt;
	&amp;quot;type&amp;quot;: &amp;quot;png&amp;quot;,&lt;br /&gt;
	&amp;quot;mask&amp;quot;: &amp;quot;5seenland&amp;quot;,&lt;br /&gt;
	&amp;quot;hsv&amp;quot;: false,&lt;br /&gt;
	&amp;quot;lower_col_1&amp;quot;: [45,100,200],&lt;br /&gt;
	&amp;quot;upper_col_1&amp;quot;: [45,100,200],&lt;br /&gt;
	&amp;quot;lower_col_2&amp;quot;: [60,200,250],&lt;br /&gt;
	&amp;quot;upper_col_2&amp;quot;: [60,200,250],&lt;br /&gt;
	&amp;quot;lower_col_3&amp;quot;: [75,250,250],&lt;br /&gt;
	&amp;quot;upper_col_3&amp;quot;: [75,250,250],&lt;br /&gt;
	&amp;quot;lower_col_4&amp;quot;: [75,250,200],&lt;br /&gt;
	&amp;quot;upper_col_4&amp;quot;: [75,250,200],&lt;br /&gt;
	&amp;quot;lower_col_5&amp;quot;: [75,220,150],&lt;br /&gt;
	&amp;quot;upper_col_5&amp;quot;: [75,220,150],&lt;br /&gt;
	&amp;quot;lower_col_6&amp;quot;: [75,150,75],&lt;br /&gt;
	&amp;quot;upper_col_6&amp;quot;: [75,150,75],&lt;br /&gt;
	&amp;quot;lower_col_7&amp;quot;: [250,200,50],&lt;br /&gt;
	&amp;quot;upper_col_7&amp;quot;: [250,200,50],&lt;br /&gt;
	&amp;quot;lower_col_8&amp;quot;: [250,0,0],&lt;br /&gt;
	&amp;quot;upper_col_8&amp;quot;: [250,0,0],&lt;br /&gt;
	&amp;quot;fhem_command_1&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%200-10&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_2&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2010-30&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_3&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2030-50&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_4&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2050-80&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_5&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2080-95&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_6&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2095-100&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_7&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%20100-105&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_8&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%20105-&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Eigentlich ganz einfach. Für jede ROI benötigt man lower_col_?, upper_col_? und fhem_command_?&lt;br /&gt;
&lt;br /&gt;
Die  lower/upper cols definieren für jede ROI den zu suchenden Farbbereich... das Ergebnis wird dann an den fhem_command_? angehängt.&lt;br /&gt;
&lt;br /&gt;
Hat man nur 2 ROI, kann man die Werte 4-8 natürlich rauswerfen; andernfalls werden sie schlicht ignoriert, tun also auch nicht weh. Sind nur eben sinnbefreit.&lt;br /&gt;
&lt;br /&gt;
===Beispiel mit Bildern===&lt;br /&gt;
Ist denke ich im Forumsthread schon ganz schön beschrieben.&lt;br /&gt;
&lt;br /&gt;
Wer eigene Beispiele hat, immer her damit :)&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Optischer_Sensor,_Software&amp;diff=11885</id>
		<title>Optischer Sensor, Software</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Optischer_Sensor,_Software&amp;diff=11885"/>
		<updated>2015-08-04T10:43:33Z</updated>

		<summary type="html">&lt;p&gt;Rince: /* Benötigte Frameworks */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- hier nicht erforderlich; verwirrt derzeit nur {{SEITENTITEL:Optischer Sensor, Software}} --&amp;gt;&lt;br /&gt;
&amp;lt;!-- stattdessen: evtl gleich {{Infobox Modul}} einbauen und füllen (und vielleicht auch an der darin vorgeschlagenen Gliederung orientieren) --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todo|Das wird die Doku für den optischen Sensor. Der Programmcode ist ziemlich weit gediehen. Ich dachte mir, die Doku mal zum Start eines Projekts fertig zu haben, ist auch nicht schlecht}}&lt;br /&gt;
&amp;lt;!-- Hier wäre eine &amp;quot;Unterschrift&amp;quot; nicht schlecht, auch wenn in Artikeln/Seiten eigentlich unüblich. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Was ich noch nicht weiß==&lt;br /&gt;
* soll das Programm regelmäßig per Cron ausgeführt werden, oder ist es schlauer einen WebSocket zu öffnen, so dass fhem dem Programm sagen kann, wenn es ein Bild bearbeiten soll&lt;br /&gt;
* &amp;lt;s&amp;gt;Treshold für Farben im Programm anwenden,&amp;lt;/s&amp;gt; oder nackten Zähler direkt an fhem senden&lt;br /&gt;
** besser, eine Weiterverarbeitung der Werte in fhem&lt;br /&gt;
** fhem ist diesbezüglich viel mächtiger&lt;br /&gt;
&lt;br /&gt;
==Übersicht==&lt;br /&gt;
Das kleine Programm liest ein Farbbild ein. Anschließend werden (in definierbaren Bereichen) Farbwerte ermittelt. Das Resultat wird dann an fhem gesendet.&lt;br /&gt;
&lt;br /&gt;
Wozu ist das gut?&lt;br /&gt;
&lt;br /&gt;
Mein Anwendungsfall:&lt;br /&gt;
&lt;br /&gt;
Eine USB Kamera am Raspberry macht regelmäßig Bilder meiner Küche. Darin sind insbesondere die Geschirrspülmaschine und der Herd zu sehen. Wenn meine Geschirrspülmaschine Dinge wie Salz oder Klarspüler benötigt, leuchtet eine entsprechende LED rot auf. Das kann das Programm erkennen und fhem mitteilen. &lt;br /&gt;
Ähnlich beim Herd: ist der an, leuchtet es gelb. Beim Verlassen des Hauses kann mir fhem sagen, dass der Herd noch an ist...&lt;br /&gt;
&lt;br /&gt;
Wichtig:&lt;br /&gt;
Die Kamera darf nicht bewegt werden, sonst funktionieren die Masken nicht mehr! Also z.B. festschrauben...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anderer Anwendungsfall:&lt;br /&gt;
&lt;br /&gt;
Ein Bild (z.B. Bodenfeuchte) vom DWD runterladen (das müsst ihr selbst!), dann analysieren lassen, welche Bodenfeuchte bei euch ist. Selbiges wird an fhem gesendet.&lt;br /&gt;
&lt;br /&gt;
Einfach für jede mögliche Farbe eine eigene Maske erstellen (die ist natürlich identisch), in die conf die Farbwerte und die setreadings schreiben, fertig...&lt;br /&gt;
&lt;br /&gt;
{{Link2Forum|Topic=39678|LinkText=Forumsthread}}&lt;br /&gt;
&lt;br /&gt;
==Beschreibung==&lt;br /&gt;
Ein bisschen mehr ins Detail gehend:&lt;br /&gt;
&lt;br /&gt;
Das Programm erwartet ein farbiges Bitmap Bild. Anschließend werden Masken über das Bild gelegt. Was übrig bleibt (idealerweise also der Bildausschnitt wo die entsprechende LED zu sehen ist) wird in den HSV Farbraum konvertiert. Eine Beschreibung warum und wie er funktioniert, folgt noch. Dann werden Die gewünschten Farben gefiltert. Intern übrig bleiben dann einige weiße Pixel auf schwarzem Grund. Die werden schlicht gezählt. Der Wert wird an fhem gesendet.&lt;br /&gt;
&lt;br /&gt;
===Konfiguration der Software===&lt;br /&gt;
Das Programm an sich benötigt eine Config-Datei.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;fhem_host_port&amp;quot;: &amp;quot;http://192.168.5.31:8083&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_request&amp;quot;: &amp;quot;/fhem?cmd=&amp;quot;,&lt;br /&gt;
	&amp;quot;different_ROI&amp;quot;: &amp;quot;5&amp;quot;,&lt;br /&gt;
	&amp;quot;path_to_picture&amp;quot;: &amp;quot;./Picture&amp;quot;,&lt;br /&gt;
	&amp;quot;picture&amp;quot;: &amp;quot;picture_kitchen&amp;quot;,&lt;br /&gt;
	&amp;quot;type&amp;quot;: &amp;quot;jpg&amp;quot;,&lt;br /&gt;
	&amp;quot;mask&amp;quot;: &amp;quot;dishwasher&amp;quot;,&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Was ist hier einzustellen?&lt;br /&gt;
* &amp;quot;fhem_host_port&amp;quot;: Adresse des fhem Servers, ebenso wie der Port. (Muss man also anpassen)&lt;br /&gt;
* &amp;quot;fhem_request&amp;quot;: (weiß nicht, wie es heißt), sollte aber so passen&lt;br /&gt;
* &amp;quot;different_ROI&amp;quot;: ist spannend: hier sagt man, wie viele LEDs (ROI = region of interesst) man überwachen will. (für jede ROI muss genau 1 Maske existieren)&lt;br /&gt;
* &amp;quot;path_to_picture&amp;quot;: logisch, wo liegt das Bild? In diesem Fall in einem Unterordner Namens Picture&lt;br /&gt;
* &amp;quot;picture&amp;quot;: der Name des Bildes (aufgemerkt: das Programm geht also immer vom gleichen Dateinamen aus!) (Quellbild)&lt;br /&gt;
* &amp;quot;type&amp;quot;: bitte mit angeben; jpg, png...&lt;br /&gt;
* &amp;quot;mask&amp;quot;: der erste Teil des Maskennamens&lt;br /&gt;
** die Dateiendung nicht angeben, bitte die gleiche wie beim Quellbild verwenden&lt;br /&gt;
** so kann man bei einem Quellbild verschiedene Masken angeben (in verschiedenen Config Dateien)&lt;br /&gt;
** bei Karten vom DWD z.B. kann man so aus einem Quellbild Werte für verschiedene Regionen ermitteln&lt;br /&gt;
** munic.conf, berlin.conf&lt;br /&gt;
** bei mehr Küchengeräten z.B. dishwasher.conf und waterboiler.conf&lt;br /&gt;
&lt;br /&gt;
===Was sind diese Masken?===&lt;br /&gt;
Die sind cool. Einfache schwarz/weiß Bilder.&lt;br /&gt;
&lt;br /&gt;
Zum erstellen:&lt;br /&gt;
Ein Musterbild von der Kamera besorgen. In Gimp öffnen, den Bereich um eine der gewünschten LEDs ein Viereck oder ein Kreis, ist egal) markieren. Löschen, Füllfarbe weiß. Markierung umdrehen, löschen, Füllfarbe schwarz. Fertig.&lt;br /&gt;
&lt;br /&gt;
Stellt euch vor, die Maske wäre aus Tonpapier. Da wo weiß ist, ist ein Loch drin. Die Maske wird über das Bild gelegt. Nun seht ihr nur noch die gewünschte LED...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wichtig:&lt;br /&gt;
&lt;br /&gt;
Die Maske braucht nun einen festen Dateinamen, damit sie gefunden werden kann! Hängt an den in der Config angegebenen Dateinamen ein _mask_1 an, für eure erste Maske. Hättet ihr ROI = 1, ist das alles. Bei ROI = 2 wollen wir 2 Masken abarbeiten.&lt;br /&gt;
&lt;br /&gt;
Also, bei ROI = 3&lt;br /&gt;
* quellbild.jpg (das, was eure Kamera immer generiert, oder euch der DWD zur Verfügung stellt)&lt;br /&gt;
* &amp;lt;AngegebenerName&amp;gt;_mask_1.jpg (die Dateiendung bitte wie beim Quellbild)&lt;br /&gt;
* &amp;lt;AngegebenerName&amp;gt;_mask_2.jpg&lt;br /&gt;
* &amp;lt;AngegebenerName&amp;gt;_mask_3.jpg&lt;br /&gt;
&lt;br /&gt;
===Benötigte Frameworks===&lt;br /&gt;
folgt noch&lt;br /&gt;
&lt;br /&gt;
*Linux&lt;br /&gt;
*[http://www.pyimagesearch.com/2015/02/23/install-opencv-and-python-on-your-raspberry-pi-2-and-b/ Diese] Anleitung ist wirklich gut. Habe es auf meinem RasPi auch so gemacht.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Windows&lt;br /&gt;
*bei Bedarf gerne&lt;br /&gt;
&lt;br /&gt;
===Kalibrierung des Sensors===&lt;br /&gt;
&lt;br /&gt;
==Programmcode==&lt;br /&gt;
Der Programmcode ist im ersten Forumsthread mit einigen Beispielen zum Download.&lt;br /&gt;
[http://forum.fhem.de/index.php/topic,39678.msg318865.html#msg318865 Download]&lt;br /&gt;
&lt;br /&gt;
===Sensor===&lt;br /&gt;
Anmerkung:&lt;br /&gt;
&lt;br /&gt;
Ich bin kein Programmierer. Wenn das jemand durchliest der Ahnung hat, sich totlacht =&amp;gt; ich übernehme keine Verantwortung&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# Optical Sensor&lt;br /&gt;
# using Python 2.7 and OpenCV 2.4.11&lt;br /&gt;
# do not use german umlauts, not even in description&lt;br /&gt;
# ver 0.2 first public release&lt;br /&gt;
import cv2&lt;br /&gt;
import argparse&lt;br /&gt;
import json&lt;br /&gt;
import urllib&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
#cv2 importiert OpenCV&lt;br /&gt;
#argparse wird benoetigt fuer die Parameteruebergabe&lt;br /&gt;
#json zum lesen des Config-Files&lt;br /&gt;
#urllib um uns mit fhem zu unterhalten&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# construct the argument parse and parse the arguments&lt;br /&gt;
ap = argparse.ArgumentParser()&lt;br /&gt;
ap.add_argument(&amp;quot;-c&amp;quot;, &amp;quot;--conf&amp;quot;, required=True,&lt;br /&gt;
	help=&amp;quot;path to the JSON configuration file; eg try: &amp;gt;sensor.py --conf dishwasher.json&amp;quot;)&lt;br /&gt;
args = vars(ap.parse_args())&lt;br /&gt;
&lt;br /&gt;
#ConfigFile laden&lt;br /&gt;
conf = json.load(open(args[&amp;quot;conf&amp;quot;]))&lt;br /&gt;
client = None&lt;br /&gt;
&lt;br /&gt;
#Gespeichertes Bild mit Pfad in Variable&lt;br /&gt;
path = (conf[&amp;quot;path_to_picture&amp;quot;])&lt;br /&gt;
picture = (conf[&amp;quot;picture&amp;quot;])&lt;br /&gt;
type = (conf[&amp;quot;type&amp;quot;])&lt;br /&gt;
first_picture = path + &amp;quot;/&amp;quot; + picture + &amp;quot;.&amp;quot; + type&lt;br /&gt;
&lt;br /&gt;
#Namen der Maske auslesen&lt;br /&gt;
first_mask = (conf[&amp;quot;mask&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
#Laden des Bildes&lt;br /&gt;
image = cv2.imread(first_picture)&lt;br /&gt;
&lt;br /&gt;
# Bild anzeigen&lt;br /&gt;
#cv2.imshow(&amp;quot;Originalbild&amp;quot;, image)&lt;br /&gt;
&lt;br /&gt;
# Schleife erzeugen&lt;br /&gt;
ROI = int(conf[&amp;quot;different_ROI&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
print &amp;quot;Soll-Durchlaeufe &amp;quot; + str(ROI)&lt;br /&gt;
&lt;br /&gt;
i = 0&lt;br /&gt;
while i &amp;lt; ROI:&lt;br /&gt;
	i = i + 1&lt;br /&gt;
	&lt;br /&gt;
	# Maskenpfad und Dateinamen generieren&lt;br /&gt;
	mask = path + &amp;quot;/&amp;quot; + first_mask + &amp;quot;_mask_&amp;quot; + str(i) + &amp;quot;.&amp;quot; + type&lt;br /&gt;
	&lt;br /&gt;
	# Maske laden&lt;br /&gt;
	mask = cv2.imread(mask,0)&lt;br /&gt;
	&lt;br /&gt;
	# Maske anwenden&lt;br /&gt;
	masked = cv2.bitwise_and(image, image, mask = mask)&lt;br /&gt;
	#cv2.imshow(&amp;quot;Maske&amp;quot;, masked)&lt;br /&gt;
	&lt;br /&gt;
	# BGR in HSV konvertieren wenn gewollt&lt;br /&gt;
	if conf[&amp;quot;hsv&amp;quot;]: &lt;br /&gt;
		masked = cv2.cvtColor(masked, cv2.COLOR_BGR2HSV)&lt;br /&gt;
		#cv2.imshow(&amp;quot;HSV&amp;quot;, masked)&lt;br /&gt;
	&lt;br /&gt;
	# Grenzwerte aus Config auslesen&lt;br /&gt;
	lower_col_value = tuple(conf[&amp;quot;lower_col&amp;quot; + &amp;quot;_&amp;quot; + str(i)])&lt;br /&gt;
	upper_col_value = tuple(conf[&amp;quot;upper_col&amp;quot; + &amp;quot;_&amp;quot; + str(i)])&lt;br /&gt;
	#print lower_col&lt;br /&gt;
	#print upper_col&lt;br /&gt;
	&lt;br /&gt;
	# Range definieren&lt;br /&gt;
	lower_col = np.array([(lower_col_value)], dtype=np.uint8)&lt;br /&gt;
	upper_col = np.array([(upper_col_value)], dtype=np.uint8)&lt;br /&gt;
&lt;br /&gt;
	# Threshold the image to get only selected colors&lt;br /&gt;
	mask = cv2.inRange(masked, lower_col, upper_col)&lt;br /&gt;
	#cv2.imshow(&amp;quot;Maske&amp;quot;, mask)&lt;br /&gt;
&lt;br /&gt;
	# Pixel zaehlen&lt;br /&gt;
	white = cv2.countNonZero(mask)&lt;br /&gt;
	print(&#039;The number of positive pixels is: &#039; + str(white))&lt;br /&gt;
	&lt;br /&gt;
	# Pixelanzahl an fhem senden&lt;br /&gt;
	# fhem Kommando erzeugen&lt;br /&gt;
	url = (conf[&amp;quot;fhem_host_port&amp;quot;])&lt;br /&gt;
	request = (conf[&amp;quot;fhem_request&amp;quot;])&lt;br /&gt;
	command = (conf[&amp;quot;fhem_command&amp;quot; + &amp;quot;_&amp;quot; + str(i)])&lt;br /&gt;
	value =  &amp;quot;%20&amp;quot; + str(white)&lt;br /&gt;
	fhem = url + request + command + value&lt;br /&gt;
	#print fhem&lt;br /&gt;
	urllib.urlopen(fhem)&lt;br /&gt;
	&lt;br /&gt;
	#cv2.waitKey(0)&lt;br /&gt;
	&lt;br /&gt;
print &amp;quot;Fertig&amp;quot;	&lt;br /&gt;
#cv2.waitKey(0)&lt;br /&gt;
cv2.destroyAllWindows()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config-File===&lt;br /&gt;
So kann ein Config File aussehen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
5seenland.json (könnte ein guter Dateinname sein...)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;config_version&amp;quot;: &amp;quot;0.2&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_host_port&amp;quot;: &amp;quot;http://192.168.5.31:8083&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_request&amp;quot;: &amp;quot;/fhem?cmd=&amp;quot;,&lt;br /&gt;
	&amp;quot;different_ROI&amp;quot;: &amp;quot;8&amp;quot;,&lt;br /&gt;
	&amp;quot;path_to_picture&amp;quot;: &amp;quot;./Picture&amp;quot;,&lt;br /&gt;
	&amp;quot;picture&amp;quot;: &amp;quot;bodenfeuchte&amp;quot;,&lt;br /&gt;
	&amp;quot;type&amp;quot;: &amp;quot;png&amp;quot;,&lt;br /&gt;
	&amp;quot;mask&amp;quot;: &amp;quot;5seenland&amp;quot;,&lt;br /&gt;
	&amp;quot;hsv&amp;quot;: false,&lt;br /&gt;
	&amp;quot;lower_col_1&amp;quot;: [45,100,200],&lt;br /&gt;
	&amp;quot;upper_col_1&amp;quot;: [45,100,200],&lt;br /&gt;
	&amp;quot;lower_col_2&amp;quot;: [60,200,250],&lt;br /&gt;
	&amp;quot;upper_col_2&amp;quot;: [60,200,250],&lt;br /&gt;
	&amp;quot;lower_col_3&amp;quot;: [75,250,250],&lt;br /&gt;
	&amp;quot;upper_col_3&amp;quot;: [75,250,250],&lt;br /&gt;
	&amp;quot;lower_col_4&amp;quot;: [75,250,200],&lt;br /&gt;
	&amp;quot;upper_col_4&amp;quot;: [75,250,200],&lt;br /&gt;
	&amp;quot;lower_col_5&amp;quot;: [75,220,150],&lt;br /&gt;
	&amp;quot;upper_col_5&amp;quot;: [75,220,150],&lt;br /&gt;
	&amp;quot;lower_col_6&amp;quot;: [75,150,75],&lt;br /&gt;
	&amp;quot;upper_col_6&amp;quot;: [75,150,75],&lt;br /&gt;
	&amp;quot;lower_col_7&amp;quot;: [250,200,50],&lt;br /&gt;
	&amp;quot;upper_col_7&amp;quot;: [250,200,50],&lt;br /&gt;
	&amp;quot;lower_col_8&amp;quot;: [250,0,0],&lt;br /&gt;
	&amp;quot;upper_col_8&amp;quot;: [250,0,0],&lt;br /&gt;
	&amp;quot;fhem_command_1&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%200-10&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_2&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2010-30&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_3&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2030-50&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_4&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2050-80&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_5&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2080-95&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_6&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2095-100&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_7&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%20100-105&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_8&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%20105-&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Eigentlich ganz einfach. Für jede ROI benötigt man lower_col_?, upper_col_? und fhem_command_?&lt;br /&gt;
&lt;br /&gt;
Die  lower/upper cols definieren für jede ROI den zu suchenden Farbbereich... das Ergebnis wird dann an den fhem_command_? angehängt.&lt;br /&gt;
&lt;br /&gt;
Hat man nur 2 ROI, kann man die Werte 4-8 natürlich rauswerfen; andernfalls werden sie schlicht ignoriert, tun also auch nicht weh. Sind nur eben sinnbefreit.&lt;br /&gt;
&lt;br /&gt;
===Beispiel mit Bildern===&lt;br /&gt;
Ist denke ich im Forumsthread schon ganz schön beschrieben.&lt;br /&gt;
&lt;br /&gt;
Wer eigene Beispiele hat, immer her damit :)&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Optischer_Sensor,_Software&amp;diff=11883</id>
		<title>Optischer Sensor, Software</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Optischer_Sensor,_Software&amp;diff=11883"/>
		<updated>2015-08-04T10:33:30Z</updated>

		<summary type="html">&lt;p&gt;Rince: /* Config-File */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- hier nicht erforderlich; verwirrt derzeit nur {{SEITENTITEL:Optischer Sensor, Software}} --&amp;gt;&lt;br /&gt;
&amp;lt;!-- stattdessen: evtl gleich {{Infobox Modul}} einbauen und füllen (und vielleicht auch an der darin vorgeschlagenen Gliederung orientieren) --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Todo|Das wird die Doku für den optischen Sensor. Der Programmcode ist ziemlich weit gediehen. Ich dachte mir, die Doku mal zum Start eines Projekts fertig zu haben, ist auch nicht schlecht}}&lt;br /&gt;
&amp;lt;!-- Hier wäre eine &amp;quot;Unterschrift&amp;quot; nicht schlecht, auch wenn in Artikeln/Seiten eigentlich unüblich. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Was ich noch nicht weiß==&lt;br /&gt;
* soll das Programm regelmäßig per Cron ausgeführt werden, oder ist es schlauer einen WebSocket zu öffnen, so dass fhem dem Programm sagen kann, wenn es ein Bild bearbeiten soll&lt;br /&gt;
* &amp;lt;s&amp;gt;Treshold für Farben im Programm anwenden,&amp;lt;/s&amp;gt; oder nackten Zähler direkt an fhem senden&lt;br /&gt;
** besser, eine Weiterverarbeitung der Werte in fhem&lt;br /&gt;
** fhem ist diesbezüglich viel mächtiger&lt;br /&gt;
&lt;br /&gt;
==Übersicht==&lt;br /&gt;
Das kleine Programm liest ein Farbbild ein. Anschließend werden (in definierbaren Bereichen) Farbwerte ermittelt. Das Resultat wird dann an fhem gesendet.&lt;br /&gt;
&lt;br /&gt;
Wozu ist das gut?&lt;br /&gt;
&lt;br /&gt;
Mein Anwendungsfall:&lt;br /&gt;
&lt;br /&gt;
Eine USB Kamera am Raspberry macht regelmäßig Bilder meiner Küche. Darin sind insbesondere die Geschirrspülmaschine und der Herd zu sehen. Wenn meine Geschirrspülmaschine Dinge wie Salz oder Klarspüler benötigt, leuchtet eine entsprechende LED rot auf. Das kann das Programm erkennen und fhem mitteilen. &lt;br /&gt;
Ähnlich beim Herd: ist der an, leuchtet es gelb. Beim Verlassen des Hauses kann mir fhem sagen, dass der Herd noch an ist...&lt;br /&gt;
&lt;br /&gt;
Wichtig:&lt;br /&gt;
Die Kamera darf nicht bewegt werden, sonst funktionieren die Masken nicht mehr! Also z.B. festschrauben...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anderer Anwendungsfall:&lt;br /&gt;
&lt;br /&gt;
Ein Bild (z.B. Bodenfeuchte) vom DWD runterladen (das müsst ihr selbst!), dann analysieren lassen, welche Bodenfeuchte bei euch ist. Selbiges wird an fhem gesendet.&lt;br /&gt;
&lt;br /&gt;
Einfach für jede mögliche Farbe eine eigene Maske erstellen (die ist natürlich identisch), in die conf die Farbwerte und die setreadings schreiben, fertig...&lt;br /&gt;
&lt;br /&gt;
{{Link2Forum|Topic=39678|LinkText=Forumsthread}}&lt;br /&gt;
&lt;br /&gt;
==Beschreibung==&lt;br /&gt;
Ein bisschen mehr ins Detail gehend:&lt;br /&gt;
&lt;br /&gt;
Das Programm erwartet ein farbiges Bitmap Bild. Anschließend werden Masken über das Bild gelegt. Was übrig bleibt (idealerweise also der Bildausschnitt wo die entsprechende LED zu sehen ist) wird in den HSV Farbraum konvertiert. Eine Beschreibung warum und wie er funktioniert, folgt noch. Dann werden Die gewünschten Farben gefiltert. Intern übrig bleiben dann einige weiße Pixel auf schwarzem Grund. Die werden schlicht gezählt. Der Wert wird an fhem gesendet.&lt;br /&gt;
&lt;br /&gt;
===Konfiguration der Software===&lt;br /&gt;
Das Programm an sich benötigt eine Config-Datei.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;fhem_host_port&amp;quot;: &amp;quot;http://192.168.5.31:8083&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_request&amp;quot;: &amp;quot;/fhem?cmd=&amp;quot;,&lt;br /&gt;
	&amp;quot;different_ROI&amp;quot;: &amp;quot;5&amp;quot;,&lt;br /&gt;
	&amp;quot;path_to_picture&amp;quot;: &amp;quot;./Picture&amp;quot;,&lt;br /&gt;
	&amp;quot;picture&amp;quot;: &amp;quot;picture_kitchen&amp;quot;,&lt;br /&gt;
	&amp;quot;type&amp;quot;: &amp;quot;jpg&amp;quot;,&lt;br /&gt;
	&amp;quot;mask&amp;quot;: &amp;quot;dishwasher&amp;quot;,&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Was ist hier einzustellen?&lt;br /&gt;
* &amp;quot;fhem_host_port&amp;quot;: Adresse des fhem Servers, ebenso wie der Port. (Muss man also anpassen)&lt;br /&gt;
* &amp;quot;fhem_request&amp;quot;: (weiß nicht, wie es heißt), sollte aber so passen&lt;br /&gt;
* &amp;quot;different_ROI&amp;quot;: ist spannend: hier sagt man, wie viele LEDs (ROI = region of interesst) man überwachen will. (für jede ROI muss genau 1 Maske existieren)&lt;br /&gt;
* &amp;quot;path_to_picture&amp;quot;: logisch, wo liegt das Bild? In diesem Fall in einem Unterordner Namens Picture&lt;br /&gt;
* &amp;quot;picture&amp;quot;: der Name des Bildes (aufgemerkt: das Programm geht also immer vom gleichen Dateinamen aus!) (Quellbild)&lt;br /&gt;
* &amp;quot;type&amp;quot;: bitte mit angeben; jpg, png...&lt;br /&gt;
* &amp;quot;mask&amp;quot;: der erste Teil des Maskennamens&lt;br /&gt;
** die Dateiendung nicht angeben, bitte die gleiche wie beim Quellbild verwenden&lt;br /&gt;
** so kann man bei einem Quellbild verschiedene Masken angeben (in verschiedenen Config Dateien)&lt;br /&gt;
** bei Karten vom DWD z.B. kann man so aus einem Quellbild Werte für verschiedene Regionen ermitteln&lt;br /&gt;
** munic.conf, berlin.conf&lt;br /&gt;
** bei mehr Küchengeräten z.B. dishwasher.conf und waterboiler.conf&lt;br /&gt;
&lt;br /&gt;
===Was sind diese Masken?===&lt;br /&gt;
Die sind cool. Einfache schwarz/weiß Bilder.&lt;br /&gt;
&lt;br /&gt;
Zum erstellen:&lt;br /&gt;
Ein Musterbild von der Kamera besorgen. In Gimp öffnen, den Bereich um eine der gewünschten LEDs ein Viereck oder ein Kreis, ist egal) markieren. Löschen, Füllfarbe weiß. Markierung umdrehen, löschen, Füllfarbe schwarz. Fertig.&lt;br /&gt;
&lt;br /&gt;
Stellt euch vor, die Maske wäre aus Tonpapier. Da wo weiß ist, ist ein Loch drin. Die Maske wird über das Bild gelegt. Nun seht ihr nur noch die gewünschte LED...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wichtig:&lt;br /&gt;
&lt;br /&gt;
Die Maske braucht nun einen festen Dateinamen, damit sie gefunden werden kann! Hängt an den in der Config angegebenen Dateinamen ein _mask_1 an, für eure erste Maske. Hättet ihr ROI = 1, ist das alles. Bei ROI = 2 wollen wir 2 Masken abarbeiten.&lt;br /&gt;
&lt;br /&gt;
Also, bei ROI = 3&lt;br /&gt;
* quellbild.jpg (das, was eure Kamera immer generiert, oder euch der DWD zur Verfügung stellt)&lt;br /&gt;
* &amp;lt;AngegebenerName&amp;gt;_mask_1.jpg (die Dateiendung bitte wie beim Quellbild)&lt;br /&gt;
* &amp;lt;AngegebenerName&amp;gt;_mask_2.jpg&lt;br /&gt;
* &amp;lt;AngegebenerName&amp;gt;_mask_3.jpg&lt;br /&gt;
&lt;br /&gt;
===Benötigte Frameworks===&lt;br /&gt;
folgt noch&lt;br /&gt;
&lt;br /&gt;
===Kalibrierung des Sensors===&lt;br /&gt;
&lt;br /&gt;
==Programmcode==&lt;br /&gt;
Der Programmcode ist im ersten Forumsthread mit einigen Beispielen zum Download.&lt;br /&gt;
[http://forum.fhem.de/index.php/topic,39678.msg318865.html#msg318865 Download]&lt;br /&gt;
&lt;br /&gt;
===Sensor===&lt;br /&gt;
Anmerkung:&lt;br /&gt;
&lt;br /&gt;
Ich bin kein Programmierer. Wenn das jemand durchliest der Ahnung hat, sich totlacht =&amp;gt; ich übernehme keine Verantwortung&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
# Optical Sensor&lt;br /&gt;
# using Python 2.7 and OpenCV 2.4.11&lt;br /&gt;
# do not use german umlauts, not even in description&lt;br /&gt;
# ver 0.2 first public release&lt;br /&gt;
import cv2&lt;br /&gt;
import argparse&lt;br /&gt;
import json&lt;br /&gt;
import urllib&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
#cv2 importiert OpenCV&lt;br /&gt;
#argparse wird benoetigt fuer die Parameteruebergabe&lt;br /&gt;
#json zum lesen des Config-Files&lt;br /&gt;
#urllib um uns mit fhem zu unterhalten&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# construct the argument parse and parse the arguments&lt;br /&gt;
ap = argparse.ArgumentParser()&lt;br /&gt;
ap.add_argument(&amp;quot;-c&amp;quot;, &amp;quot;--conf&amp;quot;, required=True,&lt;br /&gt;
	help=&amp;quot;path to the JSON configuration file; eg try: &amp;gt;sensor.py --conf dishwasher.json&amp;quot;)&lt;br /&gt;
args = vars(ap.parse_args())&lt;br /&gt;
&lt;br /&gt;
#ConfigFile laden&lt;br /&gt;
conf = json.load(open(args[&amp;quot;conf&amp;quot;]))&lt;br /&gt;
client = None&lt;br /&gt;
&lt;br /&gt;
#Gespeichertes Bild mit Pfad in Variable&lt;br /&gt;
path = (conf[&amp;quot;path_to_picture&amp;quot;])&lt;br /&gt;
picture = (conf[&amp;quot;picture&amp;quot;])&lt;br /&gt;
type = (conf[&amp;quot;type&amp;quot;])&lt;br /&gt;
first_picture = path + &amp;quot;/&amp;quot; + picture + &amp;quot;.&amp;quot; + type&lt;br /&gt;
&lt;br /&gt;
#Namen der Maske auslesen&lt;br /&gt;
first_mask = (conf[&amp;quot;mask&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
#Laden des Bildes&lt;br /&gt;
image = cv2.imread(first_picture)&lt;br /&gt;
&lt;br /&gt;
# Bild anzeigen&lt;br /&gt;
#cv2.imshow(&amp;quot;Originalbild&amp;quot;, image)&lt;br /&gt;
&lt;br /&gt;
# Schleife erzeugen&lt;br /&gt;
ROI = int(conf[&amp;quot;different_ROI&amp;quot;])&lt;br /&gt;
&lt;br /&gt;
print &amp;quot;Soll-Durchlaeufe &amp;quot; + str(ROI)&lt;br /&gt;
&lt;br /&gt;
i = 0&lt;br /&gt;
while i &amp;lt; ROI:&lt;br /&gt;
	i = i + 1&lt;br /&gt;
	&lt;br /&gt;
	# Maskenpfad und Dateinamen generieren&lt;br /&gt;
	mask = path + &amp;quot;/&amp;quot; + first_mask + &amp;quot;_mask_&amp;quot; + str(i) + &amp;quot;.&amp;quot; + type&lt;br /&gt;
	&lt;br /&gt;
	# Maske laden&lt;br /&gt;
	mask = cv2.imread(mask,0)&lt;br /&gt;
	&lt;br /&gt;
	# Maske anwenden&lt;br /&gt;
	masked = cv2.bitwise_and(image, image, mask = mask)&lt;br /&gt;
	#cv2.imshow(&amp;quot;Maske&amp;quot;, masked)&lt;br /&gt;
	&lt;br /&gt;
	# BGR in HSV konvertieren wenn gewollt&lt;br /&gt;
	if conf[&amp;quot;hsv&amp;quot;]: &lt;br /&gt;
		masked = cv2.cvtColor(masked, cv2.COLOR_BGR2HSV)&lt;br /&gt;
		#cv2.imshow(&amp;quot;HSV&amp;quot;, masked)&lt;br /&gt;
	&lt;br /&gt;
	# Grenzwerte aus Config auslesen&lt;br /&gt;
	lower_col_value = tuple(conf[&amp;quot;lower_col&amp;quot; + &amp;quot;_&amp;quot; + str(i)])&lt;br /&gt;
	upper_col_value = tuple(conf[&amp;quot;upper_col&amp;quot; + &amp;quot;_&amp;quot; + str(i)])&lt;br /&gt;
	#print lower_col&lt;br /&gt;
	#print upper_col&lt;br /&gt;
	&lt;br /&gt;
	# Range definieren&lt;br /&gt;
	lower_col = np.array([(lower_col_value)], dtype=np.uint8)&lt;br /&gt;
	upper_col = np.array([(upper_col_value)], dtype=np.uint8)&lt;br /&gt;
&lt;br /&gt;
	# Threshold the image to get only selected colors&lt;br /&gt;
	mask = cv2.inRange(masked, lower_col, upper_col)&lt;br /&gt;
	#cv2.imshow(&amp;quot;Maske&amp;quot;, mask)&lt;br /&gt;
&lt;br /&gt;
	# Pixel zaehlen&lt;br /&gt;
	white = cv2.countNonZero(mask)&lt;br /&gt;
	print(&#039;The number of positive pixels is: &#039; + str(white))&lt;br /&gt;
	&lt;br /&gt;
	# Pixelanzahl an fhem senden&lt;br /&gt;
	# fhem Kommando erzeugen&lt;br /&gt;
	url = (conf[&amp;quot;fhem_host_port&amp;quot;])&lt;br /&gt;
	request = (conf[&amp;quot;fhem_request&amp;quot;])&lt;br /&gt;
	command = (conf[&amp;quot;fhem_command&amp;quot; + &amp;quot;_&amp;quot; + str(i)])&lt;br /&gt;
	value =  &amp;quot;%20&amp;quot; + str(white)&lt;br /&gt;
	fhem = url + request + command + value&lt;br /&gt;
	#print fhem&lt;br /&gt;
	urllib.urlopen(fhem)&lt;br /&gt;
	&lt;br /&gt;
	#cv2.waitKey(0)&lt;br /&gt;
	&lt;br /&gt;
print &amp;quot;Fertig&amp;quot;	&lt;br /&gt;
#cv2.waitKey(0)&lt;br /&gt;
cv2.destroyAllWindows()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Config-File===&lt;br /&gt;
So kann ein Config File aussehen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
5seenland.json (könnte ein guter Dateinname sein...)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;config_version&amp;quot;: &amp;quot;0.2&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_host_port&amp;quot;: &amp;quot;http://192.168.5.31:8083&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_request&amp;quot;: &amp;quot;/fhem?cmd=&amp;quot;,&lt;br /&gt;
	&amp;quot;different_ROI&amp;quot;: &amp;quot;8&amp;quot;,&lt;br /&gt;
	&amp;quot;path_to_picture&amp;quot;: &amp;quot;./Picture&amp;quot;,&lt;br /&gt;
	&amp;quot;picture&amp;quot;: &amp;quot;bodenfeuchte&amp;quot;,&lt;br /&gt;
	&amp;quot;type&amp;quot;: &amp;quot;png&amp;quot;,&lt;br /&gt;
	&amp;quot;mask&amp;quot;: &amp;quot;5seenland&amp;quot;,&lt;br /&gt;
	&amp;quot;hsv&amp;quot;: false,&lt;br /&gt;
	&amp;quot;lower_col_1&amp;quot;: [45,100,200],&lt;br /&gt;
	&amp;quot;upper_col_1&amp;quot;: [45,100,200],&lt;br /&gt;
	&amp;quot;lower_col_2&amp;quot;: [60,200,250],&lt;br /&gt;
	&amp;quot;upper_col_2&amp;quot;: [60,200,250],&lt;br /&gt;
	&amp;quot;lower_col_3&amp;quot;: [75,250,250],&lt;br /&gt;
	&amp;quot;upper_col_3&amp;quot;: [75,250,250],&lt;br /&gt;
	&amp;quot;lower_col_4&amp;quot;: [75,250,200],&lt;br /&gt;
	&amp;quot;upper_col_4&amp;quot;: [75,250,200],&lt;br /&gt;
	&amp;quot;lower_col_5&amp;quot;: [75,220,150],&lt;br /&gt;
	&amp;quot;upper_col_5&amp;quot;: [75,220,150],&lt;br /&gt;
	&amp;quot;lower_col_6&amp;quot;: [75,150,75],&lt;br /&gt;
	&amp;quot;upper_col_6&amp;quot;: [75,150,75],&lt;br /&gt;
	&amp;quot;lower_col_7&amp;quot;: [250,200,50],&lt;br /&gt;
	&amp;quot;upper_col_7&amp;quot;: [250,200,50],&lt;br /&gt;
	&amp;quot;lower_col_8&amp;quot;: [250,0,0],&lt;br /&gt;
	&amp;quot;upper_col_8&amp;quot;: [250,0,0],&lt;br /&gt;
	&amp;quot;fhem_command_1&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%200-10&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_2&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2010-30&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_3&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2030-50&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_4&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2050-80&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_5&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2080-95&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_6&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%2095-100&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_7&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%20100-105&amp;quot;,&lt;br /&gt;
	&amp;quot;fhem_command_8&amp;quot;: &amp;quot;setreading%20Bodenfeuchte%20105-&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Eigentlich ganz einfach. Für jede ROI benötigt man lower_col_?, upper_col_? und fhem_command_?&lt;br /&gt;
&lt;br /&gt;
Die  lower/upper cols definieren für jede ROI den zu suchenden Farbbereich... das Ergebnis wird dann an den fhem_command_? angehängt.&lt;br /&gt;
&lt;br /&gt;
Hat man nur 2 ROI, kann man die Werte 4-8 natürlich rauswerfen; andernfalls werden sie schlicht ignoriert, tun also auch nicht weh. Sind nur eben sinnbefreit.&lt;br /&gt;
&lt;br /&gt;
===Beispiel mit Bildern===&lt;br /&gt;
Ist denke ich im Forumsthread schon ganz schön beschrieben.&lt;br /&gt;
&lt;br /&gt;
Wer eigene Beispiele hat, immer her damit :)&lt;/div&gt;</summary>
		<author><name>Rince</name></author>
	</entry>
</feed>