<?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=Kaihs</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=Kaihs"/>
	<link rel="alternate" type="text/html" href="http://wiki.fhem.de/wiki/Spezial:Beitr%C3%A4ge/Kaihs"/>
	<updated>2026-04-10T00:49:42Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.43.6</generator>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=HM-WDS10-TH-O_Funk-Temperatur-/Feuchtesensor_au%C3%9Fen_(OTH)&amp;diff=38926</id>
		<title>HM-WDS10-TH-O Funk-Temperatur-/Feuchtesensor außen (OTH)</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=HM-WDS10-TH-O_Funk-Temperatur-/Feuchtesensor_au%C3%9Fen_(OTH)&amp;diff=38926"/>
		<updated>2024-01-14T17:04:52Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: Links aktualisiert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Hardware&lt;br /&gt;
|Bild=PlatzHalter.png&lt;br /&gt;
|Bildbeschreibung=Bild und Daten müssen noch ergänzt werden&lt;br /&gt;
|HWProtocol=[[HomeMatic]]&lt;br /&gt;
|HWType=[[HomeMatic Type THSensor|THSensor]]&lt;br /&gt;
|HWCategory=[[:Kategorie:Temperatursensoren|Temperatursensoren]] [[:Kategorie:Feuchtesensoren|Feuchtesensoren]]&lt;br /&gt;
|HWComm=868,3 MHz&lt;br /&gt;
|HWChannels=&lt;br /&gt;
|HWVoltage=3 V&lt;br /&gt;
|HWPowerConsumption=max. 100 mA&lt;br /&gt;
|HWPoweredBy=2x LR6/Mignon/AA&lt;br /&gt;
|HWSize=54x135x73 mm (BxHxT)&lt;br /&gt;
|HWDeviceFHEM=[[CUL_HM]]&lt;br /&gt;
&amp;lt;!-- |ModOwner=  --&amp;gt;&lt;br /&gt;
|HWManufacturer=[http://www.elv.de ELV] / [http://www.eq-3.de eQ-3]&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;HM-WDS10-TH-O Funk-Temperatur-/Feuchtesensor außen (OTH)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Homematic Außensensor für Temperatur und relative Luftfeuchte.&lt;br /&gt;
== Features ==&lt;br /&gt;
* Batteriebetrieb (2 x AA)&lt;br /&gt;
* Möglichkeit der Wandmontage&lt;br /&gt;
* Eignung für Temp. von -19,9 °C bis +79,9 °C&lt;br /&gt;
* Datenübermittlung alle 120 bis 180 Sekunden&lt;br /&gt;
* Übermittlung des Batteriestatus&lt;br /&gt;
== Hinweise zum Betrieb mit FHEM ==&lt;br /&gt;
Das Handling des Gerätes ist identisch mit der entsprechenden [[HM-WDS40-TH-I Funk-Temperatur-/Feuchtesensor innen (IT)|Innensensor]]-Version.&lt;br /&gt;
== Variablen ==&lt;br /&gt;
Das Handling des Gerätes ist identisch mit der entsprechenden [[HM-WDS40-TH-I Funk-Temperatur-/Feuchtesensor innen (IT)|Innensensor]]-Version.&lt;br /&gt;
== Bekannte Probleme ==&lt;br /&gt;
* {{Link2Forum|Area= |Topic=10445|Message= |LinkText=FHEM:Temperaturwerte mit HM-WDS10-TH-O}}&lt;br /&gt;
* [http://www.elv.de/homematic-hm-wds10-th-o-funk-temperatur-luftfeuchtesensor-oth.html www.elv.de] unter &#039;&#039;Bewertungen&#039;&#039;, 2 Sterne =&amp;amp;gt; Kontakt zur Technik erwünscht.&lt;br /&gt;
* Bei schwachen Batterien (reading &amp;quot;battery&amp;quot; = &amp;quot;low&amp;quot;) werden z.T. völlig falsche Werte geliefert.&lt;br /&gt;
&lt;br /&gt;
Bessere Batterien &#039;&#039;können&#039;&#039; evtl. helfen:&lt;br /&gt;
* [http://homematic-forum.de/forum/viewtopic.php?f=27&amp;amp;amp;t=8230 homematic-forum]&lt;br /&gt;
* [http://www.ip-symcon.de/forum/threads/17198-HM-WDS10-TH-O-Temperatur-Sensor-h%C3%A4ngt-ab-8-grad www.ip-symcon.de]&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [https://www.eq-3.de/downloads/download/homematic/bda/hm-wds10-th-o_um_ge_eq-3_web.pdf Montage und Bedienungsanleitung] (PDF)&lt;br /&gt;
* [https://www.eq-3.de/downloads/download/homematic/pdb/funk-temperatur-luftfeuchtesensor-auen_76923_produktdatenblatt_v32.pdf Produktdatenblatt] (PDF)&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HomeMatic Components]]&lt;br /&gt;
[[Kategorie:Feuchtesensoren]]&lt;br /&gt;
[[Kategorie:Temperatursensoren]]&lt;br /&gt;
[[Kategorie:868MHz]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=WMBUS&amp;diff=36193</id>
		<title>WMBUS</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=WMBUS&amp;diff=36193"/>
		<updated>2021-11-10T19:19:27Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: /* Links */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=Dekodierung von Wireless M-Bus Nachrichten&lt;br /&gt;
|ModType=d&lt;br /&gt;
|ModForumArea=Sonstige Systeme&lt;br /&gt;
|ModTechName=36_WMBUS.pm&lt;br /&gt;
|ModOwner=kaihs&lt;br /&gt;
}}&lt;br /&gt;
[[WMBUS]] ist ein Modul zur Dekodierung von Wireless M-Bus Nachrichten. Solche Nachrichten werden z. B. von Zählern für Wasser, Wärme, Gas und Elektrizität ausgestrahlt.&lt;br /&gt;
Wireless M-Bus ist ein Standardprotokoll das von unterschiedlichen Herstellern unterstützt wird.&lt;br /&gt;
Das Protokoll unterstützt unterschiedliche Kodierungen des Funksignals, im wesentlichen den S-Mode, T-Mode und C-Mode. Der Empfänger (z. B. ein CUL) muss den selben Modus nutzen wie der Sender (der Zähler). &lt;br /&gt;
Wireless M-Bus unterstützt optional die Verschlüsselung der Daten.&lt;br /&gt;
Die von einem Zähler gesendeten Daten können sehr unterschiedlich sein und hängen u. a. vom Zählertyp und dessen Hersteller ab.&lt;br /&gt;
&lt;br /&gt;
== Voraussetzungen ==&lt;br /&gt;
Das Modul interpretiert nur die Nachrichten die von einen geeigneten Empfänger empfangen werden. Aktuell kann ein [[CUL]] und verwandte Geräte die die culfw[http://culfw.de/culfw.html] verwenden sowie ein Amber Wireless AMB8465M dafür verwendet werden. In der culfw muss die Unterstützung des WMBUS-Protokolls aktiviert sein (#define HAS_MBUS in der Datei board.h des Deviceverzeichnisses). Bei einem CUL mit der Hardwareversion V4 ist das nicht der Fall.&lt;br /&gt;
&lt;br /&gt;
Der CUL muss in FHEM mittels Attribut rfmode=WMBus_S, WMBus_T oder WMBus_C in den zum Zähler passenden Empfangsmodus versetzt werden.&lt;br /&gt;
&lt;br /&gt;
== Anwendung ==&lt;br /&gt;
Die Erzeugung des passenden Devices in FHEM geschieht automatisch beim Empfang des ersten Datenpakets eines Zählers. Voraussetzung dafür ist, dass [[autocreate]] aktiv ist.&lt;br /&gt;
Alternativ kann ein Device manuell angelegt werden. Dazu wird der Hersteller, die Seriennummer, die Version und der Typ (Wasser, Gas, ...) des Zählers benötigt.&lt;br /&gt;
Sind die Daten verschlüsselt wird auch noch der passende Schlüssel benötigt um die Daten entschlüsseln zu können.&lt;br /&gt;
&lt;br /&gt;
== Verschlüsselung ==&lt;br /&gt;
Die Daten können auf drei verschiedene Arten verschlüsselt sein:&lt;br /&gt;
# Security profile A/Symmetric encryption with Mode 5&lt;br /&gt;
# Security profile B/Advanced symmetric encryption with Mode 7&lt;br /&gt;
# Security profile C/Asymmetric encryption with Mode 13&lt;br /&gt;
&lt;br /&gt;
Das Modul unterstützt aktuell Daten die per 1 oder 2 verschlüsselt wurden.&lt;br /&gt;
&lt;br /&gt;
== Anwendungsbeispiele ==&lt;br /&gt;
Ein per [[EnergyCam]] abgelesener Elektrizitätszähler sieht in FHEM z. B. so aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 Internals: &lt;br /&gt;
   CUL_MBUS_MSGCNT 29 &lt;br /&gt;
   CUL_MBUS_RAWMSG b1944C4189985051701028A7D7A540000A00405FAD4080002FD08222C1295B8::-67.5 &lt;br /&gt;
   CUL_MBUS_RSSI -67.5 &lt;br /&gt;
   CUL_MBUS_TIME 2014-10-24 22:57:53 &lt;br /&gt;
   DEF        FFD 17058599 1 2 &lt;br /&gt;
   DeviceMedium Electricity &lt;br /&gt;
   DeviceType 2 &lt;br /&gt;
   IODev      CUL_MBUS &lt;br /&gt;
   IdentNumber 17058599 &lt;br /&gt;
   LASTInputDev CUL_MBUS &lt;br /&gt;
   MSGCNT     29 &lt;br /&gt;
   Manufacturer FFD &lt;br /&gt;
   NAME       WMBUS_FFD_17058599_1_2 &lt;br /&gt;
   NR         49 &lt;br /&gt;
   STATE      no errors &lt;br /&gt;
   TYPE       WMBUS &lt;br /&gt;
   Version    1 &lt;br /&gt;
   addr       FFD_17058599_1_2 &lt;br /&gt;
   Readings: &lt;br /&gt;
     2014-10-24 22:57:53   1_storage_no    0 &lt;br /&gt;
     2014-10-24 22:57:53   1_type          VIF_ENERGY_WATT &lt;br /&gt;
     2014-10-24 22:57:53   1_unit          Wh &lt;br /&gt;
     2014-10-24 22:57:53   1_value         57881000 &lt;br /&gt;
     2014-10-24 22:57:53   2_storage_no    0 &lt;br /&gt;
     2014-10-24 22:57:53   2_type          VIF_ACCESS_NO &lt;br /&gt;
     2014-10-24 22:57:53   2_unit &lt;br /&gt;
     2014-10-24 22:57:53   2_value         11298 &lt;br /&gt;
     2014-10-24 22:57:53   LQI             184 &lt;br /&gt;
     2014-10-24 22:57:53   RSSI            -67.5 &lt;br /&gt;
     2014-10-24 22:57:53   battery         ok &lt;br /&gt;
     2014-10-24 22:57:53   decryption_ok   1 &lt;br /&gt;
     2014-10-24 22:57:53   energy          57881 &lt;br /&gt;
     2014-10-24 22:57:53   is_encrypted    0 &lt;br /&gt;
     2014-10-24 22:57:53   state           no errors &lt;br /&gt;
     2014-10-24 22:57:53   unit            kWh &lt;br /&gt;
 Attributes: &lt;br /&gt;
   IODev      CUL_MBUS &lt;br /&gt;
   room       WMBUS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Bekannte Probleme ==&lt;br /&gt;
=== Inkompatible Zähler ===&lt;br /&gt;
Obwohl Wireless M-Bus ein standardisiertes Protokoll ist, scheint sich kaum ein Hersteller vollständig daran zu halten bzw. verwendet sog. herstellerspezifische Felder um wichtige Daten zu verpacken.&lt;br /&gt;
Aus den bisher beobachteten Datenpaketen ergibt sich &lt;br /&gt;
* Qundis (Herstellerkürzel LSE) verwendet herstellerspezifische Datenblöcke für den eigentlichen Zählerstand&lt;br /&gt;
* Techem und Hydrometer verwenden ein undokumentiertes Datenformat (CI-Field A2)&lt;br /&gt;
:&#039;&#039;(Techem Heizkostenverteiler (CI-Field A0) können über das Modul [[TechemHKV]] ausgewertet werden)&#039;&#039;&lt;br /&gt;
* RWE SmartHome Powercontrol[http://www.rwe-smarthome.de/web/cms/de/1776202/smarthome/informieren/geraete/power-control/] sendet verschlüsselt und der Hersteller gibt nicht den vollständigen Schlüssel an ({{Link2Forum|Topic=24517|Message=315949}})&lt;br /&gt;
&lt;br /&gt;
Daher werden bisher erst die [[EnergyCam]] der Firma Q-loud, Zähler von Easymeter und der Kamstrup Multical 21 vollständig unterstützt.&lt;br /&gt;
Für den Multical 21 muss eine culfw mit Unterstützung für WMBUS C verwendet werden. Diese ist in der culfw ab dem 24.6.2018 enthalten.&lt;br /&gt;
&lt;br /&gt;
Andere Zähler können auch ohne Probleme funktionieren wenn diese sich an den OMS Standard halten.&lt;br /&gt;
&lt;br /&gt;
=== Empfangsprobleme ===&lt;br /&gt;
Der Empfänger (meist ein [[CUL]]) muss das WMBUS Protokoll unterstützen. Die Unterstützung ist vorhanden, wenn in der Ausgabe von &amp;lt;code&amp;gt;get cmds&amp;lt;/code&amp;gt; ein kleines [http://culfw.de/commandref.html#cmd_b b] enthalten ist.&lt;br /&gt;
Der CUL speichert die empfangenen Daten intern zwischen bevor sie an fhem geschickt werden. Der Puffer für die Speicherung muss groß genug sein, um ein komplettes Datenpaket aufzunehmen. Die Größe des Puffers kann in der culfw eingestellt werden in dem das define TTY_BUFSIZE in der Datei [https://sourceforge.net/p/culfw/code/HEAD/tree/trunk/culfw/Devices/nanoCUL/board.h board.h] des passenden Devices angepasst wird.&lt;br /&gt;
Dabei ist darauf zu achten, dass die verwendeten Mikrocontroller nur sehr wenig RAM haben (0,5-4KB). Um mehr freies RAM zu erhalten sollten Protokolle die nicht benötigt in der board.h abgeschaltet werden. Die Unterstützung für WMBUS (#define HAS_MBUS 1) muss aber natürlich eingeschaltet werden.  &lt;br /&gt;
Anschließend ist die culfw [[Selbstbau_CUL#Software|neu zu übersetzen und zu flashen]].&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Forumsthread {{Link2Forum|Topic=24517}}&lt;br /&gt;
* Protokoll Beschreibung [https://oms-group.org/open-metering-system/oms-spezifikation]&lt;br /&gt;
* Beschreibung des M-BUS Protokolls [https://m-bus.com/documentation]&lt;br /&gt;
[[Kategorie:Energieverbrauchsmessung]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FHEM_mit_HTTPS_SSL-Zertifikat_und_eine_eigene_Zertifizierungsstelle&amp;diff=35678</id>
		<title>FHEM mit HTTPS SSL-Zertifikat und eine eigene Zertifizierungsstelle</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FHEM_mit_HTTPS_SSL-Zertifikat_und_eine_eigene_Zertifizierungsstelle&amp;diff=35678"/>
		<updated>2021-05-08T21:59:28Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: nicht mehr funktionierenden Link ersetzt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Vorwort ==&lt;br /&gt;
=== Dein Anliegen ===&lt;br /&gt;
Du möchtest FHEM mit HTTPS betreiben, hasst es aber, ständig von Deinem Browser darauf aufmerksam gemacht zu werden, dass dies &amp;quot;keine sichere Verbindung&amp;quot; ist. &lt;br /&gt;
Oder Du möchtest einen weiteren Serverdienst aufsetzen, welcher verschlüsselte SSL oder TLS-Verbindungen anbietet (z.B. HTTPS, POP3S, IMAPS, LDAPS, SMTP mit TLS).&lt;br /&gt;
&lt;br /&gt;
=== Die Schwierigkeit dabei ===&lt;br /&gt;
Um eine mit SSL/TLS abgesicherte Verbindung anzubieten, benötigst Du ein Serverzertifikat. Dieses muss von einer Zertifizierungsstelle (Certification Authority oder kurz CA) signiert sein.&lt;br /&gt;
Ein offizielles Serverzertifikat, welches von einer offiziellen Stelle signiert ist, ist leider nicht kostenlos. Meist werden jährliche Gebühren in Höhe von mehreren hundert Euro fällig.&lt;br /&gt;
&lt;br /&gt;
=== Eine mögliche Lösung ===&lt;br /&gt;
Unter Linux kann man mit Bordmitteln eine eigene CA aufsetzen und selbst ein Zertifikate erstellen und signieren. Das ist ein Vorgang von wenigen Minuten. Alle Einzelheiten beschreibt dieser Artikel.&lt;br /&gt;
Der einzige Unterschied zu einem von einer anerkannten Stelle signierten Zertifikat ist, dass der Client (Emailprogramm, Browser, etc.) einmalig das root CA importieren muß.&lt;br /&gt;
&lt;br /&gt;
== Genaues Vorgehen ==&lt;br /&gt;
=== OpenSSL installieren ===&lt;br /&gt;
Für die Verwaltung der Zertifikate und im übrigen auch für die Verschlüsselung der Verbindungen mit SSL und TLS kommt unter Linux fast immer OpenSSL zum Einsatz. Wahrscheinlich ist das auf Deinem Sytem deshalb bereits installiert, wenn nicht, musst Du das Paket openssl nachinstallieren. Du benötigst aus diesem Paket den Kommandozeilenbefehl openssl.&lt;br /&gt;
&lt;br /&gt;
=== Erstellen der CA ===&lt;br /&gt;
Lege zunächst ein Verzeichnis an, in dem Du das Zertifikat ablegen willst. Wir nehmen in unserem Beispiel /root/ca:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
root@linux# mkdir /root/ca&lt;br /&gt;
root@linux# cd /root/ca&amp;lt;/source&amp;gt;&lt;br /&gt;
Die Gültigkeit setzen wir mit 10 Jahren bewusst sehr hoch an. Läuft die CA aus, so werden nämlich auch alle damit signierten Serverzertifikate ungültig. Die CA enthält einen geheimen Schlüssel, welcher automatisch erzeugt und in der Datei cakey.pem abgelegt wird. Das CA-Zertifikat wird nach cacert.pem geschrieben. Der folgende Befehl erzeugt das einen Schlüssel für das Zertifikat mit einer Länge von 2048 Bit:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
root@linux# openssl req -new -x509 -newkey rsa:2048 -keyout cakey.pem -out cacert.pem -days 3650&lt;br /&gt;
Generating a 2048 bit RSA private key&lt;br /&gt;
..............................................................&lt;br /&gt;
..............................................................&lt;br /&gt;
.........................................+++&lt;br /&gt;
......................................+++&lt;br /&gt;
writing new private key to &#039;cakey.pem&#039;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wer den geheimen Schlüssel der CA kennt, kann damit beliebige Serverzertifikate signieren. Deshalb wird diese Schlüsseldatei nicht im Klartext auf der Festplatte abgelegt, sondern mit einer Passphrase verschlüsselt. Diese Passphrase benötigst Du immer dann, wenn Du mit der CA neue Zertifikate ausstellen willst:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
Enter PEM pass phrase: sehrlangesgeheimespasswort&lt;br /&gt;
Verifying - Enter PEM pass phrase: sehrlangesgeheimespasswort&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Nun werden wir gebeten, Daten einzugeben, welche die CA identifizieren. Diese werden dem Client angezeigt, wenn er aufgefordert wird, das Zertifikat zu akzeptieren oder abzulehnen. Der Code für Deutschland ist DE. Wenn Du ein Feld leer lassen möchtest, so gib einen Punkt ein. Ansonsten wird der in eckigen Klammern stehende Defaultwert eingetragen:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
-----&lt;br /&gt;
You are about to be asked to enter information that will be incorporated&lt;br /&gt;
into your certificate request.&lt;br /&gt;
What you are about to enter is what is called a Distinguished Name or a DN.&lt;br /&gt;
There are quite a few fields but you can leave some blank&lt;br /&gt;
For some fields there will be a default value,&lt;br /&gt;
If you enter &#039;.&#039;, the field will be left blank.&lt;br /&gt;
-----&lt;br /&gt;
Country Name (2 letter code) [AU]: DE&lt;br /&gt;
State or Province Name (full name) [Some-State]:Brandenburg&lt;br /&gt;
Locality Name (eg, city) []:Potsdam&lt;br /&gt;
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Familie AG&lt;br /&gt;
Organizational Unit Name (eg, section) []:EDV&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Das Feld Common Name (CN) ist hier der offizielle Name der Zertifizierungsstelle. Für Dein eigenes CA kannst Du einfach Deinen eigenen Namen eintragen:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
Common Name (eg, YOUR name) []: Cool Tux&lt;br /&gt;
Email Address []: cooltux@gmail.tada&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Fertig. Folgende zwei Dateien sind entstanden:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
root@linux# ll&lt;br /&gt;
insgesamt 9&lt;br /&gt;
drwxr-xr-x   2 root root  112 2006-04-30 12:08 .&lt;br /&gt;
drwx------  12 root root  600 2006-04-30 11:54 ..&lt;br /&gt;
-rw-r--r--   1 root root 1212 2006-04-30 12:08 cacert.pem&lt;br /&gt;
-rw-r--r--   1 root root  963 2006-04-30 12:08 cakey.pem&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Vorsichtshalber solltest Du die Rechte so setzen, dass die Schlüsseldatei nur für root lesbar ist:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
root@linux# chmod 600 cakey.pem&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Du kannst nun ausprobieren, ob Du den Schlüssel mit der Passphrase wieder öffnen kannst:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
root@linux# openssl rsa -in cakey.pem -noout -text&lt;br /&gt;
Enter pass phrase for cakey.pem: wrzlprmpft&lt;br /&gt;
Private-Key: (1024 bit)&lt;br /&gt;
modulus:&lt;br /&gt;
    00:d5:a5:37:51:e9:d9:fa:e3:97:e7:46:b2:88:1a:&lt;br /&gt;
    b5:46:80:47:76:14:ae:2b:8b:3e:35:5c:ab:15:84:&lt;br /&gt;
    53:d9:63:2e:7f:08:4b:ec:77:db:02:45:f8:c7:46:&lt;br /&gt;
    58:cd:2d:f9:29:4d:96:3d:d8:6c:5d:9f:79:8a:04:&lt;br /&gt;
    cf:b7:3a:89:da:a9:63:9f:44:b3:83:cf:0d:70:7d:&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
usw...&lt;br /&gt;
&lt;br /&gt;
=== Schlüssel für das Serverzertifikat erzeugen ===&lt;br /&gt;
Nachdem wir nun eine eigene CA haben, kann diese nun endlich für unseren Server ein Zertifikat herausgeben. Dazu erzeugen wir zunächst einen 2048 Bit langen RSA Schlüssel, der mit AES 128 verschlüsselt auf der Platte abgelegt wird (ja wirklich, auch hier wieder ein verschlüsselter Schlüssel). Die Passphrase muss diesmal nicht sonderlich geheim sein, da wir sie ohnehin im Anschluss wieder entfernen werden. OpenSSL lässt allerdings keine leere Phrase zu:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
root@linux# openssl genrsa -out serverkey.pem -aes128 2048&lt;br /&gt;
Generating RSA private key, 2048 bit long modulus&lt;br /&gt;
....+++&lt;br /&gt;
.......................................+++&lt;br /&gt;
e is 65537 (0x10001)&lt;br /&gt;
Enter pass phrase for serverkey.pem: test&lt;br /&gt;
Verifying - Enter pass phrase for serverkey.pem: test&amp;lt;/source&amp;gt;&lt;br /&gt;
So. Nun entfernen wir die Passphrase wieder. Warum? Der Serverdienst (Apache, Cyrus, etc.) muss schließlich in der Lage sein, den Schlüssel ohne Dein Zutun zu lesen. Oder möchtest Du bei jedem Booten des Servers ein Passwort eingeben müssen?&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
root@linux# openssl rsa -in serverkey.pem -out serverkey.pem&lt;br /&gt;
Enter pass phrase for serverkey.pem: jaja&lt;br /&gt;
writing RSA key&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Certificate Signing Request erzeugen ===&lt;br /&gt;
Der nächste Schritt zum eigenen Zertifikat ist ein CSR. Dies muss dann nur noch von der CA signiert werden. Hier sind wieder Angaben analog zum Erstellen der CA nötig, was oft Verwirrung stiftet. Die allgemeinen Daten kann man ggfl. gleich wie oben eingeben:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
root@linux#  openssl req -new -key serverkey.pem -out req.pem -nodes&lt;br /&gt;
You are about to be asked to enter information that will be incorporated&lt;br /&gt;
into your certificate request.&lt;br /&gt;
What you are about to enter is what is called a Distinguished Name or a DN.&lt;br /&gt;
There are quite a few fields but you can leave some blank&lt;br /&gt;
For some fields there will be a default value,&lt;br /&gt;
If you enter &#039;.&#039;, the field will be left blank.&lt;br /&gt;
-----&lt;br /&gt;
Country Name (2 letter code) [AU]: DE&lt;br /&gt;
State or Province Name (full name) [Some-State]:Brandenburg&lt;br /&gt;
Locality Name (eg, city) []:Potsdam&lt;br /&gt;
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Familie AG&lt;br /&gt;
Organizational Unit Name (eg, section) []:EDV&amp;lt;/source&amp;gt;&lt;br /&gt;
ACHTUNG, jetzt kommt das Wichtige: Beim Serverzertifikat ist der Common Name von entscheidender Bedeutung. Hier muss der DNS-Name stehen, unter dem der Client den Server anspricht! Wird das Zertifikat für eine HTTPS-Verbindung zu fhem.local verwendet, so muss der Common Name eben genau fhem.local heißen. Anderfalls wird der Browser das Zertifikat nicht akzeptieren, da er davon ausgehen muss, auf dem falschen Server gelandet zu sein.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
Common Name (eg, YOUR name) []: fhem.local&lt;br /&gt;
Email Address []: admin.fhem.local&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Weitere Optionen kann man einfach leer lassen:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
A challenge password []:&lt;br /&gt;
An optional company name []:&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Mittlerweile tummeln sich schon vier Dateien in unserem Verzeichnis:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
root@linux# ll&lt;br /&gt;
insgesamt 17&lt;br /&gt;
drwxr-xr-x   2 root root  168 2006-04-30 12:29 .&lt;br /&gt;
drwx------  12 root root  600 2006-04-30 11:54 ..&lt;br /&gt;
-rw-r--r--   1 root root 1212 2006-04-30 12:08 cacert.pem&lt;br /&gt;
-rw-------   1 root root  963 2006-04-30 12:08 cakey.pem&lt;br /&gt;
-rw-r--r--   1 root root 1017 2006-04-30 12:29 req.pem&lt;br /&gt;
-rw-r--r--   1 root root 1679 2006-04-30 12:21 serverkey.pem&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== OpenSSL-Konfiguration anpassen ===&lt;br /&gt;
Leider kann man bei OpenSSL nicht alle Daten als Kommandozeilenargumente übergeben. Einige Einstellungen muss man lästigerweise in der Datei /etc/ssl/openssl.cnf ändern, bevor man signieren kann. Öffne diese Datei und passe folgende Zeilen in der Sektion [ CA_default ] an:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
/etc/ssl/openssl.cnf:&lt;br /&gt;
dir             = .              # Where everything is kept&lt;br /&gt;
new_certs_dir   = $dir           # default place for new certs&lt;br /&gt;
private_key     = $dir/cakey.pem # The private key&lt;br /&gt;
RANDFILE        = $dir/.rand     # private random number file&lt;br /&gt;
default_days    = 3650           # how long to certify for&amp;lt;/source&amp;gt;&lt;br /&gt;
Das Feld default_days ist auf 365 Tage voreingestellt und gibt die Gültigkeit des Zertifikates an. Abgelaufene Zertifikate sind im Übrigen ein sehr häufiges Problem. Wenn es soweit ist, kennt sich damit nämlich schon lange keiner mehr aus. Deswegen kannst Du wie im Beispiel angegeben die Lebensdauer z.B. auf 10 Jahre heraufsetzen.&lt;br /&gt;
&lt;br /&gt;
Nun muss man noch einige Dateien anlegen:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
root@linux# echo 01 &amp;gt; serial&lt;br /&gt;
root@linux# touch index.txt&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Serverzertifikat signieren ===&lt;br /&gt;
Kommen wir zum feierlichen Abschluss: Unsere CA signiert nun das Zertifikat:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
root@linux# openssl ca -in req.pem -notext -out servercert.pem&lt;br /&gt;
Enter pass phrase for ./cakey.pem: langesgeheimespasswort&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
Certificate is to be certified until Apr 27 10:45:36 2016 GMT (3650 days)&lt;br /&gt;
Sign the certificate? [y/n]: y&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
1 out of 1 certificate requests certified, commit? [y/n] y&lt;br /&gt;
Write out database with 1 new entries&lt;br /&gt;
Data Base Updated&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Zertifikate installieren ===&lt;br /&gt;
Wie Du das Zertifikat in FHEM installierst, findest Du [[Raspberry_Pi_%26_HTTPS|hier]] und wenn Du ein Server Zertifikat für NGINX installieren möchtest, findest Du Infos dazu [[HTTPS-Absicherung_%26_Authentifizierung_via_nginx_Webserver|hier]]&lt;br /&gt;
&lt;br /&gt;
== Nachwort ==&lt;br /&gt;
=== Einbinden der root CA in die Zertifizierungsstelle des Browsers ===&lt;br /&gt;
Beim Firefox importieren wir unsere cacert.pem unter Einstellungen -&amp;gt; Erweitert -&amp;gt; Zertifikate -&amp;gt; Zertifikate anzeigen -&amp;gt; Zertifizierungsstellen ein.&lt;br /&gt;
Unter Chrome/Chromium finden wir die Zertifikatsverwaltung unter Einstellungen -&amp;gt; Erweitert -&amp;gt; Zertifikate verwalten HTTPS/SSL-Zertifikate und -Einstellungen verwalten -&amp;gt; Zertifizierungsstellen&lt;br /&gt;
&lt;br /&gt;
=== Bekannte Probleme ===&lt;br /&gt;
Für den Chrome/Chromium müssen wir zusätzlich &amp;quot;Subject Alternative Names (SAN)&amp;quot; in unser Zertifikat eintragen. Dies geschieht beim Serverzertifikat signieren. Dazu müssen wir uns eine weitere Datei anlegen:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
root@linux# vim oats.extensions.cnf&lt;br /&gt;
&lt;br /&gt;
basicConstraints=CA:FALSE&lt;br /&gt;
subjectAltName=@my_subject_alt_names&lt;br /&gt;
subjectKeyIdentifier = hash&lt;br /&gt;
&lt;br /&gt;
[ my_subject_alt_names ]&lt;br /&gt;
DNS.1 = fhem01.tuxnet.local&lt;br /&gt;
DNS.2 = fhem02.tuxnet.local&lt;br /&gt;
DNS.3 = fhem01-vpn.tuxnet.local&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dabei die DNS.x Namen durch die DNS Namen (bzw. IP Addressen) ersetzen, womit man Fhem aufruft.&lt;br /&gt;
&lt;br /&gt;
Die Signierung unseres Serverzertifikates erfolgt dann mit folgendem Befehl:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
openssl ca -in req.pem -notext -extfile oats.extensions.cnf -out servercert.pem&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Prüfen von Zertifikaten ===&lt;br /&gt;
Zertifikate kann man im übrigen auf dieser [https://tools.keycdn.com/ssl| Seite] prüfen lassen.&lt;br /&gt;
Dazu kopiert man den Inhalt der servercert.pem in das Eingabefeld der Seite und klickt dann auf Check.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=SIGNALduino&amp;diff=34521</id>
		<title>SIGNALduino</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=SIGNALduino&amp;diff=34521"/>
		<updated>2021-01-02T14:38:33Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: Wortwahl&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=Empfang und Verarbeitung von digitalen Signalen&lt;br /&gt;
|ModType=d&lt;br /&gt;
|ModFTopic=38402&lt;br /&gt;
|ModCmdRef=SIGNALduino&lt;br /&gt;
|ModForumArea=Sonstige Systeme&lt;br /&gt;
|ModTechName=00_SIGNALduino.pm&lt;br /&gt;
|ModOwner=Sidey ({{Link2FU|8018|Forum}}/[[Benutzer Diskussion:Sidey|Wiki]])&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
=== Übersicht ===&lt;br /&gt;
Unter den Namen SIGNALduino versteht man sowohl den Low-Cost Empfänger für digitale Signale (vergleichbar dem  [[CUL]]) als auch das gleichnamige Modul mit dem Dateinamen 00_SIGNALduino.pm. Mit dem SIGNALduino kann man entweder 433 oder 868 MHz-Geräte auslesen und ansprechen. Der SIGNALduino funktioniert auch mit anderen Medien wie Infrarot oder direkter Kabelverbindung.&lt;br /&gt;
&lt;br /&gt;
Der SIGNALduino(-Stick) erkennt Signale anhand von Mustern und gibt sie (als maximal detaillierte Beschreibung einer Signalabfolge) dann schlicht sofort nur noch an FHEM zur Auswertung (Dekodierung) weiter. Auch nicht erkannte Signale werden an FHEM übergeben.&lt;br /&gt;
Aufgabe des SIGNALduino (Firmware/Stick) ist es also nur, Signal-Aktivitäten zu erfassen und maximal präzise (als kurzer Text-String) zu beschreiben.&lt;br /&gt;
Alles weitere (echte, finale Auswertung / Zuweisung dieser Signal-Daten) wird dann auf einer großen Box (Raspberry o.ä.) gemacht.&lt;br /&gt;
&lt;br /&gt;
=== Vorteil gegenüber einem CUL/FHEMduino ===&lt;br /&gt;
Der SIGNALduino hat den Vorteil einer sehr schnellen Demodulation des Funksignals. Sollen weitere Protokolle dekodiert werden, so muss dazu nur ein passendes FHEM Modul entwickelt oder ein universelles Modul erweitert werden (also auf flexibel direkt updatebarer Rechner-Seite!!). Änderungen am Arduino-Firmware-Code sind normalerweise nicht notwendig (sofern die grundsätzliche Signal-Klassifizierung des Sticks korrekt funktioniert - leider nicht immer, z.B.: [https://github.com/RFD-FHEM/SIGNALDuino/issues/65 MU-Nachrichten werden z.T. als MC erkannt]).&lt;br /&gt;
&lt;br /&gt;
Ein großer Vorteil des SIGNALduino besteht darin, dass auch Geräte mit leicht abweichende Frequenzen steuerbar sind; so empfangen die Somfy-Rolladenmotoren beispielsweise auf 433.42 und nicht, wie bei anderen Geräten sehr oft üblich, auf 433.92 MHz. Die Frequenzumstellung stellt für den SIGNALduino kein Problem dar.&lt;br /&gt;
&lt;br /&gt;
Ebenso kann man den SIGNALduino direkt an den Sendeausgang eines Sensors anbinden und die digitalen Signale empfangen, dabei bitte aber auf die passenden Spannungen achten, denn ein Arduino Nano verträgt nur 5V.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Entwicklungsversion ===&lt;br /&gt;
Der SIGNALduino wird derzeit aktiv weiterentwickelt, siehe dazu https://github.com/RFD-FHEM. Die offizielle Version wird {{Link2Forum|Topic=58396|LinkText=hier}} genauer beschrieben. Es existieren im Forum diverse angepasste Versionen, auf die hier nicht näher eingegangen wird.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
=== Controller ===&lt;br /&gt;
Der SIGNALduino (Hardware) wird über den USB Port angeschlossen, er kann aber auch mit zusätzlichen ESP Modulen über ein WLAN angebunden werden. Bei Einbindung via ESP muss man beachten, dass der ESP nach 5 Minuten Inaktivität seine TCP-Verbindung unterbricht (siehe [[ESP8266#Bekannte_Probleme|diesen Hinweis]]). Zu diesem Zweck gibt es einen Signalduino-eigenen Ping-Befehl (&#039;get signalduino ping&#039;), der diese Aktivität wieder aufbaut. Ping-Befehle sind auch auf Betriebssystemebene bekannt - allerdings beachte man, dass der ping-Befehl auf Betriebssystemebene ICMP verwendet, zum &amp;quot;aufwachen&amp;quot; des ESP aber auf TCP-Ebene aktiviert werden muss (zum Unterschied siehe [https://www.tippscout.de/internet-was-sind-tcp-ip-udp-und-icmp_tipp_2268.html hier]) und man daher besser den Signalduino-eigenen Befehl und nicht das Betriebssystem verwendet.&lt;br /&gt;
&lt;br /&gt;
Der SIGNALduino basiert auf einem [http://arduino.cc/de/Main/ArduinoBoardNano Arduino Nano], die Schaltung entspricht  dem [[Selbstbau_CUL]] (eine frühere Version ist der nicht mehr weiterentwickelte [[FHEMduino]]):&lt;br /&gt;
* Entweder wird ein Arduino mit einfachen Sende- und Empfangsmodulen verwendet, dann ist die Verkabelung identisch zum [[FHEMduino]] &lt;br /&gt;
* Oder es wird ein CC1101 Transceiver verwendet, dann ist die Verkabelung identisch zum [[Selbstbau_CUL]]. Dieser Aufbau wird derzeit empfohlen.&lt;br /&gt;
* Zuletzt gibt es ein fertig konfektioniertes Modul von In-Circuit mit Radino CC1101 Varianten, link zum [http://shop.in-circuit.de/index.php Hersteller]. &lt;br /&gt;
&lt;br /&gt;
Achten Sie beim Selbstbau auf die entsprechenden Sender-Empfänger. Der sehr preiswert angebotene XY-MK-5V hat sich als zu unzuverlässig erwiesen, während anscheinend beim CC1101 (insbesondere der &amp;quot;grünen Version&amp;quot;) keine Probleme auftreten. &lt;br /&gt;
&lt;br /&gt;
Es stehen auch für den [https://www.arduino.cc/en/Main/arduinoBoardUno UNO] und [https://www.arduino.cc/en/Main/ArduinoBoardProMini PRO Mini] Firmware-Dateien zur Verfügung. Die ausgelieferte Firmware läuft nur auf Mikrocontrollern mit 16 MHz; wer einen Mikrocontroller mit 8 MHz verwenden möchte, muss die Firmware selbst compilieren. Die SW ist auf [https://github.com/RFD-FHEM/SIGNALDuino github]. Vorgesehen ist nur die Übersetzung unter Windows mit Visual Studio und dem Visual Micro Zusatz. Es gibt aber auch eine Anleitung, wie man mit der [[Arduino]] IDE oder einem Makefile [[SIGNALduino Compilieren]] kann.&lt;br /&gt;
&lt;br /&gt;
Es gibt auch eine Variante des SIGNALduino, die auf einem [[ESP8266]] nativ läuft, diese funktioniert seit Anfang 2018 annehmbar, allerdings befindet diese sich noch in einer Entwicklungsphase.&lt;br /&gt;
&lt;br /&gt;
An den &amp;quot;SIGNALESP&amp;quot; kann auch ein CC1101 via SPI angebunden werden:&lt;br /&gt;
&lt;br /&gt;
{| |&lt;br /&gt;
!CC1101 Bezeichnung&lt;br /&gt;
!ESP Pin&lt;br /&gt;
|-&lt;br /&gt;
|CLK||GPIO14&lt;br /&gt;
|-&lt;br /&gt;
|MOSI||GPIO13&lt;br /&gt;
|-&lt;br /&gt;
|MISO||GPIO12&lt;br /&gt;
|-&lt;br /&gt;
|CSN||GPIO15&lt;br /&gt;
|-&lt;br /&gt;
|GDO0||GPIO4&lt;br /&gt;
|-&lt;br /&gt;
|GDO2||GPIO5&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Wird ein einfacher Empfänger / Sender Kombination verwendet, dann über die PINs:&lt;br /&gt;
&lt;br /&gt;
{| |&lt;br /&gt;
! Bezeichnung &lt;br /&gt;
! ESP Pin&lt;br /&gt;
|-&lt;br /&gt;
|Transmitter||GPIO4&lt;br /&gt;
|-&lt;br /&gt;
|Receiver||GPIO5&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Sendemodule ===&lt;br /&gt;
{{Randnotiz|RNTyp=r|RNText=Viele user berichten über Empfangsprobleme bei Nutzung des XY-MK-5V; es wird ausdrücklich empfohlen, ein anderes Empfangsmodul zu nutzen!}}&lt;br /&gt;
[[Datei:Fhemduino_schematic.png|200px|thumb|right|Beispielschaltplan SIGNAL(FHEM)duino]]  &lt;br /&gt;
&lt;br /&gt;
Mit einem Arduino-Nano und folgenden, billigen Sende- und Empfangsmodulen können Sie einen SIGNALduino bauen:&lt;br /&gt;
* FS1000A Dies ist das Sendemodul (TX) und wird oft im Set mit dem billigen XY-MK-5V-Empfänger angeboten (etwa 5€). &lt;br /&gt;
* RXB6 Das ist das empfohlene Empfangsmodul (RX), statt XY-MK-5V, etwa 5€ aus Deutschland.&lt;br /&gt;
&lt;br /&gt;
Die Verkabelung erfolgt analog zum [[FHEMduino]] und das bedeutet (Arduino -&amp;gt; Modul):&lt;br /&gt;
* PIN D2 an DATA des RX-Moduls&lt;br /&gt;
* PIN D11 an DATA des TX-Moduls (PIN links mit Beschriftung ATAD)&lt;br /&gt;
&lt;br /&gt;
Zusätzlich muss noch jeweils GND und 5V des Arduino mit dem GND bzw. VCC des Moduls verbunden werden.&lt;br /&gt;
&lt;br /&gt;
Jetzt fehlen noch die Antennen. Dafür braucht man ein 17,2 cm langes Stück Kupferdraht, das wird beim Anschluss &amp;quot;ANT&amp;quot; jeweils am Modul angelötet (anfängergeeignet).&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
&lt;br /&gt;
===  USB-ID ermitteln  ===&lt;br /&gt;
Bevor der SIGNALduino mit dem FHEM Server (im Beispiel hier ein Raspberry PI) verbunden werden kann, muss die USB-Schnittstelle ermittelt werden. Hierzu bitte auf dem Terminal den Befehl&lt;br /&gt;
&amp;lt;pre&amp;gt; ls -l /dev/serial/by-id &amp;lt;/pre&amp;gt;&lt;br /&gt;
ausführen. Beispielhaft sieht das Ergebnis etwa so aus: &lt;br /&gt;
&#039;&#039;lrwxrwxrwx 1 root root 13 Jan 31 00:02 &#039;&#039;&#039;usb-FTDI_FT232R_USB_UART_A903N5T5-if00-port&#039;&#039;&#039; -&amp;gt; ../../ttyUSB0&#039;&#039; &lt;br /&gt;
Damit ist der Anschluss des SIGNALduino bestimmt und das Gerät kann wie im nächsten Abschnitt beschrieben definiert werden. Zuvor muss noch das Modul geladen werden.&lt;br /&gt;
&lt;br /&gt;
=== FHEM-Modul laden ===&lt;br /&gt;
Die SIGNALduino Module werden über das FHEM [[update]] verteilt, sobald die Änderungen einen &amp;quot;stabilen&amp;quot; und alltags tauglichen Zustand haben. Aktuell wird dort die Version 3.4.2 seit 08.04.2020 verteilt.&lt;br /&gt;
&lt;br /&gt;
Die in der Entwicklung befindliche Version (3.4.x) kann mit folgenden Befehlen geladen werden:&lt;br /&gt;
&lt;br /&gt;
* FHEM aktualisieren: &amp;lt;code&amp;gt;update&amp;lt;/code&amp;gt; &lt;br /&gt;
* SIGNALduino Modul aktualisieren: &amp;lt;code&amp;gt;update all &amp;lt;nowiki&amp;gt;https://raw.githubusercontent.com/RFD-FHEM/RFFHEM/dev-r34/controls_signalduino.txt&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;  Durch das Update von FHEM wird sichergestellt, dass das Modul mit FHEM arbeitet.&lt;br /&gt;
*Danach kann das Gerät wie folgt definiert werden (die Spezifikation des USB-Anschlusses muss dabei an die aktuellen Gegebenheiten angepasst werden):&lt;br /&gt;
:&amp;lt;code&amp;gt;define &amp;lt;eigener-SIGNALduino-Name&amp;gt; SIGNALduino /dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A903N5T5-if00-port0@57600&amp;lt;/code&amp;gt;&lt;br /&gt;
* Solltet Ihr einen SIGNALESP via IP einbinden wollen ist die Syntax&lt;br /&gt;
:&amp;lt;code&amp;gt;define &amp;lt;eigener-SIGNALESP-Name&amp;gt; SIGNALduino &amp;lt;ip-adresse&amp;gt;:23&amp;lt;/code&amp;gt;&lt;br /&gt;
Nach dem Einbinden wird der SIGNALduino, falls er erkannt wird, im Status &amp;quot;Opened&amp;quot; angezeigt. Die Baudrate beim SIGNALduino beträgt 57600 - via telnet muss dann dieselbe Baudrate eingestellt werden. &lt;br /&gt;
&lt;br /&gt;
Für neuere Entwicklungen kann in FHEM auch dauerhaft die developer Version aktualisiert werden:&lt;br /&gt;
&amp;lt;code&amp;gt;update add &amp;lt;nowiki&amp;gt;https://raw.githubusercontent.com/RFD-FHEM/RFFHEM/dev-r34/controls_signalduino.txt&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; &lt;br /&gt;
Danach wird FHEM bei dem normalen Update-Befehl immer automatisch die aktuelle dev Version laden.&lt;br /&gt;
&lt;br /&gt;
Die nachfolgenden Beispiel-Befehle verwenden &amp;quot;sduino&amp;quot; als &amp;lt;eigener-SIGNALduino-Name&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Flashen des Arduino mit der SIGNALduino Firmware ====&lt;br /&gt;
Falls avrdude noch nicht vorhanden ist, kann es mit folgendem Befehl installiert werden:&lt;br /&gt;
:&amp;lt;code&amp;gt;sudo apt-get install avrdude&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In FHEM ist der SIGNALduino mit dem Status &amp;quot;Open&amp;quot; vorhanden. Jetzt müssen wir FHEM noch mitteilen, welche Hardware wir angeschlossen haben. Über das Attribut &#039;&#039;hardware&#039;&#039; lässt sich zwischen den mitgelieferten Firmware-Dateien wechseln. Solltet ihr einen Nano mit cc1101 Transceiver verwenden, so wählt bitte folgende Hardware&lt;br /&gt;
:&amp;lt;code&amp;gt;attr sduino hardware nanoCC1101&amp;lt;/code&amp;gt;&lt;br /&gt;
sonst üblicherweise&lt;br /&gt;
:&amp;lt;code&amp;gt;attr sduino hardware nano328&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dann muss mitgeteilt werden, welche Version man geladen haben will: stable oder testing. &lt;br /&gt;
:&amp;lt;code&amp;gt;attr sduino updateChannelFW testing&amp;lt;/code&amp;gt;&lt;br /&gt;
Nun wird die entsprechende Firmware heruntergeladen. Dies geschieht durch den Befehl&lt;br /&gt;
:&amp;lt;code&amp;gt;get sduino availableFirmware&amp;lt;/code&amp;gt;&lt;br /&gt;
Anschließend kann der &#039;&#039;flash&#039;&#039; Befehl abgesetzt werden: &lt;br /&gt;
:&amp;lt;code&amp;gt;set sduino flash &amp;lt;und-dann-auswaehlen&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
Dadurch wird der Arduino mit der gewählten Firmware geflasht. Das Ergebnis wird im Webinterface direkt angezeigt.&lt;br /&gt;
&lt;br /&gt;
Alternativ kann auch der Flash-Befehl mit einem Dateinamen aufgerufen werden. Diese Möglichkeit sollte jedoch nur verwendet werden, wenn die SIGNALduino Firmware selbst compiliert wurde und eine andere Hardware verwendet wird. Der Flash-Befehl wird wie folgt aufgerufen:&lt;br /&gt;
:&amp;lt;code&amp;gt;set sduino flash FHEM/firmware/SIGNALduino_mega2560.hex&amp;lt;/code&amp;gt;&lt;br /&gt;
(je nachdem wo und unter welchem Namen die .hex Datei abgelegt wurde)&lt;br /&gt;
&lt;br /&gt;
Wenn ein miniCUL geflasht werden soll, sind einige Besonderheiten zu beachten. Details dazu in {{Link2Forum|Topic=114413|LinkText=diesem Forenthema}}.&lt;br /&gt;
&lt;br /&gt;
==== Flashen einer Firmware über HTTP ====&lt;br /&gt;
Die Firmware wird in  nicht mehr über den FHEM Update Mechanismus verteilt. &lt;br /&gt;
Damit die passende Firmware auf den SIGNALduino geladen werden kann, wird diese dann über HTTP aus den Github Releases geladen.&lt;br /&gt;
&lt;br /&gt;
==== Vorabversion einer Firmware ====&lt;br /&gt;
Die Firmware des SIGNALduino wird ebenso wie das FHEM Modul auch weiter entwickelt.&lt;br /&gt;
Die Entwickler sind auf Tests und Rückmeldungen der Nutzer angewiesen, da leider nicht alle Sensoren vorher getestet werden können.&lt;br /&gt;
&lt;br /&gt;
Aktuell (April 2020) ist noch die Version 3.3.1 fertig. Die Version 3.4 ist seit Februar 2020 in einer Vorabversion verfügbar.&lt;br /&gt;
&lt;br /&gt;
Für die folgenden Microcontroller kann man die Firmware seit 21.02.2019 auch direkt downloaden und teilweise flashen. &lt;br /&gt;
Dazu muss das Attribut hardware auf einen gültigen Wert angepasst werden!&lt;br /&gt;
Über den GET Befehl availableFirmware werden dann für die hinterlegte Hardware die passenden Versionen gesucht. Über das Attribut updateChannelFW kann zwischen &amp;quot;stable&amp;quot; und &amp;quot;testing&amp;quot; definiert werden, welche Art von Firmware angeboten werden soll.&lt;br /&gt;
&lt;br /&gt;
Nachdem die Firmwareversion erfragt wurde, bietet der set flash Befehl eine Auswahlliste an. Wird ein Flash Befehl mit einer der Versionen ausgewählt, wird diese Version zunächst heruntergeladen und bei den AVR Versionen auch versucht diese mittels avrdude zu flashen.&lt;br /&gt;
Die Firmware für den ESP8266 kann aktuell leider noch nicht über diesen Befehl aktualisiert werden.&lt;br /&gt;
&lt;br /&gt;
Alternativ funktioniert aber auch die Option, dem Flash Befehl eine URL zu übergeben. Dann wird die Datei aus der URL heruntergeladen und auch versucht diese zu Flashen. z.B.&lt;br /&gt;
SIGNALDuino_nanocc1101.hex für einen Nano mit CC1101&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set sduino flash &amp;lt;/code&amp;gt;https://github.com/RFD-FHEM/SIGNALDuino/releases/download/3.3.1/SIGNALDuino_radinocc11013.3.1.hex&lt;br /&gt;
&lt;br /&gt;
oder&lt;br /&gt;
SIGNALESP_.hex (mit cc1101) für einen ESP8266 &lt;br /&gt;
&amp;lt;code&amp;gt;set ipduino flash &amp;lt;/code&amp;gt;https://github.com/RFD-FHEM/SIGNALDuino/releases/download/3.3.1/SIGNALDuino_ESP8266cc11013.3.1.hex&lt;br /&gt;
&lt;br /&gt;
!Achtung, aktuell wird die Firmware für den ESP dadurch nur herunter geladen. Flashen müsst ihr leider immer noch über ein passendes Tool &lt;br /&gt;
z.B. [https://github.com/nodemcu/nodemcu-flasher ESP8266Flasher.exe] oder Esptool und einer seriellen Konsole.&lt;br /&gt;
Auch ist zu beachten, es handelt sich hierbei tatsächlich um ein Binary und nicht um ein Hex File. &lt;br /&gt;
&lt;br /&gt;
Nach dem Booten des ESPs, spannt dieser ein eigenes WLAN auf. Habt ihr euch damit verbunden, könnt ihr den ESP mit eurem vorhandenen WLAN nach Eingabe der Daten verbinden.&lt;br /&gt;
&lt;br /&gt;
Die Hauptseite für Firmware-Releases findet sich unter https://github.com/RFD-FHEM/SIGNALDuino/releases/ .&lt;br /&gt;
Dort kann auch eine Änderungshistorie eingesehen werden.&lt;br /&gt;
==== Flashen eines radino Boards mit ATmega32U4 ====&lt;br /&gt;
&lt;br /&gt;
Diese Funktion steht seit 21.02.2019 nun auch in der via FHEM aktualisierten version zur Verfügung:&lt;br /&gt;
&lt;br /&gt;
Auch sind Berichte bekannt, dass der Radino beim Neustart von FHEM nicht korrekt initialisiert wird.&lt;br /&gt;
Weiterhin ist zu beachten, dass der Bootloader eine andere USB ID bekommt und diese im Attribut flashCommand hinterlegt werden muss.&lt;br /&gt;
&lt;br /&gt;
==== Fehler beim Flashen ====&lt;br /&gt;
Sollte bei einem Flash Vorgang ein Fehler auftreten, solltet ihr zunächst im Logfile mit Verbose 5 nachsehen.&lt;br /&gt;
&lt;br /&gt;
Findet ihr dort keine Fehlermeldung, gibt es noch ein separates Flashlog, welches ihr über einen Browser aufrufen könnt. Dazu müsst ihr nur den Folgenden Pfad an euren Servernamen anhängen:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
/fhem/FileLog_logWrapper?dev=Logfile&amp;amp;type=text&amp;amp;file=SIGNALduino-Flash.log&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Geräteerkennung ===&lt;br /&gt;
==== Unterstützte Geräte ====&lt;br /&gt;
Für die folgenden Geräte gibt es derzeit (2017) eine Unterstützung für den Betrieb mit FHEM. Die Geräte werden [[autocreate|automatisch erkannt]] und in der Konfiguration eingetragen, wenn der SIGNALduino läuft.&lt;br /&gt;
Bitte Geräte mit sehr präzisen Referenzen hier listen (Produktnummer, Protokoll-Variantenname etc.), damit eine globale Suche/Verifikation maximal erfolgreich ist. In der detaillierten Liste [[Geprüfte_Geräte]] lassen sich die Geräte näher identifizieren.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! style=&amp;quot;text-align:left;&amp;quot; | Produkt &lt;br /&gt;
! (E)mpfangen&amp;lt;br /&amp;gt;(S)enden &lt;br /&gt;
! Hinweise &lt;br /&gt;
! Verwendetes Modul &lt;br /&gt;
! Protokoll ID&lt;br /&gt;
|-&lt;br /&gt;
|Conrad Wetterstation KW9110||E S||Sensor: KW9010, neben Temperatur u. Luftfeuchte werden auch Trend, Batterie u. Kanal erfasst|| CUL_TCM97001  || 0.3&lt;br /&gt;
|-&lt;br /&gt;
|TCM Wetterstation (97001 und 21xxx Serie)||E|| || CUL_TCM97001 || 0&lt;br /&gt;
|-&lt;br /&gt;
|ABS Wetterstation (ABS 700)||E|| || CUL_TCM97001  || 0&lt;br /&gt;
|-&lt;br /&gt;
|Prologue Wetterstation ||E|| ||CUL_TCM97001 || 0&lt;br /&gt;
|-&lt;br /&gt;
|Rubicson Wetterstation ||E|| ||CUL_TCM97001 ||0 &lt;br /&gt;
|-&lt;br /&gt;
|NC_WS Wetterstation ||E|| ||CUL_TCM97001 || 0&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.gt-support.de/ GT-WT-02 Wetterstation]||E|| ||CUL_TCM97001 || 0&lt;br /&gt;
|-&lt;br /&gt;
|AURIOL Wetterstation ||E|| ||CUL_TCM97001 || 0&lt;br /&gt;
|-&lt;br /&gt;
|Mebus Wetterstation ||E|| ||CUL_TCM97001 || 0&lt;br /&gt;
|-&lt;br /&gt;
|Intertechno Funkschalter||E S|| ||IT || 3,4,5,17&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;strike&amp;gt;Conrad RSL Funkschalter&amp;lt;/strike&amp;gt;||E S|| Funktioniert aktuell nicht || SIGNALduino_RSL  || &lt;br /&gt;
|-&lt;br /&gt;
|[http://global.oregonscientific.com/product_view.php?id=5 Oregon Scientific Wettersensoren]||E || Protokoll V2 &amp;amp; V3 implementiert || OREGON || 10&lt;br /&gt;
|-&lt;br /&gt;
|Bresser Temp/Hydro Sensor||E || || Hideki || 12&lt;br /&gt;
|-&lt;br /&gt;
|[https://de.hama.com/00104985/hama-aussensensor-ts33c-fuer-wetterstation Hama TS33C]||E || || Hideki || 12&lt;br /&gt;
|-&lt;br /&gt;
|TFA Temp/Hydro Sensor||E || || Hideki || 12&lt;br /&gt;
|-&lt;br /&gt;
|Lacrosse TX2/TX3 Sensoren||E || || CUL_TX || 8&lt;br /&gt;
|-&lt;br /&gt;
|TFA 30320902||E || || SD_WS07 || 7&lt;br /&gt;
|-&lt;br /&gt;
|Eurochron eas800z||E || || SD_WS07  || 7&lt;br /&gt;
|-&lt;br /&gt;
|Technoline WS6750/TX70DTH||E || || SD_WS07 || 7&lt;br /&gt;
|-&lt;br /&gt;
|FreeTec Außenmodul NC-7344||E || || SD_WS07 || 7&lt;br /&gt;
|-&lt;br /&gt;
|CTW600||E || || SD_WS09 || 9&lt;br /&gt;
|-&lt;br /&gt;
|CTW602||E ||neuere Version des CTW600 mit 868.35 MHz || SD_WS09 || 9&lt;br /&gt;
|-&lt;br /&gt;
|WH1080||E || || SD_WS09 || 9&lt;br /&gt;
|-&lt;br /&gt;
|Visivon remote pt4450||E || || none || 24&lt;br /&gt;
|-&lt;br /&gt;
|Einhell HS 434/6||E || || none || 21&lt;br /&gt;
|-&lt;br /&gt;
|Flamingo FA20RF / FA21RF / FA22RF Rauchmelder||E || || FLAMINGO || 13,13.1,13.2&lt;br /&gt;
|-&lt;br /&gt;
|mumbi m-FS300||E || || none || 26,27&lt;br /&gt;
|-&lt;br /&gt;
|TFA 30.3200||E || || none || 33&lt;br /&gt;
|-&lt;br /&gt;
|Livolo||E|| || none || 20&lt;br /&gt;
|-&lt;br /&gt;
|Smartwares RM174RF/2 (RM174RF-001CPR) 4500177571 ||E [S?]|| IT EV1527; TODO herausfinden: Alarmierung (wie Alarmton getriggered werden kann); Batterieinfo? || IT || 3&lt;br /&gt;
|-&lt;br /&gt;
|Smartwares SH5-TSO-A||E S|| || IT || ?&lt;br /&gt;
|-&lt;br /&gt;
|X10 Security Devices||E|| ||  || 39&lt;br /&gt;
|-&lt;br /&gt;
|[[Somfy_via_SIGNALduino|Somfy RTS]]||E S|| || SOMFY || 43&lt;br /&gt;
|}&lt;br /&gt;
Bei einigen Intertechno-Funksteckdosen (Brennenstuhl) kann es zu Empfangsproblemen kommen. Hier muss die Taktrate, mit der gesendet wird, angepasst werden. Dazu muss für &#039;&#039;Funksteckdose&#039;&#039; (also sauber per-Client-Instanz-spezifisch, NICHT SIGNALduino-Transceiver-global) das Attribut &lt;br /&gt;
:&amp;lt;code&amp;gt;attr &amp;lt;Funksteckdose&amp;gt; ITclock 300&amp;lt;/code&amp;gt; &lt;br /&gt;
gesetzt werden, der Standardwert ist 250.&lt;br /&gt;
&lt;br /&gt;
==== Mein Gerät wird in FHEM nicht erkannt ====&lt;br /&gt;
1. Prüfen, ob vom Sensor die Signaldaten (verbose &amp;gt;=4) erkannt werden. Sobald ihr die empfangenen Signaldaten im Logfile zuordnen könnt, geht es weiter mit:&lt;br /&gt;
&lt;br /&gt;
2. Eröffnet ein Thema unter [https://github.com/RFD-FHEM/RFFHEM/issues/new?template=sensor---device-feature.md github]:&amp;lt;syntaxhighlight lang=&amp;quot;md&amp;quot;&amp;gt;&lt;br /&gt;
##  Specifications for new sensor / switch / or other device ... &lt;br /&gt;
&lt;br /&gt;
  - manufacturer:&lt;br /&gt;
  - model name:&lt;br /&gt;
  - pictures of the device / the board (very helpful)&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
## Specifications &lt;br /&gt;
&lt;br /&gt;
  - Microcontroller:&lt;br /&gt;
  - Version (Firmware):&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;!-- ( can be found here devicename -&amp;gt; Internals -&amp;gt; version ) --&amp;gt;&lt;br /&gt;
  - Versionmodul (FHEM Module):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;3. Auszug aus dem Logfile, welches zum Gerät gehört.&lt;br /&gt;
:&#039;&#039;Alles was ihr sonst noch über das Gerät und die übertragenen Daten wisst.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Im Forum solltet ihr solche Fragen besser nicht posten, wenn das Gerät noch nicht unterstützt wird, dazu ist Github besser geeignet. Inzwischen wurde im Wiki eine eigene Seite eröffnet, die sich mit der Erkennung unbekannter Protokolle beschäftigt: [[Unbekannte_Funkprotokolle#Ansatz_1_-_Versuchen|Unbekannte_Funkprotokolle]].&lt;br /&gt;
&lt;br /&gt;
==== Es wird ein Protokoll erkannt, Autocreate legt aber kein device an ====&lt;br /&gt;
Im SIGNALduino sind &amp;gt;70 Protokolle implementiert. Jedoch gibt es nicht immer ein logisches Module, welche diese Protokolle verarbeiten.&lt;br /&gt;
Teilweise ist das auch nicht zwingend notwendig, um seine Anforderungen zu erfüllen. Insbesondere für Schalter bzw. Sensoren, die nur zwei Zustände kennen, geht es meist ohne Modul und automatisch angelegtem Gerät.&lt;br /&gt;
&lt;br /&gt;
Nehmen wir an, wir haben einen Schalter. Dieser kann einen oder zwei Zustände senden.&lt;br /&gt;
Im FHEM Log (und, insbesondere, im FHEMWEB Event Monitor) tauchen Meldungen ähnlich dieser auf&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
2015.11.15 15:52:23 4: SIGNALduino_unknown incomming msg: u85#FF8081&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wir können mit Hilfe des Modules DOIF auf diese Nachricht eine Aktion ausführen:&lt;br /&gt;
&lt;br /&gt;
Entweder, wenn wir den Inhalt der Nachricht nur zu Teilen wissen, da er sich ändert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
define mydoif DOIF ([sduino:&amp;amp;DMSG] =~ &amp;quot;u85#FF8081&amp;quot;) (set Lamp on)&lt;br /&gt;
attr mydoif do always&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oder, wenn wir den Inhalt exakt kennen, dann auch als Vergleichsstring&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
define mydoif DOIF ([sduino:&amp;amp;DMSG] eq &amp;quot;u85#FF8081&amp;quot;) (set relais on)&lt;br /&gt;
attr mydoif do always&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Teil u85#FF8081 muss individuell angepasst werden, der Name eures SIGNALduino möglicherweise auch.&lt;br /&gt;
&lt;br /&gt;
Als Alternative zu DOIF hier ein regex-verwendendes notify-Beispiel für einen Sender, der meint, zwei Codes alternierend senden zu müssen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
define n_sender_trigger notify sduino:UNKNOWNCODE.*u41#(13B72253|163873B3) { my_sender_trigger_indicate();; }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Selbstverständlich muss in diesem Moment auch eine sub my_sender_trigger_indicate() definiert werden (z.B. in FHEM/99_myUtils.pm), die dort z.B. als Test eine Log-Ausgabe (Log3()) machen kann.&lt;br /&gt;
&lt;br /&gt;
=== Das Logfile ===&lt;br /&gt;
Im Logfile ab [[Verbose]] 4 tauchen diverse Meldungen auf, deren Bedeutung kurz erläutert wird (verbose 3 unterdrückt diese Meldungen).&lt;br /&gt;
&lt;br /&gt;
UPDATE: der folgende Bereich ist von einem weniger erfahrenen Zeitgenossen früher nach Kräften erweitert/geschrieben worden. Mittlerweile existiert aber ein neuer Inhalt [[Unbekannte_Funkprotokolle]] (siehe auch Erwähnung weiter oben), der als sehr gut beschrieben und unvergleichlich detailreicher bezeichnet werden muss (&amp;quot;endlich gibt es sowas!&amp;quot;). Der Bereich hier dürfte somit zwar für grundlegende Verdeutlichungen noch recht sinnvoll sein, der Inhalt sollte allerdings evt. in eine konsistente Dokumentation überarbeitet (verlagert/dedupliziert/reduziert) werden.&lt;br /&gt;
&lt;br /&gt;
Die Protokolle (von der SIGNALDuino-Firmware gesendete Signal-Beschreibungs-Strings) können wie folgt unterschieden werden:&lt;br /&gt;
&lt;br /&gt;
*MS - Nachricht mit Sync Puls: Hierzu ein Beispiel&lt;br /&gt;
:&amp;lt;code&amp;gt;MS;P0=-108;P1=395;P2=-1033;P3=-547;P4=-19932;P5=-8916;P6=1368;D=151313131312131313131313131313131312121212121313131313131312131212132;CP=1;SP=5;&amp;lt;/code&amp;gt; P0-P6 sind die Signalpegel (Dauer und positiv/negativ). Hinter D= befindet sich die Abfolge der Signale. Die ersten beiden Ziffern 15 in D sind wie folgt zu lesen. Zuerst wurde ein Signal &amp;quot;1&amp;quot; also P1 mit 395 Mikrosekunden high (die Zeitdauer ergibt sich aufgrund der Mitteilung &amp;quot;P1=395&amp;quot;) und anschließend ein Signal &amp;quot;5&amp;quot; also P5 mit 8916 Mikrosekunden low (die Zeitdauer ergibt sich aufgrund der Mitteilung &amp;quot;P5=-8916&amp;quot;) gemessen. CP=1 ist die Referenz auf den Takt des Signales - der Basistakt ist in diesem Fall ~395 Mikrosekunden. SP=5 gibt die Referenz zum Syncpuls an, der das gesamte Signal einleitet. Welche Signalfolge nun eine binäre 1 bzw. 0 bedeutet, wird im SIGNALduino über die integrierte Protokoll Liste realisiert.&lt;br /&gt;
&lt;br /&gt;
*MC - Nachricht vom Typ Manchester: Manchesterkodierte Signale können bereits sehr einfach im Arduino in eine Binärform umgewandelt werden. Es wird hier nach IEEE 802.3 umgewandelt. In Manchester Signalen gibt es lange und kurze Pulse. Deren Durchschnittswert wird mit LL (long low), LH (long high), SL (short low) und SH (short high) übermittelt. Zusätzlich, um das Protokoll schneller erkennen zu können, wird die Taktfrequenz mit übermittelt (C=429 Mikrosekunden). Die Daten befinden sich hinter D= und werden in HEX Form übergeben.&lt;br /&gt;
:&amp;lt;code&amp;gt;MC;LL=-1066;LH=904;SL=-562;SH=385;D=332B4B4D54D5554B552CD2D554B2B5354A;C=429;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*MU - Message unsynced: Diese Art von Nachrichten sind nicht nach Manchester codiert und haben auch keinen erkennbaren Sync / Clock Signalpegel am Start der Nachricht. Bei diesen Nachrichtentypen ist es, im Vergleich zu den anderen, am wahrscheinlichsten, dass das übermittelte Signal unvollständig oder überhaupt kein Signal ist. Wie bei MS sind P0-P6 die Signalpegel und in D= wird die Abfolge der Signalpegel referenziert. CP=2 gibt auch hier die Referenz zum Takt an, allerdings muss dieser nicht korrekt erkannt worden sein.&lt;br /&gt;
:&amp;lt;code&amp;gt;MU;P0=1372;P1=-580;P2=362;P3=-1047;D=01212321212321212121212121212123212123212321232121212121212321;CP=2;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es erscheinen viele Meldungen dieser Art:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Fingerprint for MU Protocol id xxxx -&amp;gt; yyy matches, trying to demodulate&lt;br /&gt;
sduino: Starting demodulation at Position 1&lt;br /&gt;
Fingerprint for MU Protocol id 28 -&amp;gt; IC Ledspot matches, trying to demodulate&lt;br /&gt;
sduino: Starting demodulation at Position 1&lt;br /&gt;
Fingerprint for MU Protocol id 29 -&amp;gt; HT12e remote matches, trying to demodulate&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dies sind nun Bemühungen, anhand der von der SIGNALDuino-Firmware gelieferten rohen aber detaillierten Signal-Strings eine Vor-Analyse / Fingerprinting vorzunehmen.&lt;br /&gt;
Man könnte nun z.B. bei solchen Fingerprinting-Analysen erkennen:&lt;br /&gt;
* dass der Basis-Takt-Wert innerhalb eines charakteristischen Zeit-Bereichs liegt&lt;br /&gt;
* dass die Anzahl der Sync-Pulse eine präzise Zahl ist&lt;br /&gt;
* dass Längen erkannter Puls-Typen innerhalb eines Bereichs liegen&lt;br /&gt;
&lt;br /&gt;
Mittels solcher Untersuchungen kann man also final hoffentlich hinreichend plausibel feststellen, &amp;quot;dass diese Aktivitäten offensichtlich(?) zu einer Funk-Komponente Rauchmelder von Hersteller XYZ gehören müssen, und man somit weiterleiten muss an ein (möglicherweise bereits existierendes) Userdaten-Dekodier-Modul für diese Herstellerkomponente&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Bei einer dann erfolgenden Demodulation des noch rohen SIGNALDuino-Strings könnte man z.B. (hoffentlich richtigerweise) annehmen, dass eine Signalpegel-Typ-Folge &amp;quot;13&amp;quot; eine binäre 1 bedeuten soll, während eine Folge &amp;quot;12&amp;quot; eine binäre 0 bedeuten soll. Man erhält aus dem Gesamt-Puls-String also nach vollständiger Demodulation eine Abfolge von vielen 0/1 Bits, die insgesamt ein Datenwort darstellen, mit einer gewissen Länge von NN bits (diese Längen-Angabe könnte übrigens - neben Namenssuche nach Hersteller oder Produkt etc. - ein wichtiges Such-Merkmal sein, ob andere Frameworks tatsächlich bereits wissen, wie Daten dieser Funk-Komponente zu dekodieren sind!). Dieses demodulierte Datenwort ist nun das finale Datenwort, welches einen Container für die Funk-Komponenten-Informationen darstellt (in diesem Container also beispielsweise enthalten: Temperatur, Feuchte, Akku-Status, ID, Alarm, ... - zumindest wenn nicht dummerweise der ganze Container erst einmal CRC- oder Crypto-verschlüsselt ist...).&lt;br /&gt;
&lt;br /&gt;
Man muss an dieser Stelle unbedingt sagen, dass dieses Userdaten-Datenwort (einer bestimmten Hersteller-Funk-Komponente!) natürlich bei &#039;&#039;jeglichen&#039;&#039; Transceiver-Systemen &#039;&#039;immer&#039;&#039; gleich erkannt werden &#039;&#039;muss&#039;&#039; - an dieser Stelle ist also ganz klar, dass diese Daten an &#039;&#039;allgemeine&#039;&#039; FHEM-Module weitergeleitet (Dispatched) werden müssen, die nach Übernahme von Daten von &#039;&#039;jeglichen&#039;&#039; Transceiver-Systemen diese Daten immer auf die gleiche Weise (&#039;&#039;&#039;&#039;&#039;generisch/zentral&#039;&#039;&#039;&#039;&#039;) für die jeweilige Hersteller-Funk-Komponente erledigen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Die Abfolge ist also ganz klar:&#039;&#039;&#039;&lt;br /&gt;
Funk-Aktivität --&amp;gt; Transceiver-Gerät/Firmware (SIGNALDuino) --&amp;gt; maximal detailreich beschreibender Rx-Analyse-Output-String --&amp;gt; Fingerprinting-Grobzuordnung des (SIGNALDuino-Firmware-)Outputs (durch 00_SIGNALduino.pm) auf gerätespezifisches Verhalten --&amp;gt; &#039;&#039;generische/zentrale&#039;&#039; Dekodierung des gerätespezifischen Protokoll-Datenworts, in zentralen Grundsatz-Modulen wie z.B. &amp;lt;code&amp;gt;14_SD_WS.pm&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Und wenn dann bei einer solchen Schritte-Abfolge irgendetwas noch fehlen/unpassend sein sollte, dann muss eben entsprechendes Development an gewissen Stellen erfolgen ;-)&lt;br /&gt;
&lt;br /&gt;
====Minimieren (whitelist/blacklist) von unerwünschter Kommunikations-Aktivität/Einträgen====&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Unknown Code&amp;quot; bedeutet, dass der SIGNALduino Signaldaten empfangen und diese binär interpretiert hat. Diese Meldung soll uns nun aber mitteilen, dass es dann nicht weiter verarbeitet werden kann, da kein Modul  existiert (oder kein Weiterleitungs-Dispatch zu einem bereits existierenden), welches diese Daten jetzt in ihre Bedeutung umwandeln kann. &lt;br /&gt;
:&amp;lt;code&amp;gt;sduino: Unknown code u1FFFFF0, help me!&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Außerdem kommt es gehäuft zu Logmeldungen und auch Events in ähnlicher Form:&lt;br /&gt;
:&amp;lt;code&amp;gt;SIGNALduino_unknown incomming msg: u85#FF8081&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mittlerweile sind über 50 Protokolle für den SIGNALduino definiert. Dadurch kommt es vor, dass sich ein Signal mit mehr als einem Protokoll demodulieren lässt. Meist führt dies dann zu zusätzlichen &amp;quot;Unknown code&amp;quot;-Einträgen.&lt;br /&gt;
&lt;br /&gt;
Derartige Einträge können mit dem Attribut WhitelistID minimiert werden. Dabei werden die Geräte, die nach Daten-Empfang tatsächlich verarbeitet werden sollen (also welche Protokolle vom FHEM Modul berücksichtigt werden), mit ihrer Protokollnummer in die WhitelistID aufgenommen.&lt;br /&gt;
Für Protokolle, die nicht berücksichtigt werden, gibt es weder Logeinträge noch Events. Diese werden im Programmablauf nicht berücksichtigt. Das spart zum einen Ressourcen und trägt auch zur Übersichtlichkeit bei. &lt;br /&gt;
Die Protokollnummer kann Tabelle [[#Unterst.C3.BCtzte_Ger.C3.A4te|Unterstützte Geräte]] entnommen werden (hilfreich ist es auch, wenn in den verwendeten Geräten im Internal &amp;lt;gerätename&amp;gt;_DMSG nachgesehen wird). So bedeutet beispielsweise ein Eintrag der Form &amp;lt;code&amp;gt;W50#FF553335FFBC&amp;lt;/code&amp;gt; dass dann das Protokoll  #50 in die Whitelist aufzunehmen wäre (&amp;lt;code&amp;gt;attr sduino whitelist_IDs 50&amp;lt;/code&amp;gt;).&lt;br /&gt;
{{Randnotiz|RNTyp=r|RNText=Achtung Schreibweise: Dokumentation oft als WhitelistID o.ä., aber Name ist whitelist_IDs!!&lt;br /&gt;
}}&lt;br /&gt;
Die Angabe erfolgt durch Komma getrennt: z.B.:&lt;br /&gt;
:&amp;lt;code&amp;gt;1,2,5,10&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Senden mit dem SIGNALduino ===&lt;br /&gt;
Der SIGNALduino kann etwas &amp;quot;raw senden&amp;quot;, indem ihm das SIGNAL so übermittelt wird, wie er es moduliert. Hierzu  muss der Befehl wie folgt eingegeben werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
set sduino sendMsg P3#00111010#R4&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dieser Befehl moduliert die Bitfolge 00111010 mittels Protokoll #3 und wiederholt die Nachricht 4x.&lt;br /&gt;
Die Protokoll Nummer kann aus einer empfangenen Nachricht extrahiert werden. Ebenso die Bits.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
sduino: extracted data 00111010 (bin)&lt;br /&gt;
sduino: Found Protocol id 3 &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternativ kann das Signal auch in einer &amp;quot;rohform&amp;quot; angegeben werden. Dies ist manchmal in speziellen Fällen notwendig:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
set sduino raw SR;;R=3;;P0=4742;;P1=-1554;;P2=286;;P3=-786;;P4=649;;P5=-420;;D=0123234545234545452323232323454523234523454523232345454523232323452345234523452345;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
R=3 bedeutet, das Signal wird 3x gesendet.&lt;br /&gt;
Die Übertragung besteht aus den in D angegeben Pulsen, welche in P0-P5 definiert werden.&lt;br /&gt;
Die Daten kann man aus einer empfangenen MS oder MU Nachricht extrahieren.&lt;br /&gt;
&lt;br /&gt;
Alternativ kann ab Version 3.2 auch eine vereinfachte Form eingegeben werden.&lt;br /&gt;
&lt;br /&gt;
====Fehlersuche====&lt;br /&gt;
(Zielgerät reagiert nicht, etc.)&lt;br /&gt;
&lt;br /&gt;
* Nachrichtenwiederholungsanzahl muss evt. für manche Geräte entsprechend groß eingestellt sein&lt;br /&gt;
{{Randnotiz|RNTyp=r|RNText=VORSICHT blöder Schreibweisen-Mismatch ITClock vs. ITclock!!}}&lt;br /&gt;
* Sende-Takt-Wert (Clock) passt evt. nicht ganz, siehe z.B. Thread-Antwort {{Link2Forum|Topic=58397|Message=775434|LinkText=Signalduino Version 3.3.1}}, wo für IT-Geräte ein Attribut anhand der CP= des Empfangsdaten-Logs modifiziert wird. ACHTUNG: dies kann entweder global das Internal-Attribut ITClock eines SIGNALduino-Transceiver-Devices sein, oder (viel besser da korrekt geräte-instanz-spezifische Konfiguration) das ITclock eines IT-Client-Devices.&lt;br /&gt;
&lt;br /&gt;
== Fehlerbehandlung ==&lt;br /&gt;
Der SIGNALduino kann mit folgendem Befehl auf Werkseinstellungen zurückgesetzt werden:&lt;br /&gt;
:&amp;lt;code&amp;gt;set raw e&amp;lt;/code&amp;gt;&lt;br /&gt;
Ob ein solcher Reset nötig ist, erkennt man an dem Inhalt vom Reading &amp;lt;code&amp;gt;cc1101_config&amp;lt;/code&amp;gt;, dort unsinnige Werte angezeigt werden oder dem Reading  &amp;lt;code&amp;gt;config&amp;lt;/code&amp;gt; welches durch den Befehl &amp;quot;get config&amp;quot; aktualisiert wird, was im Standard auf &amp;quot;MS=1;MU=1;MC=1&amp;quot; entspricht.&lt;br /&gt;
&lt;br /&gt;
In der Firmware sind die diverse Befehle eingebaut, welche über einen &amp;lt;code&amp;gt;set raw&amp;lt;/code&amp;gt; Befehl im Modul direkt ausgeführt werden können. Sofern möglich, sollten die Abfrage von Werten aus dem Modul allerdings mit den dafür vorgesehenen Kommandos erfolgen, da die Rückmeldungen des &amp;lt;code&amp;gt;set raw&amp;lt;/code&amp;gt; Befehls nur im Logfile ab Verbose 4 erscheinen. Die Befehle sind nützlich, wenn direkt auf den Microcontroller zugegriffen wird: &lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;C&amp;lt;reg&amp;gt;&amp;lt;/code&amp;gt; &amp;lt;reg&amp;gt; is a (two digit) hex number: return the value of the cc1101 register. &amp;lt;reg&amp;gt;=99 dumps the first 48 registers. Example: &amp;lt;code&amp;gt;set raw C35&amp;lt;/code&amp;gt; führt ab Verbose 4 zu einer Logausgabe folgender Art  &amp;lt;code&amp;gt;Read, msg: C35 = 0D&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;e&amp;lt;/code&amp;gt; EEPROM / factory reset.  resets all eeprom values without reboot&lt;br /&gt;
:&amp;lt;code&amp;gt;W&amp;lt;AA&amp;gt;&amp;lt;XX&amp;gt;&amp;lt;/code&amp;gt; Write eeprom (schreibt einen Wert ins EEPROM und ins CC1101 Register. Die eeprom Adresse hat einen Offset von 2. z.B W041D schreibt 1D ins Register 2 des CC1101)&lt;br /&gt;
&lt;br /&gt;
Die Sendeleistung lässt sich mit &lt;br /&gt;
:&amp;lt;code&amp;gt;get sduino ccpatable&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
prüfen, wobei die Rückmeldung wie folgt zu lesen ist: &lt;br /&gt;
  &amp;quot;-10_dBm&amp;quot;  =&amp;gt; &#039;34&#039;,&lt;br /&gt;
  &amp;quot;-5_dBm&amp;quot;   =&amp;gt; &#039;68&#039;,&lt;br /&gt;
  &amp;quot;0_dBm&amp;quot;    =&amp;gt; &#039;60&#039;,&lt;br /&gt;
  &amp;quot;5_dBm&amp;quot;    =&amp;gt; &#039;84&#039;,&lt;br /&gt;
  &amp;quot;7_dBm&amp;quot;    =&amp;gt; &#039;C8&#039;,&lt;br /&gt;
  &amp;quot;10_dBm&amp;quot;   =&amp;gt; &#039;C0&#039; &lt;br /&gt;
Dabei wird die Sendeleistung dauerhaft mit dem Befehl&lt;br /&gt;
:&amp;lt;code&amp;gt;set sduino cc1101_patable &amp;lt;value&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
hochgeschaltet (&amp;lt;value&amp;gt; durch den Wert ersetzen).&lt;br /&gt;
&lt;br /&gt;
Weitere Firmware-Befehle sind im Thread-Beitrag {{Link2Forum|Topic=58396|Message=497921}} zu finden.&lt;br /&gt;
&lt;br /&gt;
== Foren Links ==&lt;br /&gt;
* {{Link2Forum|Topic=38402|LinkText=Forenthread - Ankündigung}}&lt;br /&gt;
* {{Link2Forum|Topic=58396|LinkText=SIGNALDuino Empfänger Firm- und Hardware}}&lt;br /&gt;
* {{Link2Forum|Topic=82379|Message=1033374|LinkText=SIGNALDuino Schaltplan}}&lt;br /&gt;
* {{Link2Forum|Topic=58397|LinkText=Signalduino Entwicklung Version 3.3.1 }}&lt;br /&gt;
* [http://www.rflink.nl/blog2/wiring Beschreibung zu diversen Empfängern und Verbesserung der Empfangsleistung]&lt;br /&gt;
* [[SIGNALduino in die Arduino Entwicklungsumgebung einbinden]]&lt;br /&gt;
* [[Somfy via SIGNALduino]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Interfaces]]&lt;br /&gt;
[[Kategorie:Arduino]]&lt;br /&gt;
[[Kategorie:433MHz]]&lt;br /&gt;
[[Kategorie:868MHz]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=SIGNALduino&amp;diff=34520</id>
		<title>SIGNALduino</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=SIGNALduino&amp;diff=34520"/>
		<updated>2021-01-02T14:37:43Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: /* Minimieren (whitelist/blacklist) von unerwünschter Kommunikations-Aktivität/Einträgen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=Empfang und Verarbeitung von digitalen Signalen&lt;br /&gt;
|ModType=d&lt;br /&gt;
|ModFTopic=38402&lt;br /&gt;
|ModCmdRef=SIGNALduino&lt;br /&gt;
|ModForumArea=Sonstige Systeme&lt;br /&gt;
|ModTechName=00_SIGNALduino.pm&lt;br /&gt;
|ModOwner=Sidey ({{Link2FU|8018|Forum}}/[[Benutzer Diskussion:Sidey|Wiki]])&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
=== Übersicht ===&lt;br /&gt;
Unter den Namen SIGNALduino versteht man sowohl den Low-Cost Empfänger für digitale Signale (vergleichbar dem  [[CUL]]) als auch das gleichnamige Modul mit dem Dateinamen 00_SIGNALduino.pm. Mit dem SIGNALduino kann man entweder 433 oder 868 MHz-Geräte auslesen und ansprechen. Der SIGNALduino funktioniert auch mit anderen Medien wie Infrarot oder direkter Kabelverbindung.&lt;br /&gt;
&lt;br /&gt;
Der SIGNALduino(-Stick) erkennt Signale anhand von Mustern und gibt sie (als maximal detaillierte Beschreibung einer Signalabfolge) dann schlicht sofort nur noch an FHEM zur Auswertung (Dekodierung) weiter. Auch nicht erkannte Signale werden an FHEM übergeben.&lt;br /&gt;
Aufgabe des SIGNALduino (Firmware/Stick) ist es also nur, Signal-Aktivitäten zu erfassen und maximal präzise (als kurzer Text-String) zu beschreiben.&lt;br /&gt;
Alles weitere (echte, finale Auswertung / Zuweisung dieser Signal-Daten) wird dann auf einer großen Box (Raspberry o.ä.) gemacht.&lt;br /&gt;
&lt;br /&gt;
=== Vorteil gegenüber einem CUL/FHEMduino ===&lt;br /&gt;
Der SIGNALduino hat den Vorteil einer sehr schnellen Demodulation des Funksignals. Sollen weitere Protokolle dekodiert werden, so muss dazu nur ein passendes FHEM Modul entwickelt oder ein universelles Modul erweitert werden (also auf flexibel direkt updatebarer Rechner-Seite!!). Änderungen am Arduino-Firmware-Code sind normalerweise nicht notwendig (sofern die grundsätzliche Signal-Klassifizierung des Sticks korrekt funktioniert - leider nicht immer, z.B.: [https://github.com/RFD-FHEM/SIGNALDuino/issues/65 MU-Nachrichten werden z.T. als MC erkannt]).&lt;br /&gt;
&lt;br /&gt;
Ein großer Vorteil des SIGNALduino besteht darin, dass auch Geräte mit leicht abweichende Frequenzen steuerbar sind; so empfangen die Somfy-Rolladenmotoren beispielsweise auf 433.42 und nicht, wie bei anderen Geräten sehr oft üblich, auf 433.92 MHz. Die Frequenzumstellung stellt für den SIGNALduino kein Problem dar.&lt;br /&gt;
&lt;br /&gt;
Ebenso kann man den SIGNALduino direkt an den Sendeausgang eines Sensors anbinden und die digitalen Signale empfangen, dabei bitte aber auf die passenden Spannungen achten, denn ein Arduino Nano verträgt nur 5V.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Entwicklungsversion ===&lt;br /&gt;
Der SIGNALduino wird derzeit aktiv weiterentwickelt, siehe dazu https://github.com/RFD-FHEM. Die offizielle Version wird {{Link2Forum|Topic=58396|LinkText=hier}} genauer beschrieben. Es existieren im Forum diverse angepasste Versionen, auf die hier nicht näher eingegangen wird.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
=== Controller ===&lt;br /&gt;
Der SIGNALduino (Hardware) wird über den USB Port angeschlossen, er kann aber auch mit zusätzlichen ESP Modulen über ein WLAN angebunden werden. Bei Einbindung via ESP muss man beachten, dass der ESP nach 5 Minuten Inaktivität seine TCP-Verbindung unterbricht (siehe [[ESP8266#Bekannte_Probleme|diesen Hinweis]]). Zu diesem Zweck gibt es einen Signalduino-eigenen Ping-Befehl (&#039;get signalduino ping&#039;), der diese Aktivität wieder aufbaut. Ping-Befehle sind auch auf Betriebssystemebene bekannt - allerdings beachte man, dass der ping-Befehl auf Betriebssystemebene ICMP verwendet, zum &amp;quot;aufwachen&amp;quot; des ESP aber auf TCP-Ebene aktiviert werden muss (zum Unterschied siehe [https://www.tippscout.de/internet-was-sind-tcp-ip-udp-und-icmp_tipp_2268.html hier]) und man daher besser den Signalduino-eigenen Befehl und nicht das Betriebssystem verwendet.&lt;br /&gt;
&lt;br /&gt;
Der SIGNALduino basiert auf einem [http://arduino.cc/de/Main/ArduinoBoardNano Arduino Nano], die Schaltung entspricht  dem [[Selbstbau_CUL]] (eine frühere Version ist der nicht mehr weiterentwickelte [[FHEMduino]]):&lt;br /&gt;
* Entweder wird ein Arduino mit einfachen Sende- und Empfangsmodulen verwendet, dann ist die Verkabelung identisch zum [[FHEMduino]] &lt;br /&gt;
* Oder es wird ein CC1101 Transceiver verwendet, dann ist die Verkabelung identisch zum [[Selbstbau_CUL]]. Dieser Aufbau wird derzeit empfohlen.&lt;br /&gt;
* Zuletzt gibt es ein fertig konfektioniertes Modul von In-Circuit mit Radino CC1101 Varianten, link zum [http://shop.in-circuit.de/index.php Hersteller]. &lt;br /&gt;
&lt;br /&gt;
Achten Sie beim Selbstbau auf die entsprechenden Sender-Empfänger. Der sehr preiswert angebotene XY-MK-5V hat sich als zu unzuverlässig erwiesen, während anscheinend beim CC1101 (insbesondere der &amp;quot;grünen Version&amp;quot;) keine Probleme auftreten. &lt;br /&gt;
&lt;br /&gt;
Es stehen auch für den [https://www.arduino.cc/en/Main/arduinoBoardUno UNO] und [https://www.arduino.cc/en/Main/ArduinoBoardProMini PRO Mini] Firmware-Dateien zur Verfügung. Die ausgelieferte Firmware läuft nur auf Mikrocontrollern mit 16 MHz; wer einen Mikrocontroller mit 8 MHz verwenden möchte, muss die Firmware selbst compilieren. Die SW ist auf [https://github.com/RFD-FHEM/SIGNALDuino github]. Vorgesehen ist nur die Übersetzung unter Windows mit Visual Studio und dem Visual Micro Zusatz. Es gibt aber auch eine Anleitung, wie man mit der [[Arduino]] IDE oder einem Makefile [[SIGNALduino Compilieren]] kann.&lt;br /&gt;
&lt;br /&gt;
Es gibt auch eine Variante des SIGNALduino, die auf einem [[ESP8266]] nativ läuft, diese funktioniert seit Anfang 2018 annehmbar, allerdings befindet diese sich noch in einer Entwicklungsphase.&lt;br /&gt;
&lt;br /&gt;
An den &amp;quot;SIGNALESP&amp;quot; kann auch ein CC1101 via SPI angebunden werden:&lt;br /&gt;
&lt;br /&gt;
{| |&lt;br /&gt;
!CC1101 Bezeichnung&lt;br /&gt;
!ESP Pin&lt;br /&gt;
|-&lt;br /&gt;
|CLK||GPIO14&lt;br /&gt;
|-&lt;br /&gt;
|MOSI||GPIO13&lt;br /&gt;
|-&lt;br /&gt;
|MISO||GPIO12&lt;br /&gt;
|-&lt;br /&gt;
|CSN||GPIO15&lt;br /&gt;
|-&lt;br /&gt;
|GDO0||GPIO4&lt;br /&gt;
|-&lt;br /&gt;
|GDO2||GPIO5&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Wird ein einfacher Empfänger / Sender Kombination verwendet, dann über die PINs:&lt;br /&gt;
&lt;br /&gt;
{| |&lt;br /&gt;
! Bezeichnung &lt;br /&gt;
! ESP Pin&lt;br /&gt;
|-&lt;br /&gt;
|Transmitter||GPIO4&lt;br /&gt;
|-&lt;br /&gt;
|Receiver||GPIO5&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Sendemodule ===&lt;br /&gt;
{{Randnotiz|RNTyp=r|RNText=Viele user berichten über Empfangsprobleme bei Nutzung des XY-MK-5V; es wird ausdrücklich empfohlen, ein anderes Empfangsmodul zu nutzen!}}&lt;br /&gt;
[[Datei:Fhemduino_schematic.png|200px|thumb|right|Beispielschaltplan SIGNAL(FHEM)duino]]  &lt;br /&gt;
&lt;br /&gt;
Mit einem Arduino-Nano und folgenden, billigen Sende- und Empfangsmodulen können Sie einen SIGNALduino bauen:&lt;br /&gt;
* FS1000A Dies ist das Sendemodul (TX) und wird oft im Set mit dem billigen XY-MK-5V-Empfänger angeboten (etwa 5€). &lt;br /&gt;
* RXB6 Das ist das empfohlene Empfangsmodul (RX), statt XY-MK-5V, etwa 5€ aus Deutschland.&lt;br /&gt;
&lt;br /&gt;
Die Verkabelung erfolgt analog zum [[FHEMduino]] und das bedeutet (Arduino -&amp;gt; Modul):&lt;br /&gt;
* PIN D2 an DATA des RX-Moduls&lt;br /&gt;
* PIN D11 an DATA des TX-Moduls (PIN links mit Beschriftung ATAD)&lt;br /&gt;
&lt;br /&gt;
Zusätzlich muss noch jeweils GND und 5V des Arduino mit dem GND bzw. VCC des Moduls verbunden werden.&lt;br /&gt;
&lt;br /&gt;
Jetzt fehlen noch die Antennen. Dafür braucht man ein 17,2 cm langes Stück Kupferdraht, das wird beim Anschluss &amp;quot;ANT&amp;quot; jeweils am Modul angelötet (anfängergeeignet).&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
&lt;br /&gt;
===  USB-ID ermitteln  ===&lt;br /&gt;
Bevor der SIGNALduino mit dem FHEM Server (im Beispiel hier ein Raspberry PI) verbunden werden kann, muss die USB-Schnittstelle ermittelt werden. Hierzu bitte auf dem Terminal den Befehl&lt;br /&gt;
&amp;lt;pre&amp;gt; ls -l /dev/serial/by-id &amp;lt;/pre&amp;gt;&lt;br /&gt;
ausführen. Beispielhaft sieht das Ergebnis etwa so aus: &lt;br /&gt;
&#039;&#039;lrwxrwxrwx 1 root root 13 Jan 31 00:02 &#039;&#039;&#039;usb-FTDI_FT232R_USB_UART_A903N5T5-if00-port&#039;&#039;&#039; -&amp;gt; ../../ttyUSB0&#039;&#039; &lt;br /&gt;
Damit ist der Anschluss des SIGNALduino bestimmt und das Gerät kann wie im nächsten Abschnitt beschrieben definiert werden. Zuvor muss noch das Modul geladen werden.&lt;br /&gt;
&lt;br /&gt;
=== FHEM-Modul laden ===&lt;br /&gt;
Die SIGNALduino Module werden über das FHEM [[update]] verteilt, sobald die Änderungen einen &amp;quot;stabilen&amp;quot; und alltags tauglichen Zustand haben. Aktuell wird dort die Version 3.4.2 seit 08.04.2020 verteilt.&lt;br /&gt;
&lt;br /&gt;
Die in der Entwicklung befindliche Version (3.4.x) kann mit folgenden Befehlen geladen werden:&lt;br /&gt;
&lt;br /&gt;
* FHEM aktualisieren: &amp;lt;code&amp;gt;update&amp;lt;/code&amp;gt; &lt;br /&gt;
* SIGNALduino Modul aktualisieren: &amp;lt;code&amp;gt;update all &amp;lt;nowiki&amp;gt;https://raw.githubusercontent.com/RFD-FHEM/RFFHEM/dev-r34/controls_signalduino.txt&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;  Durch das Update von FHEM wird sichergestellt, dass das Modul mit FHEM arbeitet.&lt;br /&gt;
*Danach kann das Gerät wie folgt definiert werden (die Spezifikation des USB-Anschlusses muss dabei an die aktuellen Gegebenheiten angepasst werden):&lt;br /&gt;
:&amp;lt;code&amp;gt;define &amp;lt;eigener-SIGNALduino-Name&amp;gt; SIGNALduino /dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A903N5T5-if00-port0@57600&amp;lt;/code&amp;gt;&lt;br /&gt;
* Solltet Ihr einen SIGNALESP via IP einbinden wollen ist die Syntax&lt;br /&gt;
:&amp;lt;code&amp;gt;define &amp;lt;eigener-SIGNALESP-Name&amp;gt; SIGNALduino &amp;lt;ip-adresse&amp;gt;:23&amp;lt;/code&amp;gt;&lt;br /&gt;
Nach dem Einbinden wird der SIGNALduino, falls er erkannt wird, im Status &amp;quot;Opened&amp;quot; angezeigt. Die Baudrate beim SIGNALduino beträgt 57600 - via telnet muss dann dieselbe Baudrate eingestellt werden. &lt;br /&gt;
&lt;br /&gt;
Für neuere Entwicklungen kann in FHEM auch dauerhaft die developer Version aktualisiert werden:&lt;br /&gt;
&amp;lt;code&amp;gt;update add &amp;lt;nowiki&amp;gt;https://raw.githubusercontent.com/RFD-FHEM/RFFHEM/dev-r34/controls_signalduino.txt&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; &lt;br /&gt;
Danach wird FHEM bei dem normalen Update-Befehl immer automatisch die aktuelle dev Version laden.&lt;br /&gt;
&lt;br /&gt;
Die nachfolgenden Beispiel-Befehle verwenden &amp;quot;sduino&amp;quot; als &amp;lt;eigener-SIGNALduino-Name&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Flashen des Arduino mit der SIGNALduino Firmware ====&lt;br /&gt;
Falls avrdude noch nicht vorhanden ist, kann es mit folgendem Befehl installiert werden:&lt;br /&gt;
:&amp;lt;code&amp;gt;sudo apt-get install avrdude&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In FHEM ist der SIGNALduino mit dem Status &amp;quot;Open&amp;quot; vorhanden. Jetzt müssen wir FHEM noch mitteilen, welche Hardware wir angeschlossen haben. Über das Attribut &#039;&#039;hardware&#039;&#039; lässt sich zwischen den mitgelieferten Firmware-Dateien wechseln. Solltet ihr einen Nano mit cc1101 Transceiver verwenden, so wählt bitte folgende Hardware&lt;br /&gt;
:&amp;lt;code&amp;gt;attr sduino hardware nanoCC1101&amp;lt;/code&amp;gt;&lt;br /&gt;
sonst üblicherweise&lt;br /&gt;
:&amp;lt;code&amp;gt;attr sduino hardware nano328&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dann muss mitgeteilt werden, welche Version man geladen haben will: stable oder testing. &lt;br /&gt;
:&amp;lt;code&amp;gt;attr sduino updateChannelFW testing&amp;lt;/code&amp;gt;&lt;br /&gt;
Nun wird die entsprechende Firmware heruntergeladen. Dies geschieht durch den Befehl&lt;br /&gt;
:&amp;lt;code&amp;gt;get sduino availableFirmware&amp;lt;/code&amp;gt;&lt;br /&gt;
Anschließend kann der &#039;&#039;flash&#039;&#039; Befehl abgesetzt werden: &lt;br /&gt;
:&amp;lt;code&amp;gt;set sduino flash &amp;lt;und-dann-auswaehlen&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
Dadurch wird der Arduino mit der gewählten Firmware geflasht. Das Ergebnis wird im Webinterface direkt angezeigt.&lt;br /&gt;
&lt;br /&gt;
Alternativ kann auch der Flash-Befehl mit einem Dateinamen aufgerufen werden. Diese Möglichkeit sollte jedoch nur verwendet werden, wenn die SIGNALduino Firmware selbst compiliert wurde und eine andere Hardware verwendet wird. Der Flash-Befehl wird wie folgt aufgerufen:&lt;br /&gt;
:&amp;lt;code&amp;gt;set sduino flash FHEM/firmware/SIGNALduino_mega2560.hex&amp;lt;/code&amp;gt;&lt;br /&gt;
(je nachdem wo und unter welchem Namen die .hex Datei abgelegt wurde)&lt;br /&gt;
&lt;br /&gt;
Wenn ein miniCUL geflasht werden soll, sind einige Besonderheiten zu beachten. Details dazu in {{Link2Forum|Topic=114413|LinkText=diesem Forenthema}}.&lt;br /&gt;
&lt;br /&gt;
==== Flashen einer Firmware über HTTP ====&lt;br /&gt;
Die Firmware wird in  nicht mehr über den FHEM Update Mechanismus verteilt. &lt;br /&gt;
Damit die passende Firmware auf den SIGNALduino geladen werden kann, wird diese dann über HTTP aus den Github Releases geladen.&lt;br /&gt;
&lt;br /&gt;
==== Vorabversion einer Firmware ====&lt;br /&gt;
Die Firmware des SIGNALduino wird ebenso wie das FHEM Modul auch weiter entwickelt.&lt;br /&gt;
Die Entwickler sind auf Tests und Rückmeldungen der Nutzer angewiesen, da leider nicht alle Sensoren vorher getestet werden können.&lt;br /&gt;
&lt;br /&gt;
Aktuell (April 2020) ist noch die Version 3.3.1 fertig. Die Version 3.4 ist seit Februar 2020 in einer Vorabversion verfügbar.&lt;br /&gt;
&lt;br /&gt;
Für die folgenden Microcontroller kann man die Firmware seit 21.02.2019 auch direkt downloaden und teilweise flashen. &lt;br /&gt;
Dazu muss das Attribut hardware auf einen gültigen Wert angepasst werden!&lt;br /&gt;
Über den GET Befehl availableFirmware werden dann für die hinterlegte Hardware die passenden Versionen gesucht. Über das Attribut updateChannelFW kann zwischen &amp;quot;stable&amp;quot; und &amp;quot;testing&amp;quot; definiert werden, welche Art von Firmware angeboten werden soll.&lt;br /&gt;
&lt;br /&gt;
Nachdem die Firmwareversion erfragt wurde, bietet der set flash Befehl eine Auswahlliste an. Wird ein Flash Befehl mit einer der Versionen ausgewählt, wird diese Version zunächst heruntergeladen und bei den AVR Versionen auch versucht diese mittels avrdude zu flashen.&lt;br /&gt;
Die Firmware für den ESP8266 kann aktuell leider noch nicht über diesen Befehl aktualisiert werden.&lt;br /&gt;
&lt;br /&gt;
Alternativ funktioniert aber auch die Option, dem Flash Befehl eine URL zu übergeben. Dann wird die Datei aus der URL heruntergeladen und auch versucht diese zu Flashen. z.B.&lt;br /&gt;
SIGNALDuino_nanocc1101.hex für einen Nano mit CC1101&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;set sduino flash &amp;lt;/code&amp;gt;https://github.com/RFD-FHEM/SIGNALDuino/releases/download/3.3.1/SIGNALDuino_radinocc11013.3.1.hex&lt;br /&gt;
&lt;br /&gt;
oder&lt;br /&gt;
SIGNALESP_.hex (mit cc1101) für einen ESP8266 &lt;br /&gt;
&amp;lt;code&amp;gt;set ipduino flash &amp;lt;/code&amp;gt;https://github.com/RFD-FHEM/SIGNALDuino/releases/download/3.3.1/SIGNALDuino_ESP8266cc11013.3.1.hex&lt;br /&gt;
&lt;br /&gt;
!Achtung, aktuell wird die Firmware für den ESP dadurch nur herunter geladen. Flashen müsst ihr leider immer noch über ein passendes Tool &lt;br /&gt;
z.B. [https://github.com/nodemcu/nodemcu-flasher ESP8266Flasher.exe] oder Esptool und einer seriellen Konsole.&lt;br /&gt;
Auch ist zu beachten, es handelt sich hierbei tatsächlich um ein Binary und nicht um ein Hex File. &lt;br /&gt;
&lt;br /&gt;
Nach dem Booten des ESPs, spannt dieser ein eigenes WLAN auf. Habt ihr euch damit verbunden, könnt ihr den ESP mit eurem vorhandenen WLAN nach Eingabe der Daten verbinden.&lt;br /&gt;
&lt;br /&gt;
Die Hauptseite für Firmware-Releases findet sich unter https://github.com/RFD-FHEM/SIGNALDuino/releases/ .&lt;br /&gt;
Dort kann auch eine Änderungshistorie eingesehen werden.&lt;br /&gt;
==== Flashen eines radino Boards mit ATmega32U4 ====&lt;br /&gt;
&lt;br /&gt;
Diese Funktion steht seit 21.02.2019 nun auch in der via FHEM aktualisierten version zur Verfügung:&lt;br /&gt;
&lt;br /&gt;
Auch sind Berichte bekannt, dass der Radino beim Neustart von FHEM nicht korrekt initialisiert wird.&lt;br /&gt;
Weiterhin ist zu beachten, dass der Bootloader eine andere USB ID bekommt und diese im Attribut flashCommand hinterlegt werden muss.&lt;br /&gt;
&lt;br /&gt;
==== Fehler beim Flashen ====&lt;br /&gt;
Sollte bei einem Flash Vorgang ein Fehler auftreten, solltet ihr zunächst im Logfile mit Verbose 5 nachsehen.&lt;br /&gt;
&lt;br /&gt;
Findet ihr dort keine Fehlermeldung, gibt es noch ein separates Flashlog, welches ihr über einen Browser aufrufen könnt. Dazu müsst ihr nur den Folgenden Pfad an euren Servernamen anhängen:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
/fhem/FileLog_logWrapper?dev=Logfile&amp;amp;type=text&amp;amp;file=SIGNALduino-Flash.log&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Geräteerkennung ===&lt;br /&gt;
==== Unterstützte Geräte ====&lt;br /&gt;
Für die folgenden Geräte gibt es derzeit (2017) eine Unterstützung für den Betrieb mit FHEM. Die Geräte werden [[autocreate|automatisch erkannt]] und in der Konfiguration eingetragen, wenn der SIGNALduino läuft.&lt;br /&gt;
Bitte Geräte mit sehr präzisen Referenzen hier listen (Produktnummer, Protokoll-Variantenname etc.), damit eine globale Suche/Verifikation maximal erfolgreich ist. In der detaillierten Liste [[Geprüfte_Geräte]] lassen sich die Geräte näher identifizieren.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! style=&amp;quot;text-align:left;&amp;quot; | Produkt &lt;br /&gt;
! (E)mpfangen&amp;lt;br /&amp;gt;(S)enden &lt;br /&gt;
! Hinweise &lt;br /&gt;
! Verwendetes Modul &lt;br /&gt;
! Protokoll ID&lt;br /&gt;
|-&lt;br /&gt;
|Conrad Wetterstation KW9110||E S||Sensor: KW9010, neben Temperatur u. Luftfeuchte werden auch Trend, Batterie u. Kanal erfasst|| CUL_TCM97001  || 0.3&lt;br /&gt;
|-&lt;br /&gt;
|TCM Wetterstation (97001 und 21xxx Serie)||E|| || CUL_TCM97001 || 0&lt;br /&gt;
|-&lt;br /&gt;
|ABS Wetterstation (ABS 700)||E|| || CUL_TCM97001  || 0&lt;br /&gt;
|-&lt;br /&gt;
|Prologue Wetterstation ||E|| ||CUL_TCM97001 || 0&lt;br /&gt;
|-&lt;br /&gt;
|Rubicson Wetterstation ||E|| ||CUL_TCM97001 ||0 &lt;br /&gt;
|-&lt;br /&gt;
|NC_WS Wetterstation ||E|| ||CUL_TCM97001 || 0&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.gt-support.de/ GT-WT-02 Wetterstation]||E|| ||CUL_TCM97001 || 0&lt;br /&gt;
|-&lt;br /&gt;
|AURIOL Wetterstation ||E|| ||CUL_TCM97001 || 0&lt;br /&gt;
|-&lt;br /&gt;
|Mebus Wetterstation ||E|| ||CUL_TCM97001 || 0&lt;br /&gt;
|-&lt;br /&gt;
|Intertechno Funkschalter||E S|| ||IT || 3,4,5,17&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;strike&amp;gt;Conrad RSL Funkschalter&amp;lt;/strike&amp;gt;||E S|| Funktioniert aktuell nicht || SIGNALduino_RSL  || &lt;br /&gt;
|-&lt;br /&gt;
|[http://global.oregonscientific.com/product_view.php?id=5 Oregon Scientific Wettersensoren]||E || Protokoll V2 &amp;amp; V3 implementiert || OREGON || 10&lt;br /&gt;
|-&lt;br /&gt;
|Bresser Temp/Hydro Sensor||E || || Hideki || 12&lt;br /&gt;
|-&lt;br /&gt;
|[https://de.hama.com/00104985/hama-aussensensor-ts33c-fuer-wetterstation Hama TS33C]||E || || Hideki || 12&lt;br /&gt;
|-&lt;br /&gt;
|TFA Temp/Hydro Sensor||E || || Hideki || 12&lt;br /&gt;
|-&lt;br /&gt;
|Lacrosse TX2/TX3 Sensoren||E || || CUL_TX || 8&lt;br /&gt;
|-&lt;br /&gt;
|TFA 30320902||E || || SD_WS07 || 7&lt;br /&gt;
|-&lt;br /&gt;
|Eurochron eas800z||E || || SD_WS07  || 7&lt;br /&gt;
|-&lt;br /&gt;
|Technoline WS6750/TX70DTH||E || || SD_WS07 || 7&lt;br /&gt;
|-&lt;br /&gt;
|FreeTec Außenmodul NC-7344||E || || SD_WS07 || 7&lt;br /&gt;
|-&lt;br /&gt;
|CTW600||E || || SD_WS09 || 9&lt;br /&gt;
|-&lt;br /&gt;
|CTW602||E ||neuere Version des CTW600 mit 868.35 MHz || SD_WS09 || 9&lt;br /&gt;
|-&lt;br /&gt;
|WH1080||E || || SD_WS09 || 9&lt;br /&gt;
|-&lt;br /&gt;
|Visivon remote pt4450||E || || none || 24&lt;br /&gt;
|-&lt;br /&gt;
|Einhell HS 434/6||E || || none || 21&lt;br /&gt;
|-&lt;br /&gt;
|Flamingo FA20RF / FA21RF / FA22RF Rauchmelder||E || || FLAMINGO || 13,13.1,13.2&lt;br /&gt;
|-&lt;br /&gt;
|mumbi m-FS300||E || || none || 26,27&lt;br /&gt;
|-&lt;br /&gt;
|TFA 30.3200||E || || none || 33&lt;br /&gt;
|-&lt;br /&gt;
|Livolo||E|| || none || 20&lt;br /&gt;
|-&lt;br /&gt;
|Smartwares RM174RF/2 (RM174RF-001CPR) 4500177571 ||E [S?]|| IT EV1527; TODO herausfinden: Alarmierung (wie Alarmton getriggered werden kann); Batterieinfo? || IT || 3&lt;br /&gt;
|-&lt;br /&gt;
|Smartwares SH5-TSO-A||E S|| || IT || ?&lt;br /&gt;
|-&lt;br /&gt;
|X10 Security Devices||E|| ||  || 39&lt;br /&gt;
|-&lt;br /&gt;
|[[Somfy_via_SIGNALduino|Somfy RTS]]||E S|| || SOMFY || 43&lt;br /&gt;
|}&lt;br /&gt;
Bei einigen Intertechno-Funksteckdosen (Brennenstuhl) kann es zu Empfangsproblemen kommen. Hier muss die Taktrate, mit der gesendet wird, angepasst werden. Dazu muss für &#039;&#039;Funksteckdose&#039;&#039; (also sauber per-Client-Instanz-spezifisch, NICHT SIGNALduino-Transceiver-global) das Attribut &lt;br /&gt;
:&amp;lt;code&amp;gt;attr &amp;lt;Funksteckdose&amp;gt; ITclock 300&amp;lt;/code&amp;gt; &lt;br /&gt;
gesetzt werden, der Standardwert ist 250.&lt;br /&gt;
&lt;br /&gt;
==== Mein Gerät wird in FHEM nicht erkannt ====&lt;br /&gt;
1. Prüfen, ob vom Sensor die Signaldaten (verbose &amp;gt;=4) erkannt werden. Sobald ihr die empfangenen Signaldaten im Logfile zuordnen könnt, geht es weiter mit:&lt;br /&gt;
&lt;br /&gt;
2. Eröffnet ein Thema unter [https://github.com/RFD-FHEM/RFFHEM/issues/new?template=sensor---device-feature.md github]:&amp;lt;syntaxhighlight lang=&amp;quot;md&amp;quot;&amp;gt;&lt;br /&gt;
##  Specifications for new sensor / switch / or other device ... &lt;br /&gt;
&lt;br /&gt;
  - manufacturer:&lt;br /&gt;
  - model name:&lt;br /&gt;
  - pictures of the device / the board (very helpful)&lt;br /&gt;
&lt;br /&gt;
  &lt;br /&gt;
## Specifications &lt;br /&gt;
&lt;br /&gt;
  - Microcontroller:&lt;br /&gt;
  - Version (Firmware):&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;!-- ( can be found here devicename -&amp;gt; Internals -&amp;gt; version ) --&amp;gt;&lt;br /&gt;
  - Versionmodul (FHEM Module):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;3. Auszug aus dem Logfile, welches zum Gerät gehört.&lt;br /&gt;
:&#039;&#039;Alles was ihr sonst noch über das Gerät und die übertragenen Daten wisst.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Im Forum solltet ihr solche Fragen besser nicht posten, wenn das Gerät noch nicht unterstützt wird, dazu ist Github besser geeignet. Inzwischen wurde im Wiki eine eigene Seite eröffnet, die sich mit der Erkennung unbekannter Protokolle beschäftigt: [[Unbekannte_Funkprotokolle#Ansatz_1_-_Versuchen|Unbekannte_Funkprotokolle]].&lt;br /&gt;
&lt;br /&gt;
==== Es wird ein Protokoll erkannt, Autocreate legt aber kein device an ====&lt;br /&gt;
Im SIGNALduino sind &amp;gt;70 Protokolle implementiert. Jedoch gibt es nicht immer ein logisches Module, welche diese Protokolle verarbeiten.&lt;br /&gt;
Teilweise ist das auch nicht zwingend notwendig, um seine Anforderungen zu erfüllen. Insbesondere für Schalter bzw. Sensoren, die nur zwei Zustände kennen, geht es meist ohne Modul und automatisch angelegtem Gerät.&lt;br /&gt;
&lt;br /&gt;
Nehmen wir an, wir haben einen Schalter. Dieser kann einen oder zwei Zustände senden.&lt;br /&gt;
Im FHEM Log (und, insbesondere, im FHEMWEB Event Monitor) tauchen Meldungen ähnlich dieser auf&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
2015.11.15 15:52:23 4: SIGNALduino_unknown incomming msg: u85#FF8081&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wir können mit Hilfe des Modules DOIF auf diese Nachricht eine Aktion ausführen:&lt;br /&gt;
&lt;br /&gt;
Entweder, wenn wir den Inhalt der Nachricht nur zu Teilen wissen, da er sich ändert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
define mydoif DOIF ([sduino:&amp;amp;DMSG] =~ &amp;quot;u85#FF8081&amp;quot;) (set Lamp on)&lt;br /&gt;
attr mydoif do always&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oder, wenn wir den Inhalt exakt kennen, dann auch als Vergleichsstring&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
define mydoif DOIF ([sduino:&amp;amp;DMSG] eq &amp;quot;u85#FF8081&amp;quot;) (set relais on)&lt;br /&gt;
attr mydoif do always&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Teil u85#FF8081 muss individuell angepasst werden, der Name eures SIGNALduino möglicherweise auch.&lt;br /&gt;
&lt;br /&gt;
Als Alternative zu DOIF hier ein regex-verwendendes notify-Beispiel für einen Sender, der meint, zwei Codes alternierend senden zu müssen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
define n_sender_trigger notify sduino:UNKNOWNCODE.*u41#(13B72253|163873B3) { my_sender_trigger_indicate();; }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Selbstverfreilich muss in diesem Moment auch eine sub my_sender_trigger_indicate() definiert werden (z.B. in FHEM/99_myUtils.pm), die dort z.B. als Test eine Log-Ausgabe (Log3()) machen kann.&lt;br /&gt;
&lt;br /&gt;
=== Das Logfile ===&lt;br /&gt;
Im Logfile ab [[Verbose]] 4 tauchen diverse Meldungen auf, deren Bedeutung kurz erläutert wird (verbose 3 unterdrückt diese Meldungen).&lt;br /&gt;
&lt;br /&gt;
UPDATE: der folgende Bereich ist von einem weniger erfahrenen Zeitgenossen früher nach Kräften erweitert/geschrieben worden. Mittlerweile existiert aber ein neuer Inhalt [[Unbekannte_Funkprotokolle]] (siehe auch Erwähnung weiter oben), der als sehr gut beschrieben und unvergleichlich detailreicher bezeichnet werden muss (&amp;quot;endlich gibt es sowas!&amp;quot;). Der Bereich hier dürfte somit zwar für grundlegende Verdeutlichungen noch recht sinnvoll sein, der Inhalt sollte allerdings evt. in eine konsistente Dokumentation überarbeitet (verlagert/dedupliziert/reduziert) werden.&lt;br /&gt;
&lt;br /&gt;
Die Protokolle (von der SIGNALDuino-Firmware gesendete Signal-Beschreibungs-Strings) können wie folgt unterschieden werden:&lt;br /&gt;
&lt;br /&gt;
*MS - Nachricht mit Sync Puls: Hierzu ein Beispiel&lt;br /&gt;
:&amp;lt;code&amp;gt;MS;P0=-108;P1=395;P2=-1033;P3=-547;P4=-19932;P5=-8916;P6=1368;D=151313131312131313131313131313131312121212121313131313131312131212132;CP=1;SP=5;&amp;lt;/code&amp;gt; P0-P6 sind die Signalpegel (Dauer und positiv/negativ). Hinter D= befindet sich die Abfolge der Signale. Die ersten beiden Ziffern 15 in D sind wie folgt zu lesen. Zuerst wurde ein Signal &amp;quot;1&amp;quot; also P1 mit 395 Mikrosekunden high (die Zeitdauer ergibt sich aufgrund der Mitteilung &amp;quot;P1=395&amp;quot;) und anschließend ein Signal &amp;quot;5&amp;quot; also P5 mit 8916 Mikrosekunden low (die Zeitdauer ergibt sich aufgrund der Mitteilung &amp;quot;P5=-8916&amp;quot;) gemessen. CP=1 ist die Referenz auf den Takt des Signales - der Basistakt ist in diesem Fall ~395 Mikrosekunden. SP=5 gibt die Referenz zum Syncpuls an, der das gesamte Signal einleitet. Welche Signalfolge nun eine binäre 1 bzw. 0 bedeutet, wird im SIGNALduino über die integrierte Protokoll Liste realisiert.&lt;br /&gt;
&lt;br /&gt;
*MC - Nachricht vom Typ Manchester: Manchesterkodierte Signale können bereits sehr einfach im Arduino in eine Binärform umgewandelt werden. Es wird hier nach IEEE 802.3 umgewandelt. In Manchester Signalen gibt es lange und kurze Pulse. Deren Durchschnittswert wird mit LL (long low), LH (long high), SL (short low) und SH (short high) übermittelt. Zusätzlich, um das Protokoll schneller erkennen zu können, wird die Taktfrequenz mit übermittelt (C=429 Mikrosekunden). Die Daten befinden sich hinter D= und werden in HEX Form übergeben.&lt;br /&gt;
:&amp;lt;code&amp;gt;MC;LL=-1066;LH=904;SL=-562;SH=385;D=332B4B4D54D5554B552CD2D554B2B5354A;C=429;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*MU - Message unsynced: Diese Art von Nachrichten sind nicht nach Manchester codiert und haben auch keinen erkennbaren Sync / Clock Signalpegel am Start der Nachricht. Bei diesen Nachrichtentypen ist es, im Vergleich zu den anderen, am wahrscheinlichsten, dass das übermittelte Signal unvollständig oder überhaupt kein Signal ist. Wie bei MS sind P0-P6 die Signalpegel und in D= wird die Abfolge der Signalpegel referenziert. CP=2 gibt auch hier die Referenz zum Takt an, allerdings muss dieser nicht korrekt erkannt worden sein.&lt;br /&gt;
:&amp;lt;code&amp;gt;MU;P0=1372;P1=-580;P2=362;P3=-1047;D=01212321212321212121212121212123212123212321232121212121212321;CP=2;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es erscheinen viele Meldungen dieser Art:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Fingerprint for MU Protocol id xxxx -&amp;gt; yyy matches, trying to demodulate&lt;br /&gt;
sduino: Starting demodulation at Position 1&lt;br /&gt;
Fingerprint for MU Protocol id 28 -&amp;gt; IC Ledspot matches, trying to demodulate&lt;br /&gt;
sduino: Starting demodulation at Position 1&lt;br /&gt;
Fingerprint for MU Protocol id 29 -&amp;gt; HT12e remote matches, trying to demodulate&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dies sind nun Bemühungen, anhand der von der SIGNALDuino-Firmware gelieferten rohen aber detaillierten Signal-Strings eine Vor-Analyse / Fingerprinting vorzunehmen.&lt;br /&gt;
Man könnte nun z.B. bei solchen Fingerprinting-Analysen erkennen:&lt;br /&gt;
* dass der Basis-Takt-Wert innerhalb eines charakteristischen Zeit-Bereichs liegt&lt;br /&gt;
* dass die Anzahl der Sync-Pulse eine präzise Zahl ist&lt;br /&gt;
* dass Längen erkannter Puls-Typen innerhalb eines Bereichs liegen&lt;br /&gt;
&lt;br /&gt;
Mittels solcher Untersuchungen kann man also final hoffentlich hinreichend plausibel feststellen, &amp;quot;dass diese Aktivitäten offensichtlich(?) zu einer Funk-Komponente Rauchmelder von Hersteller XYZ gehören müssen, und man somit weiterleiten muss an ein (möglicherweise bereits existierendes) Userdaten-Dekodier-Modul für diese Herstellerkomponente&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Bei einer dann erfolgenden Demodulation des noch rohen SIGNALDuino-Strings könnte man z.B. (hoffentlich richtigerweise) annehmen, dass eine Signalpegel-Typ-Folge &amp;quot;13&amp;quot; eine binäre 1 bedeuten soll, während eine Folge &amp;quot;12&amp;quot; eine binäre 0 bedeuten soll. Man erhält aus dem Gesamt-Puls-String also nach vollständiger Demodulation eine Abfolge von vielen 0/1 Bits, die insgesamt ein Datenwort darstellen, mit einer gewissen Länge von NN bits (diese Längen-Angabe könnte übrigens - neben Namenssuche nach Hersteller oder Produkt etc. - ein wichtiges Such-Merkmal sein, ob andere Frameworks tatsächlich bereits wissen, wie Daten dieser Funk-Komponente zu dekodieren sind!). Dieses demodulierte Datenwort ist nun das finale Datenwort, welches einen Container für die Funk-Komponenten-Informationen darstellt (in diesem Container also beispielsweise enthalten: Temperatur, Feuchte, Akku-Status, ID, Alarm, ... - zumindest wenn nicht dummerweise der ganze Container erst einmal CRC- oder Crypto-verschlüsselt ist...).&lt;br /&gt;
&lt;br /&gt;
Man muss an dieser Stelle unbedingt sagen, dass dieses Userdaten-Datenwort (einer bestimmten Hersteller-Funk-Komponente!) natürlich bei &#039;&#039;jeglichen&#039;&#039; Transceiver-Systemen &#039;&#039;immer&#039;&#039; gleich erkannt werden &#039;&#039;muss&#039;&#039; - an dieser Stelle ist also ganz klar, dass diese Daten an &#039;&#039;allgemeine&#039;&#039; FHEM-Module weitergeleitet (Dispatched) werden müssen, die nach Übernahme von Daten von &#039;&#039;jeglichen&#039;&#039; Transceiver-Systemen diese Daten immer auf die gleiche Weise (&#039;&#039;&#039;&#039;&#039;generisch/zentral&#039;&#039;&#039;&#039;&#039;) für die jeweilige Hersteller-Funk-Komponente erledigen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Die Abfolge ist also ganz klar:&#039;&#039;&#039;&lt;br /&gt;
Funk-Aktivität --&amp;gt; Transceiver-Gerät/Firmware (SIGNALDuino) --&amp;gt; maximal detailreich beschreibender Rx-Analyse-Output-String --&amp;gt; Fingerprinting-Grobzuordnung des (SIGNALDuino-Firmware-)Outputs (durch 00_SIGNALduino.pm) auf gerätespezifisches Verhalten --&amp;gt; &#039;&#039;generische/zentrale&#039;&#039; Dekodierung des gerätespezifischen Protokoll-Datenworts, in zentralen Grundsatz-Modulen wie z.B. &amp;lt;code&amp;gt;14_SD_WS.pm&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Und wenn dann bei einer solchen Schritte-Abfolge irgendetwas noch fehlen/unpassend sein sollte, dann muss eben entsprechendes Development an gewissen Stellen erfolgen ;-)&lt;br /&gt;
&lt;br /&gt;
====Minimieren (whitelist/blacklist) von unerwünschter Kommunikations-Aktivität/Einträgen====&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Unknown Code&amp;quot; bedeutet, dass der SIGNALduino Signaldaten empfangen und diese binär interpretiert hat. Diese Meldung soll uns nun aber mitteilen, dass es dann nicht weiter verarbeitet werden kann, da kein Modul  existiert (oder kein Weiterleitungs-Dispatch zu einem bereits existierenden), welches diese Daten jetzt in ihre Bedeutung umwandeln kann. &lt;br /&gt;
:&amp;lt;code&amp;gt;sduino: Unknown code u1FFFFF0, help me!&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Außerdem kommt es gehäuft zu Logmeldungen und auch Events in ähnlicher Form:&lt;br /&gt;
:&amp;lt;code&amp;gt;SIGNALduino_unknown incomming msg: u85#FF8081&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mittlerweile sind über 50 Protokolle für den SIGNALduino definiert. Dadurch kommt es vor, dass sich ein Signal mit mehr als einem Protokoll demodulieren lässt. Meist führt dies dann zu zusätzlichen &amp;quot;Unknown code&amp;quot;-Einträgen.&lt;br /&gt;
&lt;br /&gt;
Derartige Einträge können mit dem Attribut WhitelistID minimiert werden. Dabei werden die Geräte, die nach Daten-Empfang tatsächlich verarbeitet werden sollen (also welche Protokolle vom FHEM Modul berücksichtigt werden), mit ihrer Protokollnummer in die WhitelistID aufgenommen.&lt;br /&gt;
Für Protokolle, die nicht berücksichtigt werden, gibt es weder Logeinträge noch Events. Diese werden im Programmablauf nicht berücksichtigt. Das spart zum einen Ressourcen und trägt auch zur Übersichtlichkeit bei. &lt;br /&gt;
Die Protokollnummer kann Tabelle [[#Unterst.C3.BCtzte_Ger.C3.A4te|Unterstützte Geräte]] entnommen werden (hilfreich ist es auch, wenn in den verwendeten Geräten im Internal &amp;lt;gerätename&amp;gt;_DMSG nachgesehen wird). So bedeutet beispielsweise ein Eintrag der Form &amp;lt;code&amp;gt;W50#FF553335FFBC&amp;lt;/code&amp;gt; dass dann das Protokoll  #50 in die Whitelist aufzunehmen wäre (&amp;lt;code&amp;gt;attr sduino whitelist_IDs 50&amp;lt;/code&amp;gt;).&lt;br /&gt;
{{Randnotiz|RNTyp=r|RNText=Achtung Schreibweise: Dokumentation oft als WhitelistID o.ä., aber Name ist whitelist_IDs!!&lt;br /&gt;
}}&lt;br /&gt;
Die Angabe erfolgt durch Komma getrennt: z.B.:&lt;br /&gt;
:&amp;lt;code&amp;gt;1,2,5,10&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Senden mit dem SIGNALduino ===&lt;br /&gt;
Der SIGNALduino kann etwas &amp;quot;raw senden&amp;quot;, indem ihm das SIGNAL so übermittelt wird, wie er es moduliert. Hierzu  muss der Befehl wie folgt eingegeben werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
set sduino sendMsg P3#00111010#R4&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dieser Befehl moduliert die Bitfolge 00111010 mittels Protokoll #3 und wiederholt die Nachricht 4x.&lt;br /&gt;
Die Protokoll Nummer kann aus einer empfangenen Nachricht extrahiert werden. Ebenso die Bits.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
sduino: extracted data 00111010 (bin)&lt;br /&gt;
sduino: Found Protocol id 3 &lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternativ kann das Signal auch in einer &amp;quot;rohform&amp;quot; angegeben werden. Dies ist manchmal in speziellen Fällen notwendig:&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
set sduino raw SR;;R=3;;P0=4742;;P1=-1554;;P2=286;;P3=-786;;P4=649;;P5=-420;;D=0123234545234545452323232323454523234523454523232345454523232323452345234523452345;;&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
R=3 bedeutet, das Signal wird 3x gesendet.&lt;br /&gt;
Die Übertragung besteht aus den in D angegeben Pulsen, welche in P0-P5 definiert werden.&lt;br /&gt;
Die Daten kann man aus einer empfangenen MS oder MU Nachricht extrahieren.&lt;br /&gt;
&lt;br /&gt;
Alternativ kann ab Version 3.2 auch eine vereinfachte Form eingegeben werden.&lt;br /&gt;
&lt;br /&gt;
====Fehlersuche====&lt;br /&gt;
(Zielgerät reagiert nicht, etc.)&lt;br /&gt;
&lt;br /&gt;
* Nachrichtenwiederholungsanzahl muss evt. für manche Geräte entsprechend groß eingestellt sein&lt;br /&gt;
{{Randnotiz|RNTyp=r|RNText=VORSICHT blöder Schreibweisen-Mismatch ITClock vs. ITclock!!}}&lt;br /&gt;
* Sende-Takt-Wert (Clock) passt evt. nicht ganz, siehe z.B. Thread-Antwort {{Link2Forum|Topic=58397|Message=775434|LinkText=Signalduino Version 3.3.1}}, wo für IT-Geräte ein Attribut anhand der CP= des Empfangsdaten-Logs modifiziert wird. ACHTUNG: dies kann entweder global das Internal-Attribut ITClock eines SIGNALduino-Transceiver-Devices sein, oder (viel besser da korrekt geräte-instanz-spezifische Konfiguration) das ITclock eines IT-Client-Devices.&lt;br /&gt;
&lt;br /&gt;
== Fehlerbehandlung ==&lt;br /&gt;
Der SIGNALduino kann mit folgendem Befehl auf Werkseinstellungen zurückgesetzt werden:&lt;br /&gt;
:&amp;lt;code&amp;gt;set raw e&amp;lt;/code&amp;gt;&lt;br /&gt;
Ob ein solcher Reset nötig ist, erkennt man an dem Inhalt vom Reading &amp;lt;code&amp;gt;cc1101_config&amp;lt;/code&amp;gt;, dort unsinnige Werte angezeigt werden oder dem Reading  &amp;lt;code&amp;gt;config&amp;lt;/code&amp;gt; welches durch den Befehl &amp;quot;get config&amp;quot; aktualisiert wird, was im Standard auf &amp;quot;MS=1;MU=1;MC=1&amp;quot; entspricht.&lt;br /&gt;
&lt;br /&gt;
In der Firmware sind die diverse Befehle eingebaut, welche über einen &amp;lt;code&amp;gt;set raw&amp;lt;/code&amp;gt; Befehl im Modul direkt ausgeführt werden können. Sofern möglich, sollten die Abfrage von Werten aus dem Modul allerdings mit den dafür vorgesehenen Kommandos erfolgen, da die Rückmeldungen des &amp;lt;code&amp;gt;set raw&amp;lt;/code&amp;gt; Befehls nur im Logfile ab Verbose 4 erscheinen. Die Befehle sind nützlich, wenn direkt auf den Microcontroller zugegriffen wird: &lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;C&amp;lt;reg&amp;gt;&amp;lt;/code&amp;gt; &amp;lt;reg&amp;gt; is a (two digit) hex number: return the value of the cc1101 register. &amp;lt;reg&amp;gt;=99 dumps the first 48 registers. Example: &amp;lt;code&amp;gt;set raw C35&amp;lt;/code&amp;gt; führt ab Verbose 4 zu einer Logausgabe folgender Art  &amp;lt;code&amp;gt;Read, msg: C35 = 0D&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;e&amp;lt;/code&amp;gt; EEPROM / factory reset.  resets all eeprom values without reboot&lt;br /&gt;
:&amp;lt;code&amp;gt;W&amp;lt;AA&amp;gt;&amp;lt;XX&amp;gt;&amp;lt;/code&amp;gt; Write eeprom (schreibt einen Wert ins EEPROM und ins CC1101 Register. Die eeprom Adresse hat einen Offset von 2. z.B W041D schreibt 1D ins Register 2 des CC1101)&lt;br /&gt;
&lt;br /&gt;
Die Sendeleistung lässt sich mit &lt;br /&gt;
:&amp;lt;code&amp;gt;get sduino ccpatable&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
prüfen, wobei die Rückmeldung wie folgt zu lesen ist: &lt;br /&gt;
  &amp;quot;-10_dBm&amp;quot;  =&amp;gt; &#039;34&#039;,&lt;br /&gt;
  &amp;quot;-5_dBm&amp;quot;   =&amp;gt; &#039;68&#039;,&lt;br /&gt;
  &amp;quot;0_dBm&amp;quot;    =&amp;gt; &#039;60&#039;,&lt;br /&gt;
  &amp;quot;5_dBm&amp;quot;    =&amp;gt; &#039;84&#039;,&lt;br /&gt;
  &amp;quot;7_dBm&amp;quot;    =&amp;gt; &#039;C8&#039;,&lt;br /&gt;
  &amp;quot;10_dBm&amp;quot;   =&amp;gt; &#039;C0&#039; &lt;br /&gt;
Dabei wird die Sendeleistung dauerhaft mit dem Befehl&lt;br /&gt;
:&amp;lt;code&amp;gt;set sduino cc1101_patable &amp;lt;value&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
hochgeschaltet (&amp;lt;value&amp;gt; durch den Wert ersetzen).&lt;br /&gt;
&lt;br /&gt;
Weitere Firmware-Befehle sind im Thread-Beitrag {{Link2Forum|Topic=58396|Message=497921}} zu finden.&lt;br /&gt;
&lt;br /&gt;
== Foren Links ==&lt;br /&gt;
* {{Link2Forum|Topic=38402|LinkText=Forenthread - Ankündigung}}&lt;br /&gt;
* {{Link2Forum|Topic=58396|LinkText=SIGNALDuino Empfänger Firm- und Hardware}}&lt;br /&gt;
* {{Link2Forum|Topic=82379|Message=1033374|LinkText=SIGNALDuino Schaltplan}}&lt;br /&gt;
* {{Link2Forum|Topic=58397|LinkText=Signalduino Entwicklung Version 3.3.1 }}&lt;br /&gt;
* [http://www.rflink.nl/blog2/wiring Beschreibung zu diversen Empfängern und Verbesserung der Empfangsleistung]&lt;br /&gt;
* [[SIGNALduino in die Arduino Entwicklungsumgebung einbinden]]&lt;br /&gt;
* [[Somfy via SIGNALduino]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Interfaces]]&lt;br /&gt;
[[Kategorie:Arduino]]&lt;br /&gt;
[[Kategorie:433MHz]]&lt;br /&gt;
[[Kategorie:868MHz]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Volume&amp;diff=33094</id>
		<title>FTUI Widget Volume</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Volume&amp;diff=33094"/>
		<updated>2020-04-25T19:36:00Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: /* Farbauswahl für Beleuchtung */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das [[{{PAGENAME}}|Volume Widget]] ist ein Widget für [[FHEM Tablet UI]], das eine Einstellscheibe zur Änderung eines einzelnen Wertes zur Verfügung stellt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:FTUI_Widget_Volume_01.png&lt;br /&gt;
File:FTUI_widget_volume-rgb.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Attribute==&lt;br /&gt;
Für das Volume-Widget gelten alle Attribute des [[FTUI Widget Knob|Knob-Widgets]]. Und zusätzlich die folgenden:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Standard-Wert&lt;br /&gt;
!Beispiel&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get&#039;&#039;&#039;||Name des Readings, das den darzustellenden Wert enthält||STATE||data-get=&amp;quot;volume&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set&#039;&#039;&#039;||Name des Readings, dessen Wert geändert werden soll||||data-set=&amp;quot;volume&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-cmd&#039;&#039;&#039;||Name des Befehls, mit dem das Reading geändert wird (z.B. setstate, set, setreading, trigger)||set||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get-value&#039;&#039;&#039;||[[Regulärer Ausdruck|RegEx]] oder Position des Wertes in einer leerzeichen-getrennten Textzeile, mit der der Wert erhalten werden kann||-1 -&amp;gt; alles anzeigen||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-set-value&#039;&#039;&#039;||Format des Wertes, wie er an FHEM gesendet werden soll||$v (nur der Wert)||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-min&#039;&#039;&#039;||Mindestwert, der gesetzt werden kann||0||data-min=&amp;quot;10&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-max&#039;&#039;&#039;||Maximalwert, der gesetzt werden kann||70||data-max=&amp;quot;100&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-tickstep&#039;&#039;&#039;||Abstand zwischen den einzelnen Schritten||4/20||data-tickstep=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-unit&#039;&#039;&#039;||Einheit zum gewünschten Wert hinzufügen||||&amp;lt;nowiki&amp;gt;data-unit=&amp;quot;&amp;amp;deg&amp;quot;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==CSS Klassen==&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
{{FTUI Klasse|mini}}{{FTUI Klasse|small}}{{FTUI Klasse|big}}{{FTUI Klasse|bigger}}{{FTUI Klasse|hue-tick}}{{FTUI Klasse|hue-front}}{{FTUI Klasse|hue-back}}{{FTUI Klasse|dim-tick}}{{FTUI Klasse|dim-front}}{{FTUI Klasse|dim-back}}{{FTUI Klasse|readonly}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
===Lautstärke===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;volume&amp;quot;&lt;br /&gt;
     data-device=&amp;quot;AVReceiver&amp;quot;&lt;br /&gt;
     data-get=&amp;quot;volume&amp;quot;&lt;br /&gt;
     data-set=&amp;quot;volume&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Datei:FTUI Widget Volume 01.png]]&lt;br /&gt;
&lt;br /&gt;
===Farbauswahl für Beleuchtung===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;volume&amp;quot;&lt;br /&gt;
	 data-device=&amp;quot;WZ.Deckenlampe&amp;quot;&lt;br /&gt;
	 data-get=&amp;quot;hue&amp;quot;&lt;br /&gt;
	 data-set=&amp;quot;hue&amp;quot;&lt;br /&gt;
	 data-min=&amp;quot;0&amp;quot;&lt;br /&gt;
	 data-max=&amp;quot;65535&amp;quot;&lt;br /&gt;
	 class=&amp;quot;hue-tick hue-front small top-space-2x&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[Datei:FTUI_widget_volume-rgb.png]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:FHEM Tablet UI|Volume]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FHEM_Tablet_UI&amp;diff=33069</id>
		<title>FHEM Tablet UI</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FHEM_Tablet_UI&amp;diff=33069"/>
		<updated>2020-04-14T19:47:30Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: /* Templates */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=Oberfläche für FHEM&lt;br /&gt;
|ModType=x&lt;br /&gt;
|ModFTopic=34233&lt;br /&gt;
|ModForumArea=TabletUI&lt;br /&gt;
|ModTechName=n.a.&lt;br /&gt;
|ModOwner=setstate ({{Link2FU|7023|Forum}})&lt;br /&gt;
}}&lt;br /&gt;
[[FHEM Tablet UI]] (FTUI) ist ein leichtgewichtiges aber funktionsreiches Frontend-Framework zum Steuern und Überwachen von in FHEM integrierten Geräten. Es basiert auf HTML/CSS/JavaScript und stellt somit keine zusätzlichen Anforderungen an den FHEM-Server.&lt;br /&gt;
&lt;br /&gt;
Mit Hilfe zahlreicher Widgets, die sehr leicht mit HTML Code konfiguriert werden können, ist es möglich, innerhalb kurzer Zeit ein den eigenen Wünschen entsprechendes User-Interface aufzubauen.&lt;br /&gt;
&lt;br /&gt;
Für den Betrieb ist nur eine FHEM-Installation mit [[HTTPSRV|HTTPSRV-Modul]] sowie ein gängiger Webbrowser notwendig.&lt;br /&gt;
&lt;br /&gt;
Mit wenigen Anpassungen ist es auch möglich, das UI auf anderen Webservern (Apache, u.a.) zu betreiben. Somit können FHEM und FHEM Tablet UI auch auf getrennten Systemen ausgeführt werden.&lt;br /&gt;
&lt;br /&gt;
[[File:tablet_ui.png|thumb|500px|center|Beispiel für ein mit [[FHEM Tablet UI]] erstelltes User-Interface]]&lt;br /&gt;
&lt;br /&gt;
{{Todo|Design-Möglichkeiten erklären, Navigationsmethoden ausformulieren}} &lt;br /&gt;
&lt;br /&gt;
== Installation ==&lt;br /&gt;
Die Installation von FHEM Tablet UI erzeugt keinen großen Aufwand und besteht im Großen und Ganzen aus drei Schritten:&lt;br /&gt;
*Dateien aus dem GitHub-Repository herunterladen&lt;br /&gt;
*FHEM konfigurieren ([[HTTPSRV]]-Device erstellen, [[FHEMWEB]]-Attribut longpoll einstellen)&lt;br /&gt;
*Eine Beispieldatei anlegen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|Diese Anleitung geht davon aus, dass FHEM unter Debian nach der Anleitung [https://debian.fhem.de Stable build using apt] installiert wurde.&lt;br /&gt;
Ist dies nicht der Fall, muss der Pfad &#039;&#039;&#039;/opt/fhem&#039;&#039;&#039; dementsprechend angepasst werden.}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;1.&#039;&#039;&#039; Zuerst müssen alle Dateien von FHEM Tablet UI in das FHEM-Verzeichnis &#039;&#039;&#039;/opt/fhem/www&#039;&#039;&#039; kopiert werden. Das geht mit folgendem &#039;&#039;&#039;update&#039;&#039;&#039;-Befehl über die FHEM-Befehlszeile.&lt;br /&gt;
:&amp;lt;code&amp;gt;update all https://raw.githubusercontent.com/knowthelist/fhem-tablet-ui/master/controls_fhemtabletui.txt&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:[[Datei:FTUI_Installation_01.png|thumb|none|Schritt 1: Dateien kopieren]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;2.&#039;&#039;&#039; Anschließend ist ein neues [[HTTPSRV]]-Device in FHEM anzulegen, welches auf den Ordner mit den gerade heruntergeladenen Dateien verweist.&lt;br /&gt;
:&amp;lt;code&amp;gt;define TABLETUI HTTPSRV ftui/ ./www/tablet/ Tablet-UI&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:[[Datei:FTUI_Installation_02.png|thumb|none|Schritt 2: HTTPSRV-Device anlegen]]&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|Dieser Schritt kann ausgelassen werden, wenn die Funktionalitäten von [[FHEMWEB]] ausreichend sind. Dann muss FTUI aber in weiterer Folge unter der URL &#039;&#039;&#039;&amp;lt;nowiki&amp;gt;http(s)://&amp;lt;fhem-server&amp;gt;:8083/fhem/tablet/index.html&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039; aufgerufen werden und es wird kein Link auf FTUI in der FHEM GUI erstellt. Vorteil ist aber, dass das FHEMWEB-Caching verwendet werden kann. Siehe dieser {{Link2Forum|Topic=86362|Message=788258}}.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;3.&#039;&#039;&#039; Damit FHEM Tablet UI mit FHEM kommunizieren kann, ist noch die &#039;&#039;&#039;longpoll&#039;&#039;&#039;-Einstellung im [[FHEMWEB]] Device festzulegen.&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;attr WEB longpoll websocket&amp;lt;/code&amp;gt;&lt;br /&gt;
:bzw. bei Problemen mit &#039;&#039;websocket&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;attr WEB longpoll 1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:[[Datei:FTUI_Installation_03.png|thumb|none|Schritt 3: longpoll einstellen]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;4.&#039;&#039;&#039; Weil FTUI noch nichts anzuzeigen hat, wird die Datei &#039;&#039;&#039;/opt/fhem/www/tablet/index-example.html&#039;&#039;&#039; nach &#039;&#039;&#039;/opt/fhem/www/tablet/index.html&#039;&#039;&#039; kopiert.&lt;br /&gt;
:&amp;lt;code&amp;gt;sudo cp -a /opt/fhem/www/tablet/index-example.html /opt/fhem/www/tablet/index.html&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:[[Datei:FTUI_Installation_04.png|thumb|none|Schritt 4: index.html erstellen]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;5.&#039;&#039;&#039; Abschließend muss FHEM noch &#039;&#039;&#039;neu gestartet&#039;&#039;&#039; werden (&#039;&#039;shutdown restart&#039;&#039;) da das Attribut &#039;&#039;&#039;longpoll&#039;&#039;&#039; geändert wurde.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Somit ist FHEM Tablet UI bereit zur Verwendung und kann durch Aufruf der URL &#039;&#039;&#039;&amp;lt;nowiki&amp;gt;http://&amp;lt;fhem-server&amp;gt;:8083/fhem/ftui/&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039; oder den Link im FHEM-Menü geöffnet werden&lt;br /&gt;
&lt;br /&gt;
== Update ==&lt;br /&gt;
Ein Update von FTUI kann ebenfalls über die FHEM-Kommandozeile erfolgen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;1.&#039;&#039;&#039; Prüfen der Änderungen seit dem letzten Download/Update durch Eingabe von:&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;update check https://raw.githubusercontent.com/knowthelist/fhem-tablet-ui/master/controls_fhemtabletui.txt&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;2.&#039;&#039;&#039; Update der geänderten Dateien durch Eingabe von:&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;update all https://raw.githubusercontent.com/knowthelist/fhem-tablet-ui/master/controls_fhemtabletui.txt&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Eine weitere Option ist das Hinzufügen des FTUI-Git-Repositories zum allgemeinem Update-Vorgang von FHEM. Dabei wird dann bei einem FHEM-Update auch gleich FHEM Tablet UI aktualisiert, bzw. die Änderungen angezeigt.&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;update add https://raw.githubusercontent.com/knowthelist/fhem-tablet-ui/master/controls_fhemtabletui.txt&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beachte: Das Ergebnis des o.g. Befehls wird in FHEM/controls.txt eingetragen, siehe auch [[Update#update_add]]&lt;br /&gt;
&lt;br /&gt;
== Konfiguration ==&lt;br /&gt;
===DOCTYPE===&lt;br /&gt;
In allen HTML-Dateien, die im Browser geladen werden und das typische HTML-Gerüst besitzen (also alle Hauptseiten, jedoch keine Template-Dateien), sollte eine &#039;&#039;Document Type Declaration&#039;&#039; (DTDT) eingefügt werden. Mit ihr wird festgelegt, welche &#039;&#039;Document Type Definition&#039;&#039; hier verwendet wird (das kommt aus der Metasprache XML), konkret also, in welcher Version der nachfolgende HTML-Code vom Browser interpretiert werden soll. Lässt man die DTDT weg, oder definiert sie auf verschiedenen Seiten unterschiedlich, kann ein und der selbe HTML-Code zu unterschiedlichen Darstellungen führen. Die DTDT erfolgt immer auf der ersten Zeile, noch vor dem &amp;lt;code&amp;gt;&amp;lt;html&amp;gt;&amp;lt;/code&amp;gt;-Tag. Nachfolgend wird HTML5 verwendet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE html&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
    &amp;lt;head&amp;gt;...&amp;lt;/head&amp;gt;&lt;br /&gt;
    &amp;lt;body&amp;gt;...&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===META-Parameter===&lt;br /&gt;
Das Tablet UI lässt sich über die META-Parameter konfigurieren. Diese Parameter sind in jeder &#039;&#039;&#039;.html&#039;&#039;&#039; Datei (z.B. index.html) im Abschnitt &#039;&#039;&#039;&amp;lt;head&amp;gt;&#039;&#039;&#039; einzutragen. Ausgenommen davon sind Dateien, die als Template, Pagebutton-Zielseiten oder ähnliches eingebunden werden.&lt;br /&gt;
&lt;br /&gt;
Die Parameter sind immer nach diesem Schema aufgebaut:&lt;br /&gt;
 &amp;lt;meta name=&amp;quot;[Parameter-Name]&amp;quot; content=&amp;quot;[Parameter-Wert]&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Verbindung zu FHEM===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!Parameter-Name!!Standard-Wert!!Mögliche Werte!!Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
|web_device||WEB||String||FHEM-Device, welches für das Polling verwendet wird&lt;br /&gt;
|-&lt;br /&gt;
|longpoll||1||0, 1||&lt;br /&gt;
&#039;&#039;&#039;0&#039;&#039;&#039;: Longpoll deaktiviert; alle 30s ein Shortpoll (Neuladen der gesamten Statusänderungen)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;1&#039;&#039;&#039;: Longpoll aktiv; geänderte Stati werden sofort aktualisiert, zusätzlich werden alle 15min die gesamten Statusänderungen geladen.&lt;br /&gt;
|-&lt;br /&gt;
|longpoll_type||websocket||websocket, ajax, 0||&lt;br /&gt;
&#039;&#039;&#039;websocket&#039;&#039;&#039;: Für die Aktualisierung der Daten wird das Websocket-Protokoll verwendet. Werden vom Browser keine Websockets unterstützt, gibt es einen automatischen Fallback auf Ajax.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ajax&#039;&#039;&#039;: Ajax wird für die Aktualisierung verwendet.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;0&#039;&#039;&#039;: Longpoll deaktiviert, Shortpoll wird verwendet.&lt;br /&gt;
|-&lt;br /&gt;
|longpoll_filter||.*||RegEx||Event-Filter. Kann verwendet werden, wenn z.B. Devices, die in FTUI angezeigt werden, in einem eigenen FHEM-Room sind.&lt;br /&gt;
|-&lt;br /&gt;
|longpoll_maxage||240||Integer||Kommen in diesem Zeitraum (Sekunden) keine Longpoll-Events bei FTUI an, wird die Verbindung als &amp;quot;disconnected&amp;quot; angesehen und ein neuer Verbindungsversuch wird gestartet.&lt;br /&gt;
|-&lt;br /&gt;
|shortpoll_interval||900||Integer||Zeitraum in Sekunden, nach dem ein vollständiger Refresh stattfindet&lt;br /&gt;
|-&lt;br /&gt;
|shortpoll_only_interval||30||Integer||Zeitraum in Sekunden, nach dem ein vollständiger Refresh stattfindet, sollte Longpoll deaktiviert sein&lt;br /&gt;
|-&lt;br /&gt;
|fhemweb_url||/fhem/||Integer||URL zu FHEM. Wird benötigt wenn FTUI auf einem anderen als dem FHEM Server läuft oder nicht im Standard-Pfad installiert ist. &lt;br /&gt;
Hinweis: Wenn FHEM auf einem anderem Server/Domain läuft muss man das &amp;quot;CORS&amp;quot; Attribut im FHEMWEB Modul (s.o.) auf 1 setzen, sonst bekommt man Cross Origin Fehler. &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Funktionalität===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!Parameter-Name!!Standard-Wert!!Mögliche Werte!!Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
|debug||0||0 - 5||Log-Level&lt;br /&gt;
|-&lt;br /&gt;
|toast||5||Integer||Anzahl an gleichzeitig angezeigten Toast-Nachrichten. Um keine anzuzeigen, ist der Wert auf 0 zu setzen.&lt;br /&gt;
|-&lt;br /&gt;
|toast_position||bottom-left||||Position im Browserfenster, wo die Toast-Nachrichten angezeigt werden.&lt;br /&gt;
|-&lt;br /&gt;
|lang||de||de||Sprache der Oberfläche (für z.B. Datums-/Zeitfunktionen)&lt;br /&gt;
|-&lt;br /&gt;
|username||||String||Benutzername für eine Basic-Authentifierung *&lt;br /&gt;
|-&lt;br /&gt;
|password||||String||Passwort für eine Basic-Authentifizierung *&lt;br /&gt;
|}&lt;br /&gt;
&#039;&#039;&#039;*&#039;&#039;&#039; Derzeit wird die Basic-Authentifizierung in Kombination mit WebSockets nicht unterstützt. Die Verwendung von &#039;&#039;&#039;longpoll=1&#039;&#039;&#039; (ajax) ist daher notwendig.&lt;br /&gt;
&lt;br /&gt;
===Toast-Nachrichten===&lt;br /&gt;
[[Datei:Ftui_toast.png|thumb|Toast-Nachrichten]]&lt;br /&gt;
Tablet-UI liefert Informationen darüber, was im Moment gerade passiert. Das geschieht über Toast-Nachrichten, die in der Standardeinstellung unten links im Browser auftauchen.&lt;br /&gt;
&lt;br /&gt;
Wird beispielsweise ein Gerät eingeschaltet, so erscheint eine kleine Nachricht mit dem abgesetzten Befehl. Auch Fehlermeldungen und Statusinformationen werden angezeigt. Ob überhaupt und was konkret angezeigt wird, richtet sich nach dem eingestellten Debug-Level (siehe oben). Beim Debug-Level 5 werden alle Nachrichten angezeigt, bei 0 keine.&lt;br /&gt;
&lt;br /&gt;
Die Position der Toast-Nachrichten kann über den Meta-Tag &amp;lt;code&amp;gt;meta name=&#039;toast_position&#039;&amp;lt;/code&amp;gt; festgelegt werden. Für oben-mittig müsste folgender Code eingefügt werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;meta name=&#039;toast_position&#039; content=&#039;top-center&#039;&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Möglich sind folgende Positionen:&lt;br /&gt;
* &amp;lt;code&amp;gt;top-left&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;top-right&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;bottom-left&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;bottom-right&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;top-center&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;bottom-center&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;mid-center&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die maximale Anzahl an Nachrichten, die gleichzeitig angezeigt werden können, lässt sich mit &amp;lt;code&amp;gt;meta name=&#039;toast&#039;&amp;lt;/code&amp;gt; Sind maximal 2 Nachrichten gewünscht, muss folgender Meta-Tag gesetzt werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;meta name=&#039;toast&#039; content=&#039;2&#039;&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Navigationsmethoden==&lt;br /&gt;
{{Todo|Dieser Abschnitt dient derzeit lediglich als Sammlung von Stichpunkten und muss vollständig überarbeitet werden.}} &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Unterschied zwischen Pagetab und Pagebutton:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Pagetab:&#039;&#039;&#039; Ganze Seite austauschen -&amp;gt; Menü muss auf jede Seite&lt;br /&gt;
[[FTUI_Widget_Pagetab]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Pagebutton:&#039;&#039;&#039; Teil der Seite austauschen -&amp;gt; Menü nur in erster Seite&lt;br /&gt;
[[FTUI_Widget_Pagebutton]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Pagelink:&#039;&#039;&#039; damit kann man beliebige Widgets kapseln und vorhandene Pagebutton-Seiten ansteuern &lt;br /&gt;
[[FTUI Widget Link]]&lt;br /&gt;
&lt;br /&gt;
==Gestaltung==&lt;br /&gt;
===Layout-Optionen===&lt;br /&gt;
* [[FTUI Layout Gridster|Gridster]]&lt;br /&gt;
* [[FTUI Layout Flex|Flex]]&lt;br /&gt;
* [[FTUI Layout Sheet|Tabelle]]&lt;br /&gt;
* [[FTUI Layout Row|Reihen]]&lt;br /&gt;
&lt;br /&gt;
=== Farben ===&lt;br /&gt;
Es besteht die Möglichkeit, die Farbwerte in hexadezimaler Form, als RGB-Wert oder mit dem Farbnamen anzugeben. Zum Beispiel: &lt;br /&gt;
&lt;br /&gt;
*HEX: #ADD8E6&lt;br /&gt;
*RBG: rgb(173, 216, 230)&lt;br /&gt;
*Namen: lightblue&lt;br /&gt;
&lt;br /&gt;
Knallige Farben wie &#039;&#039;&#039;&amp;lt;span style=&amp;quot;color: #ff0000;&amp;quot;&amp;gt;#ff0000&amp;lt;/span&amp;gt;&#039;&#039;&#039; für Rot oder &#039;&#039;&#039;&amp;lt;span style=&amp;quot;color: #00ff00;&amp;quot;&amp;gt;#00ff00&amp;lt;/span&amp;gt;&#039;&#039;&#039; für Grün sollten vermieden werden.&lt;br /&gt;
Es ist besser unterhalb von #D0 (208) für die Grundfarben zu bleiben.&lt;br /&gt;
&lt;br /&gt;
Empfohlene Farben sind z.B.:&lt;br /&gt;
&lt;br /&gt;
*Orange: &amp;lt;span style=&amp;quot;color: #aa6900;&amp;quot;&amp;gt;#aa6900&amp;lt;/span&amp;gt;&lt;br /&gt;
*Rot: &amp;lt;span style=&amp;quot;color: #ad3333;&amp;quot;&amp;gt;#ad3333&amp;lt;/span&amp;gt;&lt;br /&gt;
*Grün: &amp;lt;span style=&amp;quot;color: #32a054;&amp;quot;&amp;gt;#32a054&amp;lt;/span&amp;gt;&lt;br /&gt;
*Blau: &amp;lt;span style=&amp;quot;color: #6699FF;&amp;quot;&amp;gt;#6699FF&amp;lt;/span&amp;gt;&lt;br /&gt;
*Grau: &amp;lt;span style=&amp;quot;color: #8C8C8C;&amp;quot;&amp;gt;#8C8C8C&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hilfreich bei der Suche nach den Farbwerten ist zum Beispiel der Color-Picker auf dieser Seite: http://www.colorpicker.com. Für die Suche nach Farben, die einen guten Kontrast bilden, diese Webseite: http://vanisoft.pl/~lopuszanski/public/colors/&lt;br /&gt;
&lt;br /&gt;
Im Ordner &#039;&#039;css&#039;&#039; der FTUI Installation finden sich einige vorbereitete Farbschemata. Diese können mit einem zusätzlichen Eintrag im &amp;lt;nowiki&amp;gt;&amp;lt;head&amp;gt;&amp;lt;/nowiki&amp;gt;-Bereich der FTUI-Seite(n) aktiviert werden.&lt;br /&gt;
&lt;br /&gt;
Hier am Beispiel eines blauen Farbschemas:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
   [...]&lt;br /&gt;
   &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;/fhem/tablet/css/fhem-blue-ui.css&amp;quot; /&amp;gt;&lt;br /&gt;
   [...]&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Schema-Dateien ändern alle Widgets. &lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:Theme_default.png|default&lt;br /&gt;
File:Theme_blue.png|fhem-blue-ui.css&lt;br /&gt;
File:Theme_green.png|fhem-green-ui.css&lt;br /&gt;
File:Theme_mobile.png|fhem-mobile-ui.css&lt;br /&gt;
File:Theme_darkblue.png|fhem-darkblue-ui.css&lt;br /&gt;
File:Theme_darkgreen.png|fhem-darkgreen-ui.css&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Einzelne Widgets können durch Hinzufügen der jeweiligen [[#CSS-Klassen|CSS-Klasse]] geändert werden.&lt;br /&gt;
&lt;br /&gt;
===CSS-Styles===&lt;br /&gt;
Das Layout und das Aussehen des UI kann durch diverse vorgegebene CSS-Klassen beeinflusst werden. Die verfügbaren Klassen sind im Abschnitt [[#CSS-Klassen|CSS-Klassen]] aufgeführt.&lt;br /&gt;
&lt;br /&gt;
Soll das Aussehen des UI durch eigene CSS-Klassen oder durch Überschreiben der vorhandenen verändert werden, kann eine eigene CSS-Datei erstellt werden, die dann bei einem eventuellen Update von FTUI nicht überschrieben wird. Diese Datei muss den Dateinamen &#039;&#039;&#039;fhem-tablet-ui-user.css&#039;&#039;&#039; haben und im Ordner &#039;&#039;&#039;/fhem/tablet/css&#039;&#039;&#039; abgelegt werden. Sie wird dann beim Aufruf von FTUI automatisch mitgeladen.&lt;br /&gt;
&lt;br /&gt;
=== CSS-Klassen ===&lt;br /&gt;
Nicht alle Widgets unterstützen alle hier angegebenen Klassen. Welche genau unterstützt werden, kann auf der jeweiligen Widget-Seite nachgelesen werden.&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: left;&amp;quot;|sheet/row/cell-Layout&lt;br /&gt;
|-&lt;br /&gt;
!class=&amp;quot;mw-collapsible-content&amp;quot;|Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|sheet}}{{FTUI Klasse|row}}{{FTUI Klasse|cell}}{{FTUI Klasse|cell-1-x}}{{FTUI Klasse|cell-x}}{{FTUI Klasse|left-align}}{{FTUI Klasse|right-align}}{{FTUI Klasse|bottom-align}}{{FTUI Klasse|top-align}}{{FTUI Klasse|center-align}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: left;&amp;quot;|row/col-Layout&lt;br /&gt;
|-&lt;br /&gt;
!class=&amp;quot;mw-collapsible-content&amp;quot;|Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|col}}{{FTUI Klasse|col-1-x}}{{FTUI Klasse|col-x}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: left;&amp;quot;|hbox/vbox-Layout&lt;br /&gt;
|-&lt;br /&gt;
!class=&amp;quot;mw-collapsible-content&amp;quot;|Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|vbox}}{{FTUI Klasse|hbox}}{{FTUI Klasse|card}}{{FTUI Klasse|phone-width}}{{FTUI Klasse|full-height}}{{FTUI Klasse|full-width}}{{FTUI Klasse|grow-0}}{{FTUI Klasse|grow-1}}{{FTUI Klasse|grow-2}}{{FTUI Klasse|grow-x}}{{FTUI Klasse|items-top}}{{FTUI Klasse|items-center}}{{FTUI Klasse|items-bottom}}{{FTUI Klasse|items-space-between}}{{FTUI Klasse|items-space-around}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: left;&amp;quot;|Generelle Klassen für die Positionierung&lt;br /&gt;
|-&lt;br /&gt;
!class=&amp;quot;mw-collapsible-content&amp;quot;|Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|inline}}{{FTUI Klasse|newline}}{{FTUI Klasse|top-space}}{{FTUI Klasse|top-space-2x}}{{FTUI Klasse|top-space-3x}}{{FTUI Klasse|left-space}}{{FTUI Klasse|left-space-2x}}{{FTUI Klasse|left-space-3x}}{{FTUI Klasse|right-space}}{{FTUI Klasse|right-space-2x}}{{FTUI Klasse|right-space-3x}}{{FTUI Klasse|top-narrow}}{{FTUI Klasse|top-narrow-2x}}{{FTUI Klasse|top-narrow-10}}{{FTUI Klasse|left-narrow}}{{FTUI Klasse|left-narrow-2x}}{{FTUI Klasse|left-narrow-3x}}{{FTUI Klasse|right-narrow}}{{FTUI Klasse|right-narrow-2x}}{{FTUI Klasse|right-narrow-3x}}{{FTUI Klasse|centered}}{{FTUI Klasse|wider}}{{FTUI Klasse|narrow}}{{FTUI Klasse|fullsize}}{{FTUI Klasse|compressed}}{{FTUI Klasse|height-narrow}}{{FTUI Klasse|w1x}}{{FTUI Klasse|w2x}}{{FTUI Klasse|w3x}}{{FTUI Klasse|maxw40}}{{FTUI Klasse|doublebox-v}}{{FTUI Klasse|doublebox-h}}{{FTUI Klasse|triplebox-v}}{{FTUI Klasse|right}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: left;&amp;quot;|Vordergrundfarben&lt;br /&gt;
|-&lt;br /&gt;
!class=&amp;quot;mw-collapsible-content&amp;quot;|Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|red}}{{FTUI Klasse|green}}{{FTUI Klasse|blue}}{{FTUI Klasse|lightblue}}{{FTUI Klasse|orange}}{{FTUI Klasse|gray}}{{FTUI Klasse|lightgray}}{{FTUI Klasse|white}}{{FTUI Klasse|black}}{{FTUI Klasse|mint}}{{FTUI Klasse|yellow}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: left;&amp;quot;|Hintergrundfarben&lt;br /&gt;
|-&lt;br /&gt;
!class=&amp;quot;mw-collapsible-content&amp;quot;|Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|bg-red}}{{FTUI Klasse|bg-green}}{{FTUI Klasse|bg-blue}}{{FTUI Klasse|bg-lightblue}}{{FTUI Klasse|bg-orange}}{{FTUI Klasse|bg-gray}}{{FTUI Klasse|bg-lightgray}}{{FTUI Klasse|bg-white}}{{FTUI Klasse|bg-black}}{{FTUI Klasse|bg-mint}}{{FTUI Klasse|bg-yellow}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: left;&amp;quot;|Rahmen&lt;br /&gt;
|-&lt;br /&gt;
!class=&amp;quot;mw-collapsible-content&amp;quot;|Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|verticalLine}}{{FTUI Klasse|border-black}}{{FTUI Klasse|border-white}}{{FTUI Klasse|border-orange}}{{FTUI Klasse|border-red}}{{FTUI Klasse|border-green}}{{FTUI Klasse|border-mint}}{{FTUI Klasse|border-lightblue}}{{FTUI Klasse|border-blue}}{{FTUI Klasse|border-gray}}{{FTUI Klasse|border-yellow}}{{FTUI Klasse|border-lightgray}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: left;&amp;quot;|Größen&lt;br /&gt;
|-&lt;br /&gt;
!class=&amp;quot;mw-collapsible-content&amp;quot;|Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|mini}}{{FTUI Klasse|tiny}}{{FTUI Klasse|small}}{{FTUI Klasse|normal}}{{FTUI Klasse|large}}{{FTUI Klasse|big}}{{FTUI Klasse|bigger}}{{FTUI Klasse|tall}}{{FTUI Klasse|great}}{{FTUI Klasse|grande}}{{FTUI Klasse|gigantic}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: left;&amp;quot;|Schriftstil&lt;br /&gt;
|-&lt;br /&gt;
!class=&amp;quot;mw-collapsible-content&amp;quot;|Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|thin}}{{FTUI Klasse|bold}}{{FTUI Klasse|darker}}{{FTUI Klasse|truncate}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: left;&amp;quot;|Sonstiges&lt;br /&gt;
|-&lt;br /&gt;
!class=&amp;quot;mw-collapsible-content&amp;quot;|Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|blank}}{{FTUI Klasse|transparent}}{{FTUI Klasse|half-transparent}}{{FTUI Klasse|blurry}}{{FTUI Klasse|shake}}{{FTUI Klasse|fail-shake}}{{FTUI Klasse|marquee}}{{FTUI Klasse|icon round}}{{FTUI Klasse|icon square}}{{FTUI Klasse|readonly}}{{FTUI Klasse|blink}}{{FTUI Klasse|rotate-90}}{{FTUI Klasse|horizontal}}{{FTUI Klasse|circleborder}}{{FTUI Klasse|autohide}}{{FTUI Klasse|notransmit}}{{FTUI Klasse|tap}}{{FTUI Klasse|FS20}}{{FTUI Klasse|value}}{{FTUI Klasse|novalue}}{{FTUI Klasse|timestamp}}{{FTUI Klasse|percent}}{{FTUI Klasse|nocache}}{{FTUI Klasse|fade}}{{FTUI Klasse|rotate}}{{FTUI Klasse|nolabels}}{{FTUI Klasse|default}}{{FTUI Klasse|prefetch}}{{FTUI Klasse|circulate}}{{FTUI Klasse|valueonly}}{{FTUI Klasse|positiononly}}{{FTUI Klasse|lineIndicator}}{{FTUI Klasse|barIndicator}}{{FTUI Klasse|roundIndicator}}{{FTUI Klasse|dim-tick}}{{FTUI Klasse|dim-front}}{{FTUI Klasse|dim-back}}{{FTUI Klasse|hue-tick}}{{FTUI Klasse|hue-front}}{{FTUI Klasse|hue-back}}{{FTUI Klasse|warn}}{{FTUI Klasse|activate}}{{FTUI Klasse|labelright}}{{FTUI Klasse|interlock}}{{FTUI Klasse|keepopen}}{{FTUI Klasse|noshade}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Überlagerung von Text und Bild ===&lt;br /&gt;
[[Datei:FTUI_Text_auf_Bild.png||thumb|right]]&lt;br /&gt;
Texte können auf Bildern positioniert werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;li data-row=&amp;quot;1&amp;quot; data-col=&amp;quot;4&amp;quot; data-sizey=&amp;quot;4&amp;quot; data-sizex=&amp;quot;6&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;display&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div data-type=&amp;quot;image&amp;quot; data-url=&amp;quot;https://picsum.photos/200/125/?random&amp;quot; data-size=&amp;quot;100%&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;display-center bigger&amp;quot; data-type=&amp;quot;label&amp;quot;&amp;gt;Text1&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;display-topright bigger right-space top-space&amp;quot; data-type=&amp;quot;label&amp;quot;&amp;gt;Text2&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;ontop bigger&amp;quot; style=&amp;quot;left: 120px; top: 50px&amp;quot;&amp;gt;Text3&amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zur Verfügung stehen folgende Grundpositionen:&lt;br /&gt;
* &amp;lt;code&amp;gt;display-topleft&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;display-topcenter&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;display-topright&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;display-centerleft&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;display-left&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;display-centerright&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;display-right&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;display-bottomleft&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;display-bottomcenter&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;display-bottomright&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Feinjustage ist möglich über&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;right-space&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;top-space&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;left-space&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;bottom-space&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;right-space-2&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;top-space-2&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;left-space-2&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;bottom-space-2&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;right-space-3&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;top-space-3&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;left-space-3&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;bottom-space-3&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:FTUI_Beispiel_Positionierung.png|200px|thumb|right]]&lt;br /&gt;
Verallgemeinert lassen sich auf diese Weise &#039;&#039;&#039;Objekte frei im Elternelement positionieren&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;display&amp;quot; data-type=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;display-topcenter top-space big&amp;quot;&amp;gt;Fenster&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;display-center fa fa-4x ftui-window&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
        &amp;lt;div class=&amp;quot;display-bottomleft bottom-space left-space&amp;quot; data-type=&amp;quot;label&amp;quot;&amp;gt;Text&amp;lt;/div&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
=== Icons ===&lt;br /&gt;
FTUI bringt einige Icons-&amp;quot;Schriftarten&amp;quot; mit, die für die Darstellung genützt werden können. Diese werden automatisch beim Start des UI eingebunden, sobald ein entsprechendes Icon-Präfix im Code der Seite vorkommt.&lt;br /&gt;
&lt;br /&gt;
Verfügbare Icon-Schriftarten sind:&lt;br /&gt;
* Eingebaute Icons &#039;&#039;ftui-window&#039;&#039; und &#039;&#039;ftui-door&#039;&#039;. Präfix &#039;&#039;&#039;ftui-&#039;&#039;&#039;. Beispiel: &amp;lt;code&amp;gt;data-icon=&amp;quot;ftui-door&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
* [http://fontawesome.io/icons/ Font-Awesome]: Mehr als 500 Icons zur Auswahl. Präfix &#039;&#039;&#039;fa-&#039;&#039;&#039;. Beispiel: &amp;lt;code&amp;gt;data-icon=&amp;quot;fa-volume-up&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
* [https://material.io/icons/ Material Icons]: Mehr als 900 Icons zur Auswahl. Präfix &#039;&#039;&#039;mi-&#039;&#039;&#039;. Beispiel: &amp;lt;code&amp;gt;data-icon=&amp;quot;mi-local_gas_station&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
* FHEM und OpenAutomation Icons: Präfix &#039;&#039;&#039;fs-&#039;&#039;&#039; und &#039;&#039;&#039;oa-&#039;&#039;&#039;. Beispiel: &amp;lt;code&amp;gt;data-icon=&amp;quot;oa-secur_locked&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
* [https://erikflowers.github.io/weather-icons/ Weather-Icons]: Präfix &#039;&#039;&#039;wi &#039;&#039;&#039;. Beispiel: &amp;lt;code&amp;gt;data-icon=&amp;quot;wi wi-day-rain-mix&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternativ können auch Bilder Icons (bspw. png) über CSS verwendet werden. Bspw:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
  &amp;lt;style type=&amp;quot;text/css&amp;quot;&amp;gt;&lt;br /&gt;
        .logo-fhem {&lt;br /&gt;
            background: url(https://wiki.fhem.de/fhemlogo.png) no-repeat;&lt;br /&gt;
            width: 120px;&lt;br /&gt;
            height: 132px;&lt;br /&gt;
            background-size: contain;&lt;br /&gt;
        }&lt;br /&gt;
  &amp;lt;/style&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
  &amp;lt;div data-type=&amp;quot;symbol&amp;quot; data-icon=&amp;quot;logo-fhem&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Widgets ==&lt;br /&gt;
===Allgemeine Attribute===&lt;br /&gt;
Jedes Widget kann über verschiedene Attribute konfiguriert werden. Folgende Attribute gelten für alle Widgets:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+allgemeine Attribute&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-type&lt;br /&gt;
|Widget-Typ&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-device&lt;br /&gt;
|FHEM-Name des Gerätes (mit dem Befehl &#039;list&#039; bekommt man im FHEM die kpl. Liste)&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |class&lt;br /&gt;
|CSS-Klassen für Aussehen und Formatierung des Widgets&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Daten Empfangen&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-get&lt;br /&gt;
|Reading Name&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-get-on&lt;br /&gt;
|Wert für den Status on&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-get-off&lt;br /&gt;
|Wert für den Status off&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Daten Senden&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-set&lt;br /&gt;
|Reading Name&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-set-on&lt;br /&gt;
|Wert für den Status on&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-set-off&lt;br /&gt;
|Wert für den Status off&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Widget-spezifische Attribute können auf der jeweiligen Widget-Seite nachgelesen werden.&lt;br /&gt;
&lt;br /&gt;
=== Integrierte Widgets ===&lt;br /&gt;
Folgende Widgets sind direkt in FHEM Tablet UI integriert und können &amp;quot;out of the box&amp;quot; verwendet werden.&lt;br /&gt;
&lt;br /&gt;
* [[FTUI Widget Button|button]]: Variante der push und switch Widgets, die entweder einen URL ansteuern oder einen FHEM-Befehl absetzen kann&lt;br /&gt;
* [[FTUI Widget Checkbox|checkbox]]: Umschalter zwischen zwei definierten Zuständen&lt;br /&gt;
* [[FTUI Widget Circlemenu|circlemenu]]: Mehrere Widgets hinter einem Widget verborgen, trotz des &#039;circle&#039; im Namen kann das Menue jetzt auch horizontal oder vertikal ausgeklappt werden &lt;br /&gt;
* [[FTUI Widget Clock|clock]]: Stellt eine einfache Uhr zur Verfügung&lt;br /&gt;
* [[FTUI Widget Colorwheel|colorwheel]]: Farbpalette zur Auswahl von Farben&lt;br /&gt;
* [[FTUI Widget Controlbutton|controlbutton]]: iOS-ähnlicher Button zum Schalten zwischen zwei Zuständen (z.B. on / off)&lt;br /&gt;
* [[FTUI Widget Controller|controller]]: iOS-ähnlicher vertikaler Schieberegler zum Einstellen eines Wertes&lt;br /&gt;
* [[FTUI Widget Datetimepicker|datetimepicker]]: Erstellt eine Auswahl für Datum/Uhrzeit&lt;br /&gt;
* [[FTUI Widget Departure|departure]]: Abfahrtszeiten öffentlicher Verkehrsmittel&lt;br /&gt;
* [[FTUI Widget Dimmer|dimmer]]: Ein-/Aus-Button mit integriertem Schieberegler für z.B. einen Dim-Wert&lt;br /&gt;
* [[FTUI Widget Eventmonitor|eventmonitor]]:&lt;br /&gt;
* [[FTUI Widget Homestatus|homestatus]]: Auswahl für vier oder fünf definierte Stati eines Objects (z.B.: FHEM Residents)&lt;br /&gt;
* [[FTUI Widget Html|html]]:&lt;br /&gt;
* [[FTUI Widget Iframe|iframe]]: Widget zum Einbinden externer Inhalte in einem Iframe&lt;br /&gt;
* [[FTUI Widget Image|image]]: Zeigt ein Bild, dessen URL fest vorgegeben oder aus einem Device-Reading gelesen werden kann&lt;br /&gt;
* [[FTUI Widget Input|input]]: Erstellen eines Texteingabefeldes&lt;br /&gt;
* [https://github.com/nesges/Widgets-for-fhem-tablet-ui/wiki/joinedlabel joinedlabel]: verbindet mehrere Readings zu einem Feld&lt;br /&gt;
* [[FTUI Widget Klimatrend|klimatrend]]: wandelt Daten aus dem statistics-Modul in einen Pfeil um, der den aktuellen Trend anzeigt&lt;br /&gt;
* [[FTUI Widget Knob|knob]]: Erstellt einen Statusbalken auf einer Kreisbahn&lt;br /&gt;
* [[FTUI Widget Label|label]]: Reading als Text anzeigen&lt;br /&gt;
* [[FTUI Widget Level|level]]: Vertikale oder horizontale Leiste zur Anzeige von Werten zwischen einem Minimal- und einem Maximalwert&lt;br /&gt;
* [[FTUI Widget Link|link]]: Erstellt einen Link oder Button zum Aufrufen von URLs oder Senden von Befehlen an FHEM&lt;br /&gt;
* [[FTUI Widget Medialist|medialist]]:&lt;br /&gt;
* [[FTUI Widget Multistatebutton|multistatebutton]]: Variante des push-Widgets, welches den set-Befehl abhängig vom gelesenen Status ändert&lt;br /&gt;
* [[FTUI Widget Notify|notify]]: Blendet ein Hinweisfenster im Browser ein&lt;br /&gt;
* [[FTUI Widget Pagebutton|pagebutton]]: Button, mit dem auf andere Seiten gesprungen werden kann. Eignet sich gut für eine Navigation&lt;br /&gt;
* [[FTUI Widget Pagetab|pagetab]]: Tauscht den Inhalt einer Seite durch den einer anderen. Eignet sich gut für ein Navigationsmenü&lt;br /&gt;
* [[FTUI Widget Playstream|playstream]]: Abspielen eines Webradio-Streams per Button&lt;br /&gt;
* [[FTUI Widget Popup|popup]]: Öffnet ein Popup nach einem Klick auf ein Widget oder HTML-Element &lt;br /&gt;
* [[FTUI Widget Progress|progress]]: Zeigt einen Prozentwert in Form einer runden Fortschrittsleiste&lt;br /&gt;
* [[FTUI_Widget_Push|push]]: Button, mit dem ein Befehl an FHEM gesendet werden kann&lt;br /&gt;
* [[FTUI Widget Range|range]]: Erstellt vertikale Balken, die einen Wertebereich in unterschiedlichen Farben darstellen&lt;br /&gt;
* [[FTUI Widget Readingsgroup|readingsgroup]]: Zeigt eine Readingsgroup an, wie sie in FHEM definiert wurde&lt;br /&gt;
* [[FTUI Widget Rotor|rotor]]: Animiertes Umschalten von zwei oder mehr Widgets an einer Position&lt;br /&gt;
* [[FTUI Widget Scale|scale]]: Vertikale oder horizontale Leiste zur Anzeige von Werten zwischen einem Minimal- und einem Maximalwert&lt;br /&gt;
* [[FTUI_Widget_Select|select]]: Combobox, die eine Liste an Werten zur Auswahl anzeigt&lt;br /&gt;
* [https://github.com/nesges/Widgets-for-fhem-tablet-ui/wiki/settimer settimer]: Zum Anzeigen und Einstellen einer Uhrzeit&lt;br /&gt;
* [[FTUI Widget Simplechart|simplechart]]: Einfaches XY-Diagramm zur Anzeige eines Wertes, der direkt aus einem FHEM-Logfile gelesen wird&lt;br /&gt;
* [[FTUI Widget Slideout|slideout]]:&lt;br /&gt;
* [[FTUI Widget Slider|slider]]: Vertikaler Schieberegler zum Einstellen eines Wertes &lt;br /&gt;
* [[FTUI Widget Spinner|spinner]]: Element, um Werte durch Drücken auf Plus-/Minus- oder Höher-/Tiefer-Icons zu ändern&lt;br /&gt;
* [[FTUI Widget Swiper|swiper]]: Bietet die Möglichkeit, durch Wischen zwischen verschiedenen Seiten zu wechseln&lt;br /&gt;
* [[FTUI Widget Switch|switch]]: Button, um zwischen zwei Zuständen zu schalten (z.B. on / off)&lt;br /&gt;
* [[FTUI Widget Symbol|symbol]]: Status eines Devices als Symbol darstellen (z.B. Fenster offen)&lt;br /&gt;
* [[FTUI Widget Theme|theme]]: Kontextspezifisches Design&lt;br /&gt;
* [[FTUI Widget Thermostat|thermostat]]: Anzeige für Heizungsthermostate, mit der die gewünschte Temperatur eingestellt werden kann&lt;br /&gt;
* [[FTUI Widget Volume|volume]]: Einstellscheibe zur Änderung eines einzelnen Wertes&lt;br /&gt;
* [[FTUI Widget Weather|weather]]: Wettersymbol anzeigen&lt;br /&gt;
* [[FTUI Widget WindDirection|wind_direction]]: Anzeige der Windrichtung auf einer Windrose&lt;br /&gt;
&lt;br /&gt;
===3rd Party Widgets===&lt;br /&gt;
Für diese Widgets kann nicht sichergestellt werden, dass sie mit der jeweils aktuellen Version von FTUI funktionieren.&lt;br /&gt;
* [[FTUI Widget Agenda|agenda]]: Zeigt Kalendereinträge in einer Listenform an&lt;br /&gt;
* [[FTUI_Widget_Analogclock|analogclock]]: Analoguhr&lt;br /&gt;
* [[FTUI Widget Calview|calview]]: Zeigt Einträge aus einem [[CALVIEW]]-Device an&lt;br /&gt;
* [[FTUI Widget Chart|chart]]: Diagramm mit ähnlichen Möglichkeiten wie die FHEM-Plots&lt;br /&gt;
* [[FTUI Widget Classchanger|classchanger]]: Ändert seine CSS-Klassen je nach Status eines Devices&lt;br /&gt;
* [[FTUI Widget Clicksound|clicksound]]: Mit dem Widget &amp;quot;clicksound&amp;quot; können Sounds an Click-Events von Elementen gebunden werden.&lt;br /&gt;
* [[FTUI Widget Dwdweblink|dwdweblink]]: Grafische Anzeige DWD-Wetter-Weblink&lt;br /&gt;
* [[FTUI Widget Filelog|filelog]]: Teile aus einem FHEM Logfile anzeigen&lt;br /&gt;
* [[FTUI Widget Fullcalview|fullcalview]]:&lt;br /&gt;
* [[FTUI Widget Gds|gds]]:&lt;br /&gt;
* [[FTUI Widget Maps|maps]]: Kartendarstellung mit Google Maps API&lt;br /&gt;
* [[FTUI Widget Highchart|highchart]]:&lt;br /&gt;
* [[FTUI Widget Highchart3d|highchart3d]]:&lt;br /&gt;
* [https://github.com/nesges/Widgets-for-fhem-tablet-ui/wiki/itunes_artwork itunes_artwork]: itunes_artwork durchsucht die iTunes-Datenbank anhand eines Arrays von beliebigen Suchworten nach einem Cover-Artwork und zeigt dieses an. &lt;br /&gt;
* [https://github.com/nesges/Widgets-for-fhem-tablet-ui/wiki/javascript javascript]: Ermöglicht die Ausführung beliebigen Javascript-Codes aus einem Reading.&lt;br /&gt;
* [https://github.com/nesges/Widgets-for-fhem-tablet-ui/wiki/kodinowplaying kodinowplaying]: zeigt Informationen zu grade in KODI gespielten Medien in Form eines Labels an.&lt;br /&gt;
* [[FTUI Widget Loading|loading]]:&lt;br /&gt;
* [[FTUI Widget Meteogram|meteogram]]:&lt;br /&gt;
* [https://github.com/nesges/Widgets-for-fhem-tablet-ui/wiki/mpdnowplaying mpdnowplaying]: Zeigt Titelinformationen eines per MPD-Modul angebundenen Music Player Daemon an.&lt;br /&gt;
* [https://forum.fhem.de/index.php/topic,79283.msg712855.html#msg712855 pinpad]: Pinpad für z.B. eine Alarmanlage&lt;br /&gt;
* [https://forum.fhem.de/index.php/topic,76643.msg685472.html#msg685472 postme]: Liste des PostMe-Devices anzeigen&lt;br /&gt;
* [https://github.com/nesges/Widgets-for-fhem-tablet-ui/wiki/reload reload]: auslösen eine Pagereloads&lt;br /&gt;
* [[FTUI Widget Screensaver|screensaver]]:&lt;br /&gt;
* [[FTUI Widget SMAPortalSPG|smaportalspg]]: Anzeige von SMAPortal-Daten im FHEM Tablet UI&lt;br /&gt;
* [[FTUI Widget für SSCam Streaming Devices (SSCamSTRM)|sscamstrm]]: Integration von SSCam Streaming-Devices (Synology Surveillance Station Kameras) im FHEM Tablet UI&lt;br /&gt;
* [https://forum.fhem.de/index.php/topic,73497.0.html scrolllabel]: Texte in Laufschrift darstellen&lt;br /&gt;
* [[FTUI Widget Svgplot|svgplot]]: Unveränderte Übernahme eine bestehenden SVG-Plots&lt;br /&gt;
* [https://forum.fhem.de/index.php?topic=82883.msg750237#msg750237 todoist]: einfaches widget für todoist&lt;br /&gt;
* [[FTUI Widget Tts|tts]]: Sprachausgabe eines Textes aus einem Reading auf dem Endgerät.&lt;br /&gt;
* [[FTUI Widget UWZ|uwz]]: Anzeige der Warnungen der Unwetterzentrale&lt;br /&gt;
* [[FTUI Widget Wakeup|wakeup]]:&lt;br /&gt;
* [https://github.com/svenson08/ftui-weekdaytimer-widget wdtimer]: Visualisierung des [[WeekdayTimer]] Modul&lt;br /&gt;
* [[FTUI Widget Weekprofile|weekprofile]]: Visualisierung des [[weekprofile]] Moduls&lt;br /&gt;
* [[FTUI Widget Weatherdetail|weatherdetail]]: Detaillierte Wettervorhersage über 4 Tage (Nutzt das Proplanta Modul)&lt;br /&gt;
* [[FTUI Widget Video|videodetail]]: Video Widget für die FTUI&lt;br /&gt;
&lt;br /&gt;
===Anwendungsbeispiele===&lt;br /&gt;
Durch die Verbindung von Widgets mit dem FHEM-Umfeld entstehen Lösungen für typische Anwendungen.&lt;br /&gt;
* [[FTUI_Beispiel_Datetimepicker_für_Timer|Datetimepicker für Timer]]: Oberfläche für Timereinstellungen&lt;br /&gt;
* [[FTUI_Beispiel_Mondphase|Mondphase]]: Visuelle Darstellung der Mondphase&lt;br /&gt;
* [[FTUI_Beispiel_Webradio|Webradio]]&lt;br /&gt;
* [[FTUI Beispiel Zeitschaltung|Verschiedene Zeitschaltungen]]&lt;br /&gt;
&lt;br /&gt;
==Templates==&lt;br /&gt;
Kommt ein bestimmtes &amp;quot;Code-Fragment&amp;quot; auf mehreren Seiten oder öfter pro Seite vor, bietet FTUI die Option, Templates zu erstellen. Diese werden einmal gebaut und können dann mit dem Attribut &#039;&#039;&#039;data-template&#039;&#039;&#039; nach Belieben in eine Seite eingefügt werden. Dabei besteht auch die Möglichkeit, Variablen zu verwenden.&lt;br /&gt;
&lt;br /&gt;
Die Variablennamen sollten möglichst eindeutig und unverwechselbar gewählt werden, da bei der Verwendung von Templates im Prinzip Suchen &amp;amp; Ersetzen angewendet wird. Verwendet man beispielsweise die Variablen &#039;&#039;&#039;dev:Thermostat_Kueche&#039;&#039;&#039; und &#039;&#039;&#039;dev_temp:temperatue&#039;&#039;&#039;, so kann es passieren, dass die Ergebnisse im erzeugten Code dann &#039;&#039;&#039;Thermostat_Kueche&#039;&#039;&#039; und &#039;&#039;&#039;Thermostat_Kueche_temp&#039;&#039;&#039; lauten, statt wie gewünscht &#039;&#039;&#039;Thermostat_Kueche&#039;&#039;&#039; und &#039;&#039;&#039;temperature&#039;&#039;&#039;. Um dies zu vermeiden, sollten die Variablen besser &#039;&#039;&#039;device:Thermostat_Kueche&#039;&#039;&#039; und &#039;&#039;&#039;temp:temperature&#039;&#039;&#039; lauten.&lt;br /&gt;
&lt;br /&gt;
Im Folgenden ein paar Beispiele, wie Templates verwendet werden können.&lt;br /&gt;
&lt;br /&gt;
===Einzelnes Widget===&lt;br /&gt;
Soll ein Widget an mehreren Stellen in exakt der selben Ausführung eingebunden werden, kann diese Widget in einer eigenen Datei erstellt und diese dann auf den Zielseiten automatisch mitgeladen werden.&lt;br /&gt;
&lt;br /&gt;
;Template-Seite&lt;br /&gt;
Die Template-Seite soll in diesem Beispiel &#039;&#039;template_symbol.html&#039;&#039; genannt werden. Diese wird daher zuerst im FTUI-Verzeichnis erstellt.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;symbol&amp;quot;&lt;br /&gt;
     data-device=&amp;quot;dummy1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Haupt-Seite&lt;br /&gt;
Die oben erstellte Template-Seite kann nun in jeder gewünschten Seite eingebunden werden.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; highlight=&amp;quot;6&amp;quot;&amp;gt;&lt;br /&gt;
[...]&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;gridster&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;ul&amp;gt;&lt;br /&gt;
      &amp;lt;li data-row=&amp;quot;1&amp;quot; data-col=&amp;quot;1&amp;quot; data-sizey=&amp;quot;1&amp;quot; data-sizex=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
         &amp;lt;div data-template=&amp;quot;template_symbol.html&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
      &amp;lt;/li&amp;gt;&lt;br /&gt;
   &amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
[...]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Gridster-Element===&lt;br /&gt;
Natürlich kann auch ein ganzes Gridster-Element - in diesem Fall ein Menü - als Template eingebunden werden.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;li data-row=&amp;quot;1&amp;quot; data-col=&amp;quot;1&amp;quot; data-sizex=&amp;quot;1&amp;quot; data-sizey=&amp;quot;4&amp;quot; data-template=&amp;quot;menu.html&amp;quot;&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Widget-Gruppen ===&lt;br /&gt;
Die Template-Datei des [[#Einzelnes Widget|ersten Beispiels]] kann natürlich auch mehrere Widgets auf einmal enthalten.&lt;br /&gt;
&lt;br /&gt;
=== Verwendung von Variablen ===&lt;br /&gt;
==== Einfaches Beispiel ====&lt;br /&gt;
Oft wird ein und dasselbe Widget für verschiedenen Devices verwendet. Um nicht für jedes Device das Widget neu kopieren zu müssen (bzw. bei Änderungen alle Seiten ausbessern zu müssen), kann ein Template verwendet werden, dem einfach per Parameter mitgeteilt wird, von welchem Device es gerade die Daten empfangen soll.&lt;br /&gt;
&lt;br /&gt;
In diesem Beispiel wird ein Template erzeugt, dass nur die Temperatur verschiedenen Thermostate mittels eines [[FTUI Widget Label|Label-Widgets]] anzeigt.&lt;br /&gt;
&lt;br /&gt;
;Template-Seite&lt;br /&gt;
Die Template-Seite enthält nur ein einfaches Label-Widget und wird in diesem Beispiel &#039;&#039;template_label.html&#039;&#039; genannt. Um sie für mehrere Devices verwenden zu können, wird im Attribut &#039;&#039;&#039;data-device&#039;&#039;&#039; der Name des eigentlichen Devices durch den Parameter &#039;&#039;&#039;par01&#039;&#039;&#039; ersetzt.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; highlight=&amp;quot;2&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot;&lt;br /&gt;
     data-device=&amp;quot;par01&amp;quot;&lt;br /&gt;
     data-get=&amp;quot;measured-temp&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Haupt-Seite&lt;br /&gt;
Auf der Haupt-Seite wird die Template-Seite mit dem Attribut &#039;&#039;&#039;data-template&#039;&#039;&#039; eingebunden und ihr via Attribut &#039;&#039;&#039;data-parameter&#039;&#039;&#039; das jeweils gewünschte Device übergeben.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
[...]&lt;br /&gt;
&amp;lt;div data-template=&amp;quot;template_label.html&amp;quot; data-parameter=&#039;{&amp;quot;par01&amp;quot;:&amp;quot;Thermostat1&amp;quot;}&#039;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-template=&amp;quot;template_label.html&amp;quot; data-parameter=&#039;{&amp;quot;par01&amp;quot;:&amp;quot;Thermostat2&amp;quot;}&#039;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-template=&amp;quot;template_label.html&amp;quot; data-parameter=&#039;{&amp;quot;par01&amp;quot;:&amp;quot;Thermostat3&amp;quot;}&#039;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[...]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Wetter-Slider mit Template ====&lt;br /&gt;
In diesem Beispiel wird ein [[FTUI Widget Slider|Slider-Widget]] erstellt, welches die verschiedenen Tage eines Wetterberichtes anzeigt. Dabei wird für den Wetterbericht des jeweiligen Tages immer dasselbe Template verwendet um nicht für jeden Tag ein eigenes Widget schreiben zu müssen.&lt;br /&gt;
&lt;br /&gt;
;Template-Seite&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;left&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;AgroWeather&amp;quot; data-get=&amp;quot;par01&amp;quot; data-unit=&amp;quot;&amp;amp;deg;C&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
   &amp;lt;div class=&amp;quot;inline&amp;quot;&amp;gt;&lt;br /&gt;
       &amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;AgroWeather&amp;quot; data-get=&amp;quot;par02&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
       &amp;lt;div data-type=&amp;quot;weather&amp;quot; data-device=&amp;quot;AgroWeather&amp;quot; data-get=&amp;quot;par02&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
       min:&amp;amp;nbsp;&amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;AgroWeather&amp;quot; data-get=&amp;quot;par03&amp;quot; data-unit=&amp;quot;&amp;amp;deg;C&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
   &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;left&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;AgroWeather&amp;quot; data-get=&amp;quot;par04&amp;quot; data-substitution=&amp;quot;toDate().eeee()+&#039;,&#039;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
   &amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;AgroWeather&amp;quot; data-get=&amp;quot;par04&amp;quot; data-substitution=&amp;quot;toDate().ddmm()&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Haupt-Seite&lt;br /&gt;
In der Haupt-Seite wird das Template dann für jede Slider-Seite eingebunden und das Reading für den jeweiligen Tag via Parameter übergeben.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
[...]&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;swiper&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
   &amp;lt;li data-template=&amp;quot;templates/wetter.html&amp;quot; data-parameter=&#039;{&amp;quot;par01&amp;quot;:&amp;quot;fc0_tempMax&amp;quot;,&amp;quot;par02&amp;quot;:&amp;quot;fc0_weatherDay&amp;quot;,&amp;quot;par03&amp;quot;:&amp;quot;fc0_tempMin&amp;quot;,&amp;quot;par04&amp;quot;:&amp;quot;fc0_date&amp;quot;}&#039;&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
   &amp;lt;li data-template=&amp;quot;templates/wetter.html&amp;quot; data-parameter=&#039;{&amp;quot;par01&amp;quot;:&amp;quot;fc1_tempMax&amp;quot;,&amp;quot;par02&amp;quot;:&amp;quot;fc1_weatherDay&amp;quot;,&amp;quot;par03&amp;quot;:&amp;quot;fc1_tempMin&amp;quot;,&amp;quot;par04&amp;quot;:&amp;quot;fc1_date&amp;quot;}&#039;&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
   &amp;lt;li data-template=&amp;quot;templates/wetter.html&amp;quot; data-parameter=&#039;{&amp;quot;par01&amp;quot;:&amp;quot;fc2_tempMax&amp;quot;,&amp;quot;par02&amp;quot;:&amp;quot;fc2_weatherDay&amp;quot;,&amp;quot;par03&amp;quot;:&amp;quot;fc2_tempMin&amp;quot;,&amp;quot;par04&amp;quot;:&amp;quot;fc2_date&amp;quot;}&#039;&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
   &amp;lt;li data-template=&amp;quot;templates/wetter.html&amp;quot; data-parameter=&#039;{&amp;quot;par01&amp;quot;:&amp;quot;fc3_tempMax&amp;quot;,&amp;quot;par02&amp;quot;:&amp;quot;fc3_weatherDay&amp;quot;,&amp;quot;par03&amp;quot;:&amp;quot;fc3_tempMin&amp;quot;,&amp;quot;par04&amp;quot;:&amp;quot;fc3_date&amp;quot;}&#039;&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
[...]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== JavaScript-Funktionen ==&lt;br /&gt;
Neben den Widgets können auch einige JavaScript-Funktionen verwendet werden, um Befehle an FHEM zu senden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Folgende Zeile setzt einen direkten Befehl an FHEM ab (&amp;lt;code&amp;gt;set dummy1 off&amp;lt;/code&amp;gt;):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;div onclick=&amp;quot;ftui.setFhemStatus(&#039;set dummy1 off&#039;)&amp;quot;&amp;gt;Dummy1 aus&amp;lt;/div&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Diese Zeile veranlasst FHEM dazu, eine Funktion aus der 99_myUtils.pm auszuführen (&amp;lt;code&amp;gt;myUtils_HeizungUpDown(&amp;quot;WZ.Thermostat_Climate&amp;quot;,&amp;quot;up&amp;quot;)&amp;lt;/code&amp;gt;):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;div onclick=&amp;quot;ftui.setFhemStatus(&#039;{myUtils_HeizungUpDown(&amp;amp;quot;WZ.Thermostat_Climate&amp;amp;quot;,&amp;amp;quot;up&amp;amp;quot;)}&#039;)&amp;quot;&amp;gt;+&amp;lt;/div&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel, wie ein Kommando an FHEM gesendet wird und gleichzeitig der Wert eines bereits in FTUI angezeigten Readings verwendet werden kann:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;dummy1&amp;quot; data-get=&amp;quot;temperature&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div onClick=&amp;quot;ftui.setFhemStatus(&#039;set dummy2 &#039;+ftui.getDeviceParameter(&#039;dummy1&#039;,&#039;temperature&#039;).val);&amp;quot;&amp;gt;Senden&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Eigene Widgets erstellen ==&lt;br /&gt;
Wie eigenen Widgets für FTUI erstellt werden können, ist auf der Seite [[FTUI eigene Widgets]] beschrieben.&lt;br /&gt;
&lt;br /&gt;
Eine Schritt für Schritt Anleitung für das erste eigene Widget gibts hier [[FTUI eigene Widgets - Beispiel]]&lt;br /&gt;
&lt;br /&gt;
== FAQ ==&lt;br /&gt;
Häufig gestellte Fragen zum FHEM Tablet UI sind in der [[FHEM Tablet UI FAQ]] zusammengestellt.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [https://github.com/knowthelist/fhem-tablet-ui Projekt auf Github]&lt;br /&gt;
* {{Link2Forum|Topic=34233|LinkText=Forums-Beitrag}}&lt;br /&gt;
* [[FTUI_Snippets|Snippets]]&lt;br /&gt;
* [http://knowthelist.github.io/fhem/tablet/demo_widgets.html Live-Demos]&lt;br /&gt;
* [https://waschto.eu/fhem-und-tabletui-livedemo/ FHEM und TabletUI Live-Demo]&lt;br /&gt;
* {{Link2Forum|Topic=37378|LinkText=User-Demos}}&lt;br /&gt;
* [https://github.com/ovibox/fhem-ftui-user-demos Download der User-Demo-Dateien]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:FHEM Tablet UI|!]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=TR%C3%85DFRI&amp;diff=31717</id>
		<title>TRÅDFRI</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=TR%C3%85DFRI&amp;diff=31717"/>
		<updated>2019-11-17T16:04:03Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: /* tradfri */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div style=&amp;quot;float:right&amp;quot;&amp;gt;{{Infobox Modul&lt;br /&gt;
|Name=tradfri&lt;br /&gt;
|ModPurpose=Anbindung IKEA TRÅDFRI Gateway&lt;br /&gt;
|ModType=d&lt;br /&gt;
&amp;lt;!-- |ModCategory= (noch?) nicht verwendet --&amp;gt;&lt;br /&gt;
|ModCmdRef=tradfri&lt;br /&gt;
|ModForumArea=Zigbee&lt;br /&gt;
|ModTechName=30_tradfri.pm&lt;br /&gt;
|ModOwner=Andre ([http://forum.fhem.de/index.php?action=profile;u=430 Forum] / [[Benutzer Diskussion:justme|Wiki]])&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TRÅDFRI&#039;&#039;&#039; bzw. &#039;&#039;&#039;IKEA Home smart&#039;&#039;&#039; ist die Serie smarter Beleuchtungslösungen von IKEA auf ZigBee-Basis, ähnlich Phillips Hue.&lt;br /&gt;
&lt;br /&gt;
== tradfri ==&lt;br /&gt;
&lt;br /&gt;
TRÅDFRI (nach Umbennung jetzt &#039;&#039;&#039;IKEA Home smart&#039;&#039;&#039;) ist die Serie smarter Beleuchtungslösungen von IKEA. Ähnlich wie von Phillips [[Hue]] gibt es diverse LEDs in Glühbirnenform, LED-Streifen-Treiber, Flächenleuchten, Wandtaster, Bewegungsmelder, Fernbedienung, Dimmer, etc. und alles via Funk gekoppelt. Außerdem ein Gateway, das sich via Ethernetstecker ins heimische LAN einbinden lässt und die Bedienung via IKEA-App auf dem Handy ermöglicht. &lt;br /&gt;
{{Hinweis|Da die Geräte über den [[ZigBee]]-Standard kommunizieren, können auch andere Gateways für diese Leuchtmittel (und andere Geräte wie Rollos) genutzt werden. Dieser Artikel behandelt ausschließlich die Verwendung zusammen mit einem IKEA-Gateway!}}&lt;br /&gt;
Mit dem IKEA-Gateway ist auch eine Anbindung in FHEM möglich, dazu funktionieren zwei &#039;&#039;&#039;alternative&#039;&#039;&#039; Lösungen:&lt;br /&gt;
&lt;br /&gt;
=== alt: IKEA Trådfri Modul ===&lt;br /&gt;
IKEA Trådfri Modul (TYPE &#039;&#039;TradfriDevice&#039;&#039; und &#039;&#039;TradfriGateway&#039;&#039;, mehr Infos: https://forum.fhem.de/index.php/topic,70653.0.html seit April 2017)&lt;br /&gt;
* Erkennt Lampen&lt;br /&gt;
* Fernbedienung erscheint zwar in der Geräteliste, lässt sich aber nicht als Gerät anlegen oder Status lesen&lt;br /&gt;
&lt;br /&gt;
Die Weiterentwicklung des Moduls durch den ursprünglichen Entwickler scheint Stand 07.19 eingestellt. Inwieweit andere am Modul weiter arbeiten ist unklar.&lt;br /&gt;
&lt;br /&gt;
=== neu: tradfri-fhem Modul ===&lt;br /&gt;
tradfri-fhem Modul (TYPE &#039;&#039;HUEDevice&#039;&#039; und &#039;&#039;tradfri&#039;&#039; Gateway, mehr Infos: https://forum.fhem.de/index.php/topic,96125.0.html seit Januar 2019, Beschreibung folgt auf dieser Seite)&lt;br /&gt;
* Unterstützt Lampen (als [[Hue#HUE-Device|HUE-Device]])&lt;br /&gt;
* Unterstützt Rollos (Fyrtur und Kadrilj) &lt;br /&gt;
* Erkennt Fernbedienung, jedoch zur Zeit Batteriestatus als einziges Reading&lt;br /&gt;
* Erstellt (wenn gewünscht) automatisch Gruppen&lt;br /&gt;
* Erkennt Bewegungsmelder, jedoch zur Zeit Batteriestatus als einziges Reading&lt;br /&gt;
* Erkennt Repeater, nur Erreichbarkeit (reachable) als Reading &lt;br /&gt;
&lt;br /&gt;
====Einrichtung in FHEM====&lt;br /&gt;
&lt;br /&gt;
# node installieren (mindestens version 8)&lt;br /&gt;
# sudo npm install -g tradfri-fhem&lt;br /&gt;
# &amp;lt;code&amp;gt;define &amp;lt;tradfri&amp;gt; tradfri&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;lt;code&amp;gt;attr &amp;lt;tradfri&amp;gt; tradfriFHEM-securityCode &amp;lt;security code&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
wenn das gateway nicht automatisch erkannt wird:&lt;br /&gt;
&amp;lt;code&amp;gt;attr &amp;lt;tradfri&amp;gt; tradfriFHEM-params --ip &amp;lt;ip&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
WICHTIG: danach in FHEM einmal die Konfiguration speichern damit der Pairing-Key gesichert wird. Sonst muss beim nächsten FHEM-Neustart das Pairing erneut durchgeführt werden.&lt;br /&gt;
&lt;br /&gt;
==== HUE-Device ====&lt;br /&gt;
Alle auf dem Gateway bekannten Geräte automatisch als [[Hue#HUE-Device|HUEDevice]] in FHEM angelegt:&lt;br /&gt;
* Lampen, Stecker, Trafos, ...&lt;br /&gt;
: Hiermit werden die einzelnen Leuchten gesteuert&lt;br /&gt;
* Gruppen&lt;br /&gt;
: Hiermit lassen sich ganze Gruppen und Räume steuern&lt;br /&gt;
* Fernbedienungen&lt;br /&gt;
: aktuell gibt es nur ein Battery-Reading&lt;br /&gt;
&lt;br /&gt;
==== Darstellung im Webfrontend ====&lt;br /&gt;
Wenn man die SVG Icons verwendet ist es sinnvoll, das Attribut color-icons zu setzen. Mit &amp;lt;code&amp;gt;attr HUEDevice1 color-icons 2&amp;lt;/code&amp;gt; werden z.B. die Farben und der Dimmzustand der Lampe als Icon dargestellt.&lt;br /&gt;
Damit das ganze funktioniert, müsst ihr auch noch das &amp;lt;code&amp;gt;attr WEB iconPath fhemSVG:openautomation:default&amp;lt;/code&amp;gt; setzen.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [https://github.com/peterkappelt/Tradfri-FHEM/issues/16#issuecomment-445461242 Githubeintrag über Einstellung der Feature-Entwicklung des IKEA Trådfri Moduls].&lt;br /&gt;
[[Kategorie:ZigBee]]&lt;br /&gt;
[[Kategorie:Lichteffektgeräte]]&lt;br /&gt;
[[Kategorie:IP Components]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=TR%C3%85DFRI&amp;diff=31716</id>
		<title>TRÅDFRI</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=TR%C3%85DFRI&amp;diff=31716"/>
		<updated>2019-11-17T16:03:22Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: /* tradfri */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div style=&amp;quot;float:right&amp;quot;&amp;gt;{{Infobox Modul&lt;br /&gt;
|Name=tradfri&lt;br /&gt;
|ModPurpose=Anbindung IKEA TRÅDFRI Gateway&lt;br /&gt;
|ModType=d&lt;br /&gt;
&amp;lt;!-- |ModCategory= (noch?) nicht verwendet --&amp;gt;&lt;br /&gt;
|ModCmdRef=tradfri&lt;br /&gt;
|ModForumArea=Zigbee&lt;br /&gt;
|ModTechName=30_tradfri.pm&lt;br /&gt;
|ModOwner=Andre ([http://forum.fhem.de/index.php?action=profile;u=430 Forum] / [[Benutzer Diskussion:justme|Wiki]])&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TRÅDFRI&#039;&#039;&#039; bzw. &#039;&#039;&#039;IKEA Home smart&#039;&#039;&#039; ist die Serie smarter Beleuchtungslösungen von IKEA auf ZigBee-Basis, ähnlich Phillips Hue.&lt;br /&gt;
&lt;br /&gt;
== tradfri ==&lt;br /&gt;
&lt;br /&gt;
TRÅDFRI (nach Umbennung jetzt &#039;&#039;&#039;IKEA Home smart&#039;&#039;&#039;) ist die Serie smarter Beleuchtungslösungen von IKEA. Ähnlich von Phillips [[Hue]] gibt es diverse LEDs in Glühbirnenform, LED-Streifen-Treiber, Flächenleuchten, Wandtaster, Bewegungsmelder, Fernbedienung, Dimmer, etc. und alles via Funk gekoppelt. Außerdem ein Gateway, das sich via Ethernetstecker ins heimische LAN einbinden lässt und die Bedienung via IKEA-App auf dem Handy ermöglicht. &lt;br /&gt;
{{Hinweis|Da die Geräte über den [[ZigBee]]-Standard kommunizieren, können auch andere Gateways für diese Leuchtmittel (und andere Geräte wie Rollos) genutzt werden. Dieser Artikel behandelt ausschließlich die Verwendung zusammen mit einem IKEA-Gateway!}}&lt;br /&gt;
Mit dem IKEA-Gateway ist auch eine Anbindung in FHEM möglich, dazu funktionieren zwei &#039;&#039;&#039;alternative&#039;&#039;&#039; Lösungen:&lt;br /&gt;
&lt;br /&gt;
=== alt: IKEA Trådfri Modul ===&lt;br /&gt;
IKEA Trådfri Modul (TYPE &#039;&#039;TradfriDevice&#039;&#039; und &#039;&#039;TradfriGateway&#039;&#039;, mehr Infos: https://forum.fhem.de/index.php/topic,70653.0.html seit April 2017)&lt;br /&gt;
* Erkennt Lampen&lt;br /&gt;
* Fernbedienung erscheint zwar in der Geräteliste, lässt sich aber nicht als Gerät anlegen oder Status lesen&lt;br /&gt;
&lt;br /&gt;
Die Weiterentwicklung des Moduls durch den ursprünglichen Entwickler scheint Stand 07.19 eingestellt. Inwieweit andere am Modul weiter arbeiten ist unklar.&lt;br /&gt;
&lt;br /&gt;
=== neu: tradfri-fhem Modul ===&lt;br /&gt;
tradfri-fhem Modul (TYPE &#039;&#039;HUEDevice&#039;&#039; und &#039;&#039;tradfri&#039;&#039; Gateway, mehr Infos: https://forum.fhem.de/index.php/topic,96125.0.html seit Januar 2019, Beschreibung folgt auf dieser Seite)&lt;br /&gt;
* Unterstützt Lampen (als [[Hue#HUE-Device|HUE-Device]])&lt;br /&gt;
* Unterstützt Rollos (Fyrtur und Kadrilj) &lt;br /&gt;
* Erkennt Fernbedienung, jedoch zur Zeit Batteriestatus als einziges Reading&lt;br /&gt;
* Erstellt (wenn gewünscht) automatisch Gruppen&lt;br /&gt;
* Erkennt Bewegungsmelder, jedoch zur Zeit Batteriestatus als einziges Reading&lt;br /&gt;
* Erkennt Repeater, nur Erreichbarkeit (reachable) als Reading &lt;br /&gt;
&lt;br /&gt;
====Einrichtung in FHEM====&lt;br /&gt;
&lt;br /&gt;
# node installieren (mindestens version 8)&lt;br /&gt;
# sudo npm install -g tradfri-fhem&lt;br /&gt;
# &amp;lt;code&amp;gt;define &amp;lt;tradfri&amp;gt; tradfri&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;lt;code&amp;gt;attr &amp;lt;tradfri&amp;gt; tradfriFHEM-securityCode &amp;lt;security code&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
wenn das gateway nicht automatisch erkannt wird:&lt;br /&gt;
&amp;lt;code&amp;gt;attr &amp;lt;tradfri&amp;gt; tradfriFHEM-params --ip &amp;lt;ip&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
WICHTIG: danach in FHEM einmal die Konfiguration speichern damit der Pairing-Key gesichert wird. Sonst muss beim nächsten FHEM-Neustart das Pairing erneut durchgeführt werden.&lt;br /&gt;
&lt;br /&gt;
==== HUE-Device ====&lt;br /&gt;
Alle auf dem Gateway bekannten Geräte automatisch als [[Hue#HUE-Device|HUEDevice]] in FHEM angelegt:&lt;br /&gt;
* Lampen, Stecker, Trafos, ...&lt;br /&gt;
: Hiermit werden die einzelnen Leuchten gesteuert&lt;br /&gt;
* Gruppen&lt;br /&gt;
: Hiermit lassen sich ganze Gruppen und Räume steuern&lt;br /&gt;
* Fernbedienungen&lt;br /&gt;
: aktuell gibt es nur ein Battery-Reading&lt;br /&gt;
&lt;br /&gt;
==== Darstellung im Webfrontend ====&lt;br /&gt;
Wenn man die SVG Icons verwendet ist es sinnvoll, das Attribut color-icons zu setzen. Mit &amp;lt;code&amp;gt;attr HUEDevice1 color-icons 2&amp;lt;/code&amp;gt; werden z.B. die Farben und der Dimmzustand der Lampe als Icon dargestellt.&lt;br /&gt;
Damit das ganze funktioniert, müsst ihr auch noch das &amp;lt;code&amp;gt;attr WEB iconPath fhemSVG:openautomation:default&amp;lt;/code&amp;gt; setzen.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [https://github.com/peterkappelt/Tradfri-FHEM/issues/16#issuecomment-445461242 Githubeintrag über Einstellung der Feature-Entwicklung des IKEA Trådfri Moduls].&lt;br /&gt;
[[Kategorie:ZigBee]]&lt;br /&gt;
[[Kategorie:Lichteffektgeräte]]&lt;br /&gt;
[[Kategorie:IP Components]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=WMBUS&amp;diff=31438</id>
		<title>WMBUS</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=WMBUS&amp;diff=31438"/>
		<updated>2019-10-29T18:57:02Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: /* Empfangsprobleme */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=Dekodierung von Wireless M-Bus Nachrichten&lt;br /&gt;
|ModType=d&lt;br /&gt;
|ModForumArea=Sonstige Systeme&lt;br /&gt;
|ModTechName=36_WMBUS.pm&lt;br /&gt;
|ModOwner=kaihs&lt;br /&gt;
}}&lt;br /&gt;
[[WMBUS]] ist ein Modul zur Dekodierung von Wireless M-Bus Nachrichten. Solche Nachrichten werden z. B. von Zählern für Wasser, Wärme, Gas und Elektrizität ausgestrahlt.&lt;br /&gt;
Wireless M-Bus ist ein Standardprotokoll das von unterschiedlichen Herstellern unterstützt wird.&lt;br /&gt;
Das Protokoll unterstützt unterschiedliche Kodierungen des Funksignals, im wesentlichen den S-Mode, T-Mode und C-Mode. Der Empfänger (z. B. ein CUL) muss den selben Modus nutzen wie der Sender (der Zähler). &lt;br /&gt;
Wireless M-Bus unterstützt optional die Verschlüsselung der Daten.&lt;br /&gt;
Die von einem Zähler gesendeten Daten können sehr unterschiedlich sein und hängen u. a. vom Zählertyp und dessen Hersteller ab.&lt;br /&gt;
&lt;br /&gt;
== Voraussetzungen ==&lt;br /&gt;
Das Modul interpretiert nur die Nachrichten die von einen geeigneten Empfänger empfangen werden. Aktuell kann ein [[CUL]] und verwandte Geräte die die culfw[http://culfw.de/culfw.html] verwenden sowie ein Amber Wireless AMB8465M dafür verwendet werden. In der culfw muss die Unterstützung des WMBUS-Protokolls aktiviert sein (#define HAS_MBUS in der Datei board.h des Deviceverzeichnisses). Bei einem CUL mit der Hardwareversion V4 ist das nicht der Fall.&lt;br /&gt;
&lt;br /&gt;
Der CUL muss in FHEM mittels Attribut rfmode=WMBus_S, WMBus_T oder WMBus_C in den zum Zähler passenden Empfangsmodus versetzt werden.&lt;br /&gt;
&lt;br /&gt;
== Anwendung ==&lt;br /&gt;
Die Erzeugung des passenden Devices in FHEM geschieht automatisch beim Empfang des ersten Datenpakets eines Zählers. Voraussetzung dafür ist, dass [[autocreate]] aktiv ist.&lt;br /&gt;
Alternativ kann ein Device manuell angelegt werden. Dazu wird der Hersteller, die Seriennummer, die Version und der Typ (Wasser, Gas, ...) des Zählers benötigt.&lt;br /&gt;
Sind die Daten verschlüsselt wird auch noch der passende Schlüssel benötigt um die Daten entschlüsseln zu können.&lt;br /&gt;
&lt;br /&gt;
== Verschlüsselung ==&lt;br /&gt;
Die Daten können auf drei verschiedene Arten verschlüsselt sein:&lt;br /&gt;
# Security profile A/Symmetric encryption with Mode 5&lt;br /&gt;
# Security profile B/Advanced symmetric encryption with Mode 7&lt;br /&gt;
# Security profile C/Asymmetric encryption with Mode 13&lt;br /&gt;
&lt;br /&gt;
Das Modul unterstützt aktuell Daten die per 1 oder 2 verschlüsselt wurden.&lt;br /&gt;
&lt;br /&gt;
== Anwendungsbeispiele ==&lt;br /&gt;
Ein per [[EnergyCam]] abgelesener Elektrizitätszähler sieht in FHEM z. B. so aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 Internals: &lt;br /&gt;
   CUL_MBUS_MSGCNT 29 &lt;br /&gt;
   CUL_MBUS_RAWMSG b1944C4189985051701028A7D7A540000A00405FAD4080002FD08222C1295B8::-67.5 &lt;br /&gt;
   CUL_MBUS_RSSI -67.5 &lt;br /&gt;
   CUL_MBUS_TIME 2014-10-24 22:57:53 &lt;br /&gt;
   DEF        FFD 17058599 1 2 &lt;br /&gt;
   DeviceMedium Electricity &lt;br /&gt;
   DeviceType 2 &lt;br /&gt;
   IODev      CUL_MBUS &lt;br /&gt;
   IdentNumber 17058599 &lt;br /&gt;
   LASTInputDev CUL_MBUS &lt;br /&gt;
   MSGCNT     29 &lt;br /&gt;
   Manufacturer FFD &lt;br /&gt;
   NAME       WMBUS_FFD_17058599_1_2 &lt;br /&gt;
   NR         49 &lt;br /&gt;
   STATE      no errors &lt;br /&gt;
   TYPE       WMBUS &lt;br /&gt;
   Version    1 &lt;br /&gt;
   addr       FFD_17058599_1_2 &lt;br /&gt;
   Readings: &lt;br /&gt;
     2014-10-24 22:57:53   1_storage_no    0 &lt;br /&gt;
     2014-10-24 22:57:53   1_type          VIF_ENERGY_WATT &lt;br /&gt;
     2014-10-24 22:57:53   1_unit          Wh &lt;br /&gt;
     2014-10-24 22:57:53   1_value         57881000 &lt;br /&gt;
     2014-10-24 22:57:53   2_storage_no    0 &lt;br /&gt;
     2014-10-24 22:57:53   2_type          VIF_ACCESS_NO &lt;br /&gt;
     2014-10-24 22:57:53   2_unit &lt;br /&gt;
     2014-10-24 22:57:53   2_value         11298 &lt;br /&gt;
     2014-10-24 22:57:53   LQI             184 &lt;br /&gt;
     2014-10-24 22:57:53   RSSI            -67.5 &lt;br /&gt;
     2014-10-24 22:57:53   battery         ok &lt;br /&gt;
     2014-10-24 22:57:53   decryption_ok   1 &lt;br /&gt;
     2014-10-24 22:57:53   energy          57881 &lt;br /&gt;
     2014-10-24 22:57:53   is_encrypted    0 &lt;br /&gt;
     2014-10-24 22:57:53   state           no errors &lt;br /&gt;
     2014-10-24 22:57:53   unit            kWh &lt;br /&gt;
 Attributes: &lt;br /&gt;
   IODev      CUL_MBUS &lt;br /&gt;
   room       WMBUS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Bekannte Probleme ==&lt;br /&gt;
=== Inkompatible Zähler ===&lt;br /&gt;
Obwohl Wireless M-Bus ein standardisiertes Protokoll ist, scheint sich kaum ein Hersteller vollständig daran zu halten bzw. verwendet sog. herstellerspezifische Felder um wichtige Daten zu verpacken.&lt;br /&gt;
Aus den bisher beobachteten Datenpaketen ergibt sich &lt;br /&gt;
* Qundis (Herstellerkürzel LSE) verwendet herstellerspezifische Datenblöcke für den eigentlichen Zählerstand&lt;br /&gt;
* Techem und Hydrometer verwenden ein undokumentiertes Datenformat (CI-Field A2)&lt;br /&gt;
:&#039;&#039;(Techem Heizkostenverteiler (CI-Field A0) können über das Modul [[TechemHKV]] ausgewertet werden)&#039;&#039;&lt;br /&gt;
* RWE SmartHome Powercontrol[http://www.rwe-smarthome.de/web/cms/de/1776202/smarthome/informieren/geraete/power-control/] sendet verschlüsselt und der Hersteller gibt nicht den vollständigen Schlüssel an ({{Link2Forum|Topic=24517|Message=315949}})&lt;br /&gt;
&lt;br /&gt;
Daher werden bisher erst die [[EnergyCam]] der Firma Q-loud, Zähler von Easymeter und der Kamstrup Multical 21 vollständig unterstützt.&lt;br /&gt;
Für den Multical 21 muss eine culfw mit Unterstützung für WMBUS C verwendet werden. Diese ist in der culfw ab dem 24.6.2018 enthalten.&lt;br /&gt;
&lt;br /&gt;
Andere Zähler können auch ohne Probleme funktionieren wenn diese sich an den OMS Standard halten.&lt;br /&gt;
&lt;br /&gt;
=== Empfangsprobleme ===&lt;br /&gt;
Der Empfänger (meist ein [[CUL]]) muss das WMBUS Protokoll unterstützen. Die Unterstützung ist vorhanden, wenn in der Ausgabe von &amp;lt;code&amp;gt;get cmds&amp;lt;/code&amp;gt; ein kleines [http://culfw.de/commandref.html#cmd_b b] enthalten ist.&lt;br /&gt;
Der CUL speichert die empfangenen Daten intern zwischen bevor sie an fhem geschickt werden. Der Puffer für die Speicherung muss groß genug sein, um ein komplettes Datenpaket aufzunehmen. Die Größe des Puffers kann in der culfw eingestellt werden in dem das define TTY_BUFSIZE in der Datei [https://sourceforge.net/p/culfw/code/HEAD/tree/trunk/culfw/Devices/nanoCUL/board.h board.h] des passenden Devices angepasst wird.&lt;br /&gt;
Dabei ist darauf zu achten, dass die verwendeten Mikrocontroller nur sehr wenig RAM haben (0,5-4KB). Um mehr freies RAM zu erhalten sollten Protokolle die nicht benötigt in der board.h abgeschaltet werden. Die Unterstützung für WMBUS (#define HAS_MBUS 1) muss aber natürlich eingeschaltet werden.  &lt;br /&gt;
Anschließend ist die culfw [[Selbstbau_CUL#Software|neu zu übersetzen und zu flashen]].&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Forumsthread {{Link2Forum|Topic=24517}}&lt;br /&gt;
* Protokoll Beschreibung [http://oms-group.org/download4all/]&lt;br /&gt;
* Beschreibung des M-BUS Protokolls [http://www.m-bus.com/files/MBDOC48.PDF]&lt;br /&gt;
[[Kategorie:Energieverbrauchsmessung]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=WMBUS&amp;diff=31165</id>
		<title>WMBUS</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=WMBUS&amp;diff=31165"/>
		<updated>2019-09-01T16:29:02Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: /* Bekannte Probleme */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=Dekodierung von Wireless M-Bus Nachrichten&lt;br /&gt;
|ModType=d&lt;br /&gt;
|ModForumArea=Sonstige Systeme&lt;br /&gt;
|ModTechName=36_WMBUS.pm&lt;br /&gt;
|ModOwner=kaihs&lt;br /&gt;
}}&lt;br /&gt;
[[WMBUS]] ist ein Modul zur Dekodierung von Wireless M-Bus Nachrichten. Solche Nachrichten werden z. B. von Zählern für Wasser, Wärme, Gas und Elektrizität ausgestrahlt.&lt;br /&gt;
Wireless M-Bus ist ein Standardprotokoll das von unterschiedlichen Herstellern unterstützt wird.&lt;br /&gt;
Das Protokoll unterstützt unterschiedliche Kodierungen des Funksignals, im wesentlichen den S-Mode, T-Mode und C-Mode. Der Empfänger (z. B. ein CUL) muss den selben Modus nutzen wie der Sender (der Zähler). &lt;br /&gt;
Wireless M-Bus unterstützt optional die Verschlüsselung der Daten.&lt;br /&gt;
Die von einem Zähler gesendeten Daten können sehr unterschiedlich sein und hängen u. a. vom Zählertyp und dessen Hersteller ab.&lt;br /&gt;
&lt;br /&gt;
== Voraussetzungen ==&lt;br /&gt;
Das Modul interpretiert nur die Nachrichten die von einen geeigneten Empfänger empfangen werden. Aktuell kann ein [[CUL]] und verwandte Geräte die die culfw[http://culfw.de/culfw.html] verwenden sowie ein Amber Wireless AMB8465M dafür verwendet werden. In der culfw muss die Unterstützung des WMBUS-Protokolls aktiviert sein (#define HAS_MBUS in der Datei board.h des Deviceverzeichnisses). Bei einem CUL mit der Hardwareversion V4 ist das nicht der Fall.&lt;br /&gt;
&lt;br /&gt;
Der CUL muss in FHEM mittels Attribut rfmode=WMBus_S, WMBus_T oder WMBus_C in den zum Zähler passenden Empfangsmodus versetzt werden.&lt;br /&gt;
&lt;br /&gt;
== Anwendung ==&lt;br /&gt;
Die Erzeugung des passenden Devices in FHEM geschieht automatisch beim Empfang des ersten Datenpakets eines Zählers. Voraussetzung dafür ist, dass [[autocreate]] aktiv ist.&lt;br /&gt;
Alternativ kann ein Device manuell angelegt werden. Dazu wird der Hersteller, die Seriennummer, die Version und der Typ (Wasser, Gas, ...) des Zählers benötigt.&lt;br /&gt;
Sind die Daten verschlüsselt wird auch noch der passende Schlüssel benötigt um die Daten entschlüsseln zu können.&lt;br /&gt;
&lt;br /&gt;
== Verschlüsselung ==&lt;br /&gt;
Die Daten können auf drei verschiedene Arten verschlüsselt sein:&lt;br /&gt;
# Security profile A/Symmetric encryption with Mode 5&lt;br /&gt;
# Security profile B/Advanced symmetric encryption with Mode 7&lt;br /&gt;
# Security profile C/Asymmetric encryption with Mode 13&lt;br /&gt;
&lt;br /&gt;
Das Modul unterstützt aktuell Daten die per 1 oder 2 verschlüsselt wurden.&lt;br /&gt;
&lt;br /&gt;
== Anwendungsbeispiele ==&lt;br /&gt;
Ein per [[EnergyCam]] abgelesener Elektrizitätszähler sieht in FHEM z. B. so aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 Internals: &lt;br /&gt;
   CUL_MBUS_MSGCNT 29 &lt;br /&gt;
   CUL_MBUS_RAWMSG b1944C4189985051701028A7D7A540000A00405FAD4080002FD08222C1295B8::-67.5 &lt;br /&gt;
   CUL_MBUS_RSSI -67.5 &lt;br /&gt;
   CUL_MBUS_TIME 2014-10-24 22:57:53 &lt;br /&gt;
   DEF        FFD 17058599 1 2 &lt;br /&gt;
   DeviceMedium Electricity &lt;br /&gt;
   DeviceType 2 &lt;br /&gt;
   IODev      CUL_MBUS &lt;br /&gt;
   IdentNumber 17058599 &lt;br /&gt;
   LASTInputDev CUL_MBUS &lt;br /&gt;
   MSGCNT     29 &lt;br /&gt;
   Manufacturer FFD &lt;br /&gt;
   NAME       WMBUS_FFD_17058599_1_2 &lt;br /&gt;
   NR         49 &lt;br /&gt;
   STATE      no errors &lt;br /&gt;
   TYPE       WMBUS &lt;br /&gt;
   Version    1 &lt;br /&gt;
   addr       FFD_17058599_1_2 &lt;br /&gt;
   Readings: &lt;br /&gt;
     2014-10-24 22:57:53   1_storage_no    0 &lt;br /&gt;
     2014-10-24 22:57:53   1_type          VIF_ENERGY_WATT &lt;br /&gt;
     2014-10-24 22:57:53   1_unit          Wh &lt;br /&gt;
     2014-10-24 22:57:53   1_value         57881000 &lt;br /&gt;
     2014-10-24 22:57:53   2_storage_no    0 &lt;br /&gt;
     2014-10-24 22:57:53   2_type          VIF_ACCESS_NO &lt;br /&gt;
     2014-10-24 22:57:53   2_unit &lt;br /&gt;
     2014-10-24 22:57:53   2_value         11298 &lt;br /&gt;
     2014-10-24 22:57:53   LQI             184 &lt;br /&gt;
     2014-10-24 22:57:53   RSSI            -67.5 &lt;br /&gt;
     2014-10-24 22:57:53   battery         ok &lt;br /&gt;
     2014-10-24 22:57:53   decryption_ok   1 &lt;br /&gt;
     2014-10-24 22:57:53   energy          57881 &lt;br /&gt;
     2014-10-24 22:57:53   is_encrypted    0 &lt;br /&gt;
     2014-10-24 22:57:53   state           no errors &lt;br /&gt;
     2014-10-24 22:57:53   unit            kWh &lt;br /&gt;
 Attributes: &lt;br /&gt;
   IODev      CUL_MBUS &lt;br /&gt;
   room       WMBUS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Bekannte Probleme ==&lt;br /&gt;
=== Inkompatible Zähler ===&lt;br /&gt;
Obwohl Wireless M-Bus ein standardisiertes Protokoll ist, scheint sich kaum ein Hersteller vollständig daran zu halten bzw. verwendet sog. herstellerspezifische Felder um wichtige Daten zu verpacken.&lt;br /&gt;
Aus den bisher beobachteten Datenpaketen ergibt sich &lt;br /&gt;
* Qundis (Herstellerkürzel LSE) verwendet herstellerspezifische Datenblöcke für den eigentlichen Zählerstand&lt;br /&gt;
* Techem und Hydrometer verwenden ein undokumentiertes Datenformat (CI-Field A2)&lt;br /&gt;
:&#039;&#039;(Techem Heizkostenverteiler (CI-Field A0) können über das Modul [[TechemHKV]] ausgewertet werden)&#039;&#039;&lt;br /&gt;
* RWE SmartHome Powercontrol[http://www.rwe-smarthome.de/web/cms/de/1776202/smarthome/informieren/geraete/power-control/] sendet verschlüsselt und der Hersteller gibt nicht den vollständigen Schlüssel an ({{Link2Forum|Topic=24517|Message=315949}})&lt;br /&gt;
&lt;br /&gt;
Daher werden bisher erst die [[EnergyCam]] der Firma Q-loud, Zähler von Easymeter und der Kamstrup Multical 21 vollständig unterstützt.&lt;br /&gt;
Für den Multical 21 muss eine culfw mit Unterstützung für WMBUS C verwendet werden. Diese ist in der culfw ab dem 24.6.2018 enthalten.&lt;br /&gt;
&lt;br /&gt;
Andere Zähler können auch ohne Probleme funktionieren wenn diese sich an den OMS Standard halten.&lt;br /&gt;
&lt;br /&gt;
=== Empfangsprobleme ===&lt;br /&gt;
Der Empfänger (meist ein [[CUL]]) muss das WMBUS Protokoll unterstützen. Die Unterstützung ist vorhanden, wenn in der Ausgabe von &amp;lt;code&amp;gt;get cmds&amp;lt;/code&amp;gt; ein kleines [http://culfw.de/commandref.html#cmd_b b] enthalten ist.&lt;br /&gt;
Der CUL speichert die empfangenen Daten intern zwischen bevor sie an fhem geschickt werden. Der Puffer für die Speicherung muss groß genug sein, um ein komplettes Datenpaket aufzunehmen. Die Größe des Puffers kann in der culfw eingestellt werden in dem das define TTY_BUFSIZE in der Datei [https://sourceforge.net/p/culfw/code/HEAD/tree/trunk/culfw/Devices/nanoCUL/board.h board.h] des passenden Devices angepasst wird.&lt;br /&gt;
Dabei ist darauf zu achten, dass die verwendeten Mikrocontroller nur sehr wenig RAM haben (0,5-4KB). Um mehr freies RAM zu erhalten sollten Protokolle die nicht benötigt in der board.h abgeschaltet werden.   &lt;br /&gt;
Anschließend ist die culfw [[Selbstbau_CUL#Software|neu zu übersetzen und zu flashen]].&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Forumsthread {{Link2Forum|Topic=24517}}&lt;br /&gt;
* Protokoll Beschreibung [http://oms-group.org/download4all/]&lt;br /&gt;
* Beschreibung des M-BUS Protokolls [http://www.m-bus.com/files/MBDOC48.PDF]&lt;br /&gt;
[[Kategorie:Energieverbrauchsmessung]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=WMBUS&amp;diff=31149</id>
		<title>WMBUS</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=WMBUS&amp;diff=31149"/>
		<updated>2019-08-24T18:09:52Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: /* Bekannte Probleme */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=Dekodierung von Wireless M-Bus Nachrichten&lt;br /&gt;
|ModType=d&lt;br /&gt;
|ModForumArea=Sonstige Systeme&lt;br /&gt;
|ModTechName=36_WMBUS.pm&lt;br /&gt;
|ModOwner=kaihs&lt;br /&gt;
}}&lt;br /&gt;
[[WMBUS]] ist ein Modul zur Dekodierung von Wireless M-Bus Nachrichten. Solche Nachrichten werden z. B. von Zählern für Wasser, Wärme, Gas und Elektrizität ausgestrahlt.&lt;br /&gt;
Wireless M-Bus ist ein Standardprotokoll das von unterschiedlichen Herstellern unterstützt wird.&lt;br /&gt;
Das Protokoll unterstützt unterschiedliche Kodierungen des Funksignals, im wesentlichen den S-Mode, T-Mode und C-Mode. Der Empfänger (z. B. ein CUL) muss den selben Modus nutzen wie der Sender (der Zähler). &lt;br /&gt;
Wireless M-Bus unterstützt optional die Verschlüsselung der Daten.&lt;br /&gt;
Die von einem Zähler gesendeten Daten können sehr unterschiedlich sein und hängen u. a. vom Zählertyp und dessen Hersteller ab.&lt;br /&gt;
&lt;br /&gt;
== Voraussetzungen ==&lt;br /&gt;
Das Modul interpretiert nur die Nachrichten die von einen geeigneten Empfänger empfangen werden. Aktuell kann ein [[CUL]] und verwandte Geräte die die culfw[http://culfw.de/culfw.html] verwenden sowie ein Amber Wireless AMB8465M dafür verwendet werden. In der culfw muss die Unterstützung des WMBUS-Protokolls aktiviert sein (#define HAS_MBUS in der Datei board.h des Deviceverzeichnisses). Bei einem CUL mit der Hardwareversion V4 ist das nicht der Fall.&lt;br /&gt;
&lt;br /&gt;
Der CUL muss in FHEM mittels Attribut rfmode=WMBus_S, WMBus_T oder WMBus_C in den zum Zähler passenden Empfangsmodus versetzt werden.&lt;br /&gt;
&lt;br /&gt;
== Anwendung ==&lt;br /&gt;
Die Erzeugung des passenden Devices in FHEM geschieht automatisch beim Empfang des ersten Datenpakets eines Zählers. Voraussetzung dafür ist, dass [[autocreate]] aktiv ist.&lt;br /&gt;
Alternativ kann ein Device manuell angelegt werden. Dazu wird der Hersteller, die Seriennummer, die Version und der Typ (Wasser, Gas, ...) des Zählers benötigt.&lt;br /&gt;
Sind die Daten verschlüsselt wird auch noch der passende Schlüssel benötigt um die Daten entschlüsseln zu können.&lt;br /&gt;
&lt;br /&gt;
== Verschlüsselung ==&lt;br /&gt;
Die Daten können auf drei verschiedene Arten verschlüsselt sein:&lt;br /&gt;
# Security profile A/Symmetric encryption with Mode 5&lt;br /&gt;
# Security profile B/Advanced symmetric encryption with Mode 7&lt;br /&gt;
# Security profile C/Asymmetric encryption with Mode 13&lt;br /&gt;
&lt;br /&gt;
Das Modul unterstützt aktuell Daten die per 1 oder 2 verschlüsselt wurden.&lt;br /&gt;
&lt;br /&gt;
== Anwendungsbeispiele ==&lt;br /&gt;
Ein per [[EnergyCam]] abgelesener Elektrizitätszähler sieht in FHEM z. B. so aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 Internals: &lt;br /&gt;
   CUL_MBUS_MSGCNT 29 &lt;br /&gt;
   CUL_MBUS_RAWMSG b1944C4189985051701028A7D7A540000A00405FAD4080002FD08222C1295B8::-67.5 &lt;br /&gt;
   CUL_MBUS_RSSI -67.5 &lt;br /&gt;
   CUL_MBUS_TIME 2014-10-24 22:57:53 &lt;br /&gt;
   DEF        FFD 17058599 1 2 &lt;br /&gt;
   DeviceMedium Electricity &lt;br /&gt;
   DeviceType 2 &lt;br /&gt;
   IODev      CUL_MBUS &lt;br /&gt;
   IdentNumber 17058599 &lt;br /&gt;
   LASTInputDev CUL_MBUS &lt;br /&gt;
   MSGCNT     29 &lt;br /&gt;
   Manufacturer FFD &lt;br /&gt;
   NAME       WMBUS_FFD_17058599_1_2 &lt;br /&gt;
   NR         49 &lt;br /&gt;
   STATE      no errors &lt;br /&gt;
   TYPE       WMBUS &lt;br /&gt;
   Version    1 &lt;br /&gt;
   addr       FFD_17058599_1_2 &lt;br /&gt;
   Readings: &lt;br /&gt;
     2014-10-24 22:57:53   1_storage_no    0 &lt;br /&gt;
     2014-10-24 22:57:53   1_type          VIF_ENERGY_WATT &lt;br /&gt;
     2014-10-24 22:57:53   1_unit          Wh &lt;br /&gt;
     2014-10-24 22:57:53   1_value         57881000 &lt;br /&gt;
     2014-10-24 22:57:53   2_storage_no    0 &lt;br /&gt;
     2014-10-24 22:57:53   2_type          VIF_ACCESS_NO &lt;br /&gt;
     2014-10-24 22:57:53   2_unit &lt;br /&gt;
     2014-10-24 22:57:53   2_value         11298 &lt;br /&gt;
     2014-10-24 22:57:53   LQI             184 &lt;br /&gt;
     2014-10-24 22:57:53   RSSI            -67.5 &lt;br /&gt;
     2014-10-24 22:57:53   battery         ok &lt;br /&gt;
     2014-10-24 22:57:53   decryption_ok   1 &lt;br /&gt;
     2014-10-24 22:57:53   energy          57881 &lt;br /&gt;
     2014-10-24 22:57:53   is_encrypted    0 &lt;br /&gt;
     2014-10-24 22:57:53   state           no errors &lt;br /&gt;
     2014-10-24 22:57:53   unit            kWh &lt;br /&gt;
 Attributes: &lt;br /&gt;
   IODev      CUL_MBUS &lt;br /&gt;
   room       WMBUS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Bekannte Probleme ==&lt;br /&gt;
Obwohl Wireless M-Bus ein standardisiertes Protokoll ist, scheint sich kaum ein Hersteller vollständig daran zu halten bzw. verwendet sog. herstellerspezifische Felder um wichtige Daten zu verpacken.&lt;br /&gt;
Aus den bisher beobachteten Datenpaketen ergibt sich &lt;br /&gt;
* Qundis (Herstellerkürzel LSE) verwendet herstellerspezifische Datenblöcke für den eigentlichen Zählerstand&lt;br /&gt;
* Techem und Hydrometer verwenden ein undokumentiertes Datenformat (CI-Field A2)&lt;br /&gt;
:&#039;&#039;(Techem Heizkostenverteiler (CI-Field A0) können über das Modul [[TechemHKV]] ausgewertet werden)&#039;&#039;&lt;br /&gt;
* RWE SmartHome Powercontrol[http://www.rwe-smarthome.de/web/cms/de/1776202/smarthome/informieren/geraete/power-control/] sendet verschlüsselt und der Hersteller gibt nicht den vollständigen Schlüssel an{{Link2Forum|Topic=24517|Message=315949}}&lt;br /&gt;
&lt;br /&gt;
Daher werden bisher erst die [[EnergyCam]] der Firma Q-loud, Zähler von Easymeter und der Kamstrup Multical 21 vollständig unterstützt.&lt;br /&gt;
Für den Multical 21 muss eine culfw mit Unterstützung für WMBUS C verwendet werden. Diese ist in der culfw ab dem 24.6.2018 enthalten.&lt;br /&gt;
&lt;br /&gt;
Andere Zähler können auch ohne Probleme funktionieren wenn diese sich an den OMS Standard halten.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Forumsthread {{Link2Forum|Topic=24517}}&lt;br /&gt;
* Protokoll Beschreibung [http://oms-group.org/download4all/]&lt;br /&gt;
* Beschreibung des M-BUS Protokolls [http://www.m-bus.com/files/MBDOC48.PDF]&lt;br /&gt;
[[Kategorie:Energieverbrauchsmessung]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=WMBUS&amp;diff=31133</id>
		<title>WMBUS</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=WMBUS&amp;diff=31133"/>
		<updated>2019-08-18T15:00:24Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: Verschlüsselung&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=Dekodierung von Wireless M-Bus Nachrichten&lt;br /&gt;
|ModType=d&lt;br /&gt;
|ModForumArea=Sonstige Systeme&lt;br /&gt;
|ModTechName=36_WMBUS.pm&lt;br /&gt;
|ModOwner=kaihs&lt;br /&gt;
}}&lt;br /&gt;
[[WMBUS]] ist ein Modul zur Dekodierung von Wireless M-Bus Nachrichten. Solche Nachrichten werden z. B. von Zählern für Wasser, Wärme, Gas und Elektrizität ausgestrahlt.&lt;br /&gt;
Wireless M-Bus ist ein Standardprotokoll das von unterschiedlichen Herstellern unterstützt wird.&lt;br /&gt;
Das Protokoll unterstützt unterschiedliche Kodierungen des Funksignals, im wesentlichen den S-Mode, T-Mode und C-Mode. Der Empfänger (z. B. ein CUL) muss den selben Modus nutzen wie der Sender (der Zähler). &lt;br /&gt;
Wireless M-Bus unterstützt optional die Verschlüsselung der Daten.&lt;br /&gt;
Die von einem Zähler gesendeten Daten können sehr unterschiedlich sein und hängen u. a. vom Zählertyp und dessen Hersteller ab.&lt;br /&gt;
&lt;br /&gt;
== Voraussetzungen ==&lt;br /&gt;
Das Modul interpretiert nur die Nachrichten die von einen geeigneten Empfänger empfangen werden. Aktuell kann ein [[CUL]] und verwandte Geräte die die culfw[http://culfw.de/culfw.html] verwenden sowie ein Amber Wireless AMB8465M dafür verwendet werden. In der culfw muss die Unterstützung des WMBUS-Protokolls aktiviert sein (#define HAS_MBUS in der Datei board.h des Deviceverzeichnisses). Bei einem CUL mit der Hardwareversion V4 ist das nicht der Fall.&lt;br /&gt;
&lt;br /&gt;
Der CUL muss in FHEM mittels Attribut rfmode=WMBus_S, WMBus_T oder WMBus_C in den zum Zähler passenden Empfangsmodus versetzt werden.&lt;br /&gt;
&lt;br /&gt;
== Anwendung ==&lt;br /&gt;
Die Erzeugung des passenden Devices in FHEM geschieht automatisch beim Empfang des ersten Datenpakets eines Zählers. Voraussetzung dafür ist, dass [[autocreate]] aktiv ist.&lt;br /&gt;
Alternativ kann ein Device manuell angelegt werden. Dazu wird der Hersteller, die Seriennummer, die Version und der Typ (Wasser, Gas, ...) des Zählers benötigt.&lt;br /&gt;
Sind die Daten verschlüsselt wird auch noch der passende Schlüssel benötigt um die Daten entschlüsseln zu können.&lt;br /&gt;
&lt;br /&gt;
== Verschlüsselung ==&lt;br /&gt;
Die Daten können auf drei verschiedene Arten verschlüsselt sein:&lt;br /&gt;
# Security profile A/Symmetric encryption with Mode 5&lt;br /&gt;
# Security profile B/Advanced symmetric encryption with Mode 7&lt;br /&gt;
# Security profile C/Asymmetric encryption with Mode 13&lt;br /&gt;
&lt;br /&gt;
Das Modul unterstützt aktuell Daten die per 1 oder 2 verschlüsselt wurden.&lt;br /&gt;
&lt;br /&gt;
== Anwendungsbeispiele ==&lt;br /&gt;
Ein per [[EnergyCam]] abgelesener Elektrizitätszähler sieht in FHEM z. B. so aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 Internals: &lt;br /&gt;
   CUL_MBUS_MSGCNT 29 &lt;br /&gt;
   CUL_MBUS_RAWMSG b1944C4189985051701028A7D7A540000A00405FAD4080002FD08222C1295B8::-67.5 &lt;br /&gt;
   CUL_MBUS_RSSI -67.5 &lt;br /&gt;
   CUL_MBUS_TIME 2014-10-24 22:57:53 &lt;br /&gt;
   DEF        FFD 17058599 1 2 &lt;br /&gt;
   DeviceMedium Electricity &lt;br /&gt;
   DeviceType 2 &lt;br /&gt;
   IODev      CUL_MBUS &lt;br /&gt;
   IdentNumber 17058599 &lt;br /&gt;
   LASTInputDev CUL_MBUS &lt;br /&gt;
   MSGCNT     29 &lt;br /&gt;
   Manufacturer FFD &lt;br /&gt;
   NAME       WMBUS_FFD_17058599_1_2 &lt;br /&gt;
   NR         49 &lt;br /&gt;
   STATE      no errors &lt;br /&gt;
   TYPE       WMBUS &lt;br /&gt;
   Version    1 &lt;br /&gt;
   addr       FFD_17058599_1_2 &lt;br /&gt;
   Readings: &lt;br /&gt;
     2014-10-24 22:57:53   1_storage_no    0 &lt;br /&gt;
     2014-10-24 22:57:53   1_type          VIF_ENERGY_WATT &lt;br /&gt;
     2014-10-24 22:57:53   1_unit          Wh &lt;br /&gt;
     2014-10-24 22:57:53   1_value         57881000 &lt;br /&gt;
     2014-10-24 22:57:53   2_storage_no    0 &lt;br /&gt;
     2014-10-24 22:57:53   2_type          VIF_ACCESS_NO &lt;br /&gt;
     2014-10-24 22:57:53   2_unit &lt;br /&gt;
     2014-10-24 22:57:53   2_value         11298 &lt;br /&gt;
     2014-10-24 22:57:53   LQI             184 &lt;br /&gt;
     2014-10-24 22:57:53   RSSI            -67.5 &lt;br /&gt;
     2014-10-24 22:57:53   battery         ok &lt;br /&gt;
     2014-10-24 22:57:53   decryption_ok   1 &lt;br /&gt;
     2014-10-24 22:57:53   energy          57881 &lt;br /&gt;
     2014-10-24 22:57:53   is_encrypted    0 &lt;br /&gt;
     2014-10-24 22:57:53   state           no errors &lt;br /&gt;
     2014-10-24 22:57:53   unit            kWh &lt;br /&gt;
 Attributes: &lt;br /&gt;
   IODev      CUL_MBUS &lt;br /&gt;
   room       WMBUS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Bekannte Probleme ==&lt;br /&gt;
Obwohl Wireless M-Bus ein standardisiertes Protokoll ist, scheint sich kaum ein Hersteller vollständig daran zu halten bzw. verwendet sog. herstellerspezifische Felder um wichtige Daten zu verpacken.&lt;br /&gt;
Aus den bisher beobachteten Datenpaketen ergibt sich &lt;br /&gt;
* Qundis (Herstellerkürzel LSE) verwendet herstellerspezifische Datenblöcke für den eigentlichen Zählerstand&lt;br /&gt;
* Techem und Hydrometer verwenden ein undokumentiertes Datenformat (CI-Field A2)&lt;br /&gt;
:&#039;&#039;(Techem Heizkostenverteiler (CI-Field A0) können über das Modul [[TechemHKV]] ausgewertet werden)&#039;&#039;&lt;br /&gt;
* RWE SmartHome Powercontrol[http://www.rwe-smarthome.de/web/cms/de/1776202/smarthome/informieren/geraete/power-control/] sendet verschlüsselt und der Hersteller gibt nicht den vollständigen Schlüssel an{{Link2Forum|Topic=24517|Message=315949}}&lt;br /&gt;
&lt;br /&gt;
Daher werden bisher erst die [[EnergyCam]] der Firma Q-loud, Zähler von Easymeter und der Kamstrup Multical 21 vollständig unterstützt.&lt;br /&gt;
Für den Multical 21 muss eine culfw mit Unterstützung für WMBUS C verwendet werden. Diese ist in der culfw ab dem 24.6.2018 enthalten.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Forumsthread {{Link2Forum|Topic=24517}}&lt;br /&gt;
* Protokoll Beschreibung [http://oms-group.org/download4all/]&lt;br /&gt;
* Beschreibung des M-BUS Protokolls [http://www.m-bus.com/files/MBDOC48.PDF]&lt;br /&gt;
[[Kategorie:Energieverbrauchsmessung]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=WMBUS&amp;diff=31132</id>
		<title>WMBUS</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=WMBUS&amp;diff=31132"/>
		<updated>2019-08-18T14:54:43Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: /* Voraussetzungen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=Dekodierung von Wireless M-Bus Nachrichten&lt;br /&gt;
|ModType=d&lt;br /&gt;
|ModForumArea=Sonstige Systeme&lt;br /&gt;
|ModTechName=36_WMBUS.pm&lt;br /&gt;
|ModOwner=kaihs&lt;br /&gt;
}}&lt;br /&gt;
[[WMBUS]] ist ein Modul zur Dekodierung von Wireless M-Bus Nachrichten. Solche Nachrichten werden z. B. von Zählern für Wasser, Wärme, Gas und Elektrizität ausgestrahlt.&lt;br /&gt;
Wireless M-Bus ist ein Standardprotokoll das von unterschiedlichen Herstellern unterstützt wird.&lt;br /&gt;
Das Protokoll unterstützt unterschiedliche Kodierungen des Funksignals, im wesentlichen den S-Mode, T-Mode und C-Mode. Der Empfänger (z. B. ein CUL) muss den selben Modus nutzen wie der Sender (der Zähler). &lt;br /&gt;
Wireless M-Bus unterstützt optional die Verschlüsselung der Daten per AES.&lt;br /&gt;
Die von einem Zähler gesendeten Daten können sehr unterschiedlich sein und hängen u. a. vom Zählertyp und dessen Hersteller ab.&lt;br /&gt;
&lt;br /&gt;
== Voraussetzungen ==&lt;br /&gt;
Das Modul interpretiert nur die Nachrichten die von einen geeigneten Empfänger empfangen werden. Aktuell kann ein [[CUL]] und verwandte Geräte die die culfw[http://culfw.de/culfw.html] verwenden sowie ein Amber Wireless AMB8465M dafür verwendet werden. In der culfw muss die Unterstützung des WMBUS-Protokolls aktiviert sein (#define HAS_MBUS in der Datei board.h des Deviceverzeichnisses). Bei einem CUL mit der Hardwareversion V4 ist das nicht der Fall.&lt;br /&gt;
&lt;br /&gt;
Der CUL muss in FHEM mittels Attribut rfmode=WMBus_S, WMBus_T oder WMBus_C in den zum Zähler passenden Empfangsmodus versetzt werden.&lt;br /&gt;
&lt;br /&gt;
== Anwendung ==&lt;br /&gt;
Die Erzeugung des passenden Devices in FHEM geschieht automatisch beim Empfang des ersten Datenpakets eines Zählers. Voraussetzung dafür ist, dass [[autocreate]] aktiv ist.&lt;br /&gt;
Alternativ kann ein Device manuell angelegt werden. Dazu wird der Hersteller, die Seriennummer, die Version und der Typ (Wasser, Gas, ...) des Zählers benötigt.&lt;br /&gt;
Sind die Daten verschlüsselt wird auch noch der passende Schlüssel benötigt um die Daten entschlüsseln zu können.&lt;br /&gt;
&lt;br /&gt;
== Anwendungsbeispiele ==&lt;br /&gt;
Ein per [[EnergyCam]] abgelesener Elektrizitätszähler sieht in FHEM z. B. so aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 Internals: &lt;br /&gt;
   CUL_MBUS_MSGCNT 29 &lt;br /&gt;
   CUL_MBUS_RAWMSG b1944C4189985051701028A7D7A540000A00405FAD4080002FD08222C1295B8::-67.5 &lt;br /&gt;
   CUL_MBUS_RSSI -67.5 &lt;br /&gt;
   CUL_MBUS_TIME 2014-10-24 22:57:53 &lt;br /&gt;
   DEF        FFD 17058599 1 2 &lt;br /&gt;
   DeviceMedium Electricity &lt;br /&gt;
   DeviceType 2 &lt;br /&gt;
   IODev      CUL_MBUS &lt;br /&gt;
   IdentNumber 17058599 &lt;br /&gt;
   LASTInputDev CUL_MBUS &lt;br /&gt;
   MSGCNT     29 &lt;br /&gt;
   Manufacturer FFD &lt;br /&gt;
   NAME       WMBUS_FFD_17058599_1_2 &lt;br /&gt;
   NR         49 &lt;br /&gt;
   STATE      no errors &lt;br /&gt;
   TYPE       WMBUS &lt;br /&gt;
   Version    1 &lt;br /&gt;
   addr       FFD_17058599_1_2 &lt;br /&gt;
   Readings: &lt;br /&gt;
     2014-10-24 22:57:53   1_storage_no    0 &lt;br /&gt;
     2014-10-24 22:57:53   1_type          VIF_ENERGY_WATT &lt;br /&gt;
     2014-10-24 22:57:53   1_unit          Wh &lt;br /&gt;
     2014-10-24 22:57:53   1_value         57881000 &lt;br /&gt;
     2014-10-24 22:57:53   2_storage_no    0 &lt;br /&gt;
     2014-10-24 22:57:53   2_type          VIF_ACCESS_NO &lt;br /&gt;
     2014-10-24 22:57:53   2_unit &lt;br /&gt;
     2014-10-24 22:57:53   2_value         11298 &lt;br /&gt;
     2014-10-24 22:57:53   LQI             184 &lt;br /&gt;
     2014-10-24 22:57:53   RSSI            -67.5 &lt;br /&gt;
     2014-10-24 22:57:53   battery         ok &lt;br /&gt;
     2014-10-24 22:57:53   decryption_ok   1 &lt;br /&gt;
     2014-10-24 22:57:53   energy          57881 &lt;br /&gt;
     2014-10-24 22:57:53   is_encrypted    0 &lt;br /&gt;
     2014-10-24 22:57:53   state           no errors &lt;br /&gt;
     2014-10-24 22:57:53   unit            kWh &lt;br /&gt;
 Attributes: &lt;br /&gt;
   IODev      CUL_MBUS &lt;br /&gt;
   room       WMBUS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Bekannte Probleme ==&lt;br /&gt;
Obwohl Wireless M-Bus ein standardisiertes Protokoll ist, scheint sich kaum ein Hersteller vollständig daran zu halten bzw. verwendet sog. herstellerspezifische Felder um wichtige Daten zu verpacken.&lt;br /&gt;
Aus den bisher beobachteten Datenpaketen ergibt sich &lt;br /&gt;
* Qundis (Herstellerkürzel LSE) verwendet herstellerspezifische Datenblöcke für den eigentlichen Zählerstand&lt;br /&gt;
* Techem und Hydrometer verwenden ein undokumentiertes Datenformat (CI-Field A2)&lt;br /&gt;
:&#039;&#039;(Techem Heizkostenverteiler (CI-Field A0) können über das Modul [[TechemHKV]] ausgewertet werden)&#039;&#039;&lt;br /&gt;
* RWE SmartHome Powercontrol[http://www.rwe-smarthome.de/web/cms/de/1776202/smarthome/informieren/geraete/power-control/] sendet verschlüsselt und der Hersteller gibt nicht den vollständigen Schlüssel an{{Link2Forum|Topic=24517|Message=315949}}&lt;br /&gt;
&lt;br /&gt;
Daher werden bisher erst die [[EnergyCam]] der Firma Q-loud, Zähler von Easymeter und der Kamstrup Multical 21 vollständig unterstützt.&lt;br /&gt;
Für den Multical 21 muss eine culfw mit Unterstützung für WMBUS C verwendet werden. Diese ist in der culfw ab dem 24.6.2018 enthalten.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Forumsthread {{Link2Forum|Topic=24517}}&lt;br /&gt;
* Protokoll Beschreibung [http://oms-group.org/download4all/]&lt;br /&gt;
* Beschreibung des M-BUS Protokolls [http://www.m-bus.com/files/MBDOC48.PDF]&lt;br /&gt;
[[Kategorie:Energieverbrauchsmessung]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Weather&amp;diff=31022</id>
		<title>Weather</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Weather&amp;diff=31022"/>
		<updated>2019-07-21T13:38:31Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: Einschränkungen von OpenWeatherMap&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|&#039;&#039;&#039;End of Live der Yahoo Weather API&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
Da die Yahoo Weather API zum 03.01.2019 abgeschaltet wurde, kann &#039;&#039;&#039;Weather&#039;&#039;&#039; keine Wetterdaten von Yahoo mehr beziehen!}}&lt;br /&gt;
&lt;br /&gt;
{{SEITENTITEL:Weather}}&lt;br /&gt;
{{&lt;br /&gt;
Infobox Modul&lt;br /&gt;
|ModPurpose=Wettervorhersagen von Yahoo abfragen.&lt;br /&gt;
|ModType=d&lt;br /&gt;
&amp;lt;!-- |ModCategory= (noch?) nicht verwendet --&amp;gt;&lt;br /&gt;
|ModCmdRef=Weather&lt;br /&gt;
|ModForumArea=Unterstützende Dienste/Wettermodule&lt;br /&gt;
|ModTechName=59_Weather.pm&lt;br /&gt;
|ModOwner=Dr. Boris Neubert&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Mit dem Modul [[Weather]] können aktuelle Wetterdaten und Wettervorhersagen für einen bestimmten Ort von der Yahoo-Wetter-API regelmäßig abgefragt werden. &lt;br /&gt;
&lt;br /&gt;
== Anwendung ==&lt;br /&gt;
=== Define ===&lt;br /&gt;
siehe {{Link2CmdRef|Lang=de|Anker=Weatherdefine}}.&lt;br /&gt;
&lt;br /&gt;
=== Attribute ===&lt;br /&gt;
siehe {{Link2CmdRef|Lang=de|Anker=Weatherattr}}.&lt;br /&gt;
&lt;br /&gt;
=== API Besonderheiten ===&lt;br /&gt;
Das Openweathermap API liefert nur stundenweise Daten für drei Tage.&lt;br /&gt;
Daher funktioniert dass Attribut forecast daily nicht.&lt;br /&gt;
&lt;br /&gt;
== Anwendungsbeispiele ==&lt;br /&gt;
=== Beispiel zur Modul-Einrichtung ===&lt;br /&gt;
Zuerst einmal besuchen wir die [http://weather.yahoo.com Yahoo Wetterseite] und öffnen den Wetterbericht für die jeweilige Stadt (z.B. [http://weather.yahoo.com/germany/berlin/berlin-638242 Berlin]). In der URL des Wetterberichtes findet sich dann die sogenannte WOEID (WHERE-ON-EARTH-ID). Sie identifiziert die Wetterinfos, die FHEM abfragen soll. Für Berlin ist dies die Nummer 638242.&lt;br /&gt;
&lt;br /&gt;
In der [[Konfiguration]] richten wir dann folgendes ein:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# – Wetterdaten erfassen -&lt;br /&gt;
define MeinWetter Weather 638242 3600 de&lt;br /&gt;
attr MeinWetter room Wettervorhersage&lt;br /&gt;
&lt;br /&gt;
# - Logfile für alle Wetter Daten (monatsweise getrennt) —&lt;br /&gt;
define FileLog_MeinWetter FileLog ./log/meinwetter-%Y-%m.log MeinWetter&lt;br /&gt;
attr FileLog_MeinWetter logtype text&lt;br /&gt;
attr FileLog_MeinWetter room Wettervorhersage&lt;br /&gt;
&lt;br /&gt;
# — Wetter Icons in vertikaler Ansicht hinzufügen —&lt;br /&gt;
define weblink_meinwetter weblink htmlCode {WeatherAsHtml(&amp;quot;MeinWetter&amp;quot;,7)}&lt;br /&gt;
attr weblink_meinwetter room Wettervorhersage&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das hat zur Folge, dass FHEM nun die Wetterdaten für Berlin (638242) jede Stunde (3600) neu abholt. Zudem wird eine vertikale Ansicht der Wetterdaten der nächsten 7 Tage erstellt. Die Anzeige erfolgt im Raum &amp;quot;Wettervorhersage&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Konfigurationsschwierigkeiten ===&lt;br /&gt;
&lt;br /&gt;
Da Yahoo momentan auf mehreren Browsern Darstellungs-Schwierigkeiten hat, ist es schwer bis unmöglich, nach bestimmten Städten zu suchen (Search Box ist nicht erreichbar).&lt;br /&gt;
&lt;br /&gt;
Für diesen Fall gibt es aber noch die Möglichkeit, die WOEID auf [https://www.computerhilfen.de/hilfen-64-422419-0.html Yahoo WOEID: So bekommt man die &amp;quot;Where on Earth&amp;quot; ID einer Stadt!] zu erhalten.&lt;br /&gt;
Erfolgreich gefunden habe ich diese Seite übrigens über den Trick einer Internet-Suche nach &#039;&#039;mehreren&#039;&#039; dominant bekannten Städte-IDs (oder vielleicht einfach Internet-Suche nach &amp;quot;WOEID&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Weblink mit Stadtangabe für Wetter-Icons-Anzeige definieren: {{Link2Forum|Topic=31428|Message=267555}}&lt;br /&gt;
* Einrichtung einer automatische Aktualisierung der Wetter-Anzeige-Seite (Weblinks): {{Link2Forum|Topic=34581|Message=268957}}&lt;br /&gt;
* Anzahl der Icons definieren: {{Link2Forum|Topic=20481|Message=253464}}&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=TR%C3%85DFRI&amp;diff=29237</id>
		<title>TRÅDFRI</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=TR%C3%85DFRI&amp;diff=29237"/>
		<updated>2019-01-26T09:54:35Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: /* HUE-Device */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float:right&amp;quot;&amp;gt;{{Infobox Modul&lt;br /&gt;
|Name=tradfri&lt;br /&gt;
|ModPurpose=Anbindung IKEA TRÅDFRI Gateway&lt;br /&gt;
|ModType=d&lt;br /&gt;
&amp;lt;!-- |ModCategory= (noch?) nicht verwendet --&amp;gt;&lt;br /&gt;
|ModCmdRef=tradfri&lt;br /&gt;
|ModForumArea=Zigbee&lt;br /&gt;
|ModTechName=30_tradfri.pm&lt;br /&gt;
|ModOwner=Andre ([http://forum.fhem.de/index.php?action=profile;u=430 Forum] / [[Benutzer Diskussion:justme|Wiki]])&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== tradfri ==&lt;br /&gt;
&lt;br /&gt;
=== Einrichtung in FHEM ===&lt;br /&gt;
&lt;br /&gt;
# node installieren (mindestens version 8)&lt;br /&gt;
# sudo ppm install -g tradfri-fhem&lt;br /&gt;
# &amp;lt;code&amp;gt;define &amp;lt;tradfri&amp;gt; tradfri&amp;lt;/code&amp;gt;&lt;br /&gt;
# &amp;lt;code&amp;gt;attr &amp;lt;tradfri&amp;gt; tradfriFHEM-securityCode &amp;lt;security code&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
wenn das gateway nicht automatisch erkannt wird:&lt;br /&gt;
&amp;lt;code&amp;gt;attr &amp;lt;tradfri&amp;gt; tradfriFHEM-params --ip &amp;lt;ip&amp;gt;&amp;lt;/code&amp;gt;{{Randnotiz|RNTyp=r|RNText=Das Modul ist noch nicht eingecheckt und bis auf weiteres hier zu finden:{{Link2Forum|Topic=95272}} }}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
WICHTIG: danach in FHEM einmal die Konfiguration speichern damit der Pairing-Key gesichert wird. Sonst muss beim nächsten FHEM-Neustart das Pairing erneut durchgeführt werden.&lt;br /&gt;
&lt;br /&gt;
== HUE-Device ==&lt;br /&gt;
Alle auf dem Gateway bekannten Geräte automatisch als [[Hue#HUE-Device|HUEDevice]] in FHEM angelegt:&lt;br /&gt;
* Lampen, Stecker, Trafos, ...&lt;br /&gt;
: Hiermit werden die einzelnen Leuchten gesteuert&lt;br /&gt;
* Gruppen&lt;br /&gt;
: Hiermit lassen sich ganze Gruppen und Räume steuern&lt;br /&gt;
* Fernbedienungen&lt;br /&gt;
: aktuell gibt es nur ein battery Reading&lt;br /&gt;
&lt;br /&gt;
=== Darstellung im Webfrontend ===&lt;br /&gt;
Wenn man die SVG Icons verwendet ist es sinnvoll, das Attribut color-icons zu setzen. Mit &amp;lt;code&amp;gt;attr HUEDevice1 color-icons 2&amp;lt;/code&amp;gt; werden z.B. die Farben und der Dimmzustand der Lampe als Icon dargestellt.&lt;br /&gt;
Damit das ganze funktioniert, müsst ihr auch noch das &amp;lt;code&amp;gt;attr WEB iconPath fhemSVG:openautomation:default&amp;lt;/code&amp;gt; setzen.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:ZigBee Components]]&lt;br /&gt;
[[Kategorie:ZigBee]]&lt;br /&gt;
[[Kategorie:Lichteffektgeräte]]&lt;br /&gt;
[[Kategorie:IP Components]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Hue&amp;diff=29215</id>
		<title>Hue</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Hue&amp;diff=29215"/>
		<updated>2019-01-24T20:42:33Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: /* HUE-Device */ Müller Licht tint&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div style=&amp;quot;float:right&amp;quot;&amp;gt;{{Infobox Modul&lt;br /&gt;
|Name=HUEBridge&lt;br /&gt;
|ModPurpose=Anbindung Bridge des Philips Hue Lighting System&lt;br /&gt;
|ModType=d&lt;br /&gt;
&amp;lt;!-- |ModCategory= (noch?) nicht verwendet --&amp;gt;&lt;br /&gt;
|ModCmdRef=HUEBridge&lt;br /&gt;
|ModForumArea=Beleuchtung&lt;br /&gt;
|ModTechName=30_HUEBridge.pm&lt;br /&gt;
|ModOwner=Andre ([http://forum.fhem.de/index.php?action=profile;u=430 Forum] / [[Benutzer Diskussion:justme|Wiki]])&lt;br /&gt;
}}&lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|Name=HUEDevice&lt;br /&gt;
|ModPurpose=Ansteuerung Geräte des Philips Hue Lighting System über HUEBridge&lt;br /&gt;
|ModType=d&lt;br /&gt;
&amp;lt;!-- |ModCategory= (noch?) nicht verwendet --&amp;gt;&lt;br /&gt;
|ModCmdRef=HUEDevice&lt;br /&gt;
|ModForumArea=Beleuchtung&lt;br /&gt;
|ModTechName=31_HUEDevice.pm&lt;br /&gt;
|ModOwner=Andre ([http://forum.fhem.de/index.php?action=profile;u=430 Forum] / [[Benutzer Diskussion:justme|Wiki]])&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== HUE-Bridge ==&lt;br /&gt;
&lt;br /&gt;
=== Einrichtung in fhem ===&lt;br /&gt;
Die Einrichtung ist wirklich einfach. Mit&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;define Wiesollesheißen HUEBridge eu.re.ip.1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
wird die Bridge eingebunden. Dann einfach auf den runden Knopf in der Mitte der Bridge drücken und sie wird von FHEM erkannt. Die drei Lampen des Starterkits werden automatisch erkannt und sind ansteuerbar -&amp;gt; fertig!&lt;br /&gt;
&lt;br /&gt;
WICHTIG: danach in FHEM einmal die Konfiguration speichern damit der Pairing-Key gesichert wird. Sonst muss beim nächsten FHEM-Neustart das Pairing erneut durchgeführt werden.&lt;br /&gt;
&lt;br /&gt;
Eine ausführliche Anleitung mit Bildern zudem unter: http://www.meintechblog.de/2014/11/philips-hue-so-klappt-die-integration-in-fhem/&lt;br /&gt;
&lt;br /&gt;
Falls die Hue Bridge resetet wurde bleibt der Status auf &amp;quot;paired&amp;quot; und geht nicht mehr auf connected. Um das paring erneut durchzuführen muss das Attribut &amp;quot;key&amp;quot; gelöscht werden.&lt;br /&gt;
&lt;br /&gt;
=== Nonblocking ===&lt;br /&gt;
Wenn man möchte, dass die Versuche, die HUEBridge zu kontaktieren, FHEM nicht blockieren, sollte man &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;attr &amp;lt;HUEBridge_Name&amp;gt; httpUtils 1&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
setzen.&lt;br /&gt;
&lt;br /&gt;
== HUE-Device ==&lt;br /&gt;
Als Gerät können alle Hue und LightLink kompatiblen Modelle verwendet werden. Dies sind unter anderem:&lt;br /&gt;
*HueBulbs (E27, GU10, Lux, White, ...)&lt;br /&gt;
*Hue Beyond und Phoenix&lt;br /&gt;
*Friends of Hue LightStrips und LivingColors Bloom&lt;br /&gt;
*LivingColors ab gen2&lt;br /&gt;
*LivingColors Bloom, Iris und Aura&lt;br /&gt;
*LivingWhites Energiesparlampen&lt;br /&gt;
*LivingWhites Leuchtenadapter&lt;br /&gt;
*LivingWhites Bulbs&lt;br /&gt;
*[[HUE_Dimmer_Switch|Hue Tap und Hue Dimmer]] (mit Einschränkungen)&lt;br /&gt;
*dresden elektronik Vorschaltgeräte&lt;br /&gt;
*OSRAM LIGHTIFY Lampen (an der Hue Bridge angelernt)&lt;br /&gt;
*Müller Licht tint&lt;br /&gt;
&lt;br /&gt;
Diese sind jeweils über eine Bridge (HueDevice) steuerbar. Die LivingColors und LivingWhites Geräte sind vorher mit Hilfe einer LivingColors oder LivingWhites Fernbedienung an der Bridge anzulernen.&lt;br /&gt;
&lt;br /&gt;
Es werden auch alle HUE Sensoren unterstützt. Diese werden aber nicht per autocreate angelegt sondern müssen manuell definiert werden. Hier ist auf ein passendes polling Intervall zu achten. Siehe: [[HUE_Dimmer_Switch|HUE Dimmer Switch]]. Das [[Hue#RaspBee|RaspBee]] Gateway unterstützt auch ein PushAPI über das Sensoren ohne polling eingebunden werden können.&lt;br /&gt;
&lt;br /&gt;
=== Grundlagen - Farbmodelle ===&lt;br /&gt;
Ein HueDevice kann per set-Befehl über unterschiedliche Farbmodelle gesteuert werden. In der folgenden Tabelle ist dargestellt, welche Werte-Kombinationen sinnvoll sind:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Farbmodell !! Bestandteile !! Beispiel&lt;br /&gt;
|-&lt;br /&gt;
| xyY || x- und y-Koordinate im Farbraum, Y ist die Helligkeit || &amp;lt;code&amp;gt; set bulb1 xy 0.4595,0.4105 : bri 220 &amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| hue,sat,bri || Farbwert, Sättigung und Helligkeit || &amp;lt;code&amp;gt; set bulb1 hue 14922 : sat 144 : bri 220 &amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| ct || Farbwert über Farbtemperatur || &amp;lt;code&amp;gt; set bulb1 color 2600 &amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| rgb || Farbbestandteile rot, grün und blau || &amp;lt;code&amp;gt; set bulb1 rgb FFC698 &amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Zur Regelung der Helligkeit sind die Befehle &#039;&#039;bri&#039;&#039; und &#039;&#039;pct&#039;&#039; gleichwertig. &#039;&#039;bri&#039;&#039; hat den Bereich 0..254, &#039;&#039;pct&#039;&#039; 0..100 .&amp;lt;br&amp;gt;&lt;br /&gt;
Das Modul lässt die Mischung von Angaben aus unterschiedlichen Farbmodellen technisch zu, jedoch sind diese nicht immer sinnvoll.&lt;br /&gt;
&lt;br /&gt;
=== Darstellung im Webfrontend ===&lt;br /&gt;
Wenn man die SVG Icons verwendet ist es sinnvoll, das Attribut color-icons zu setzen. Mit &amp;lt;code&amp;gt;attr HUEDevice1 color-icons 2&amp;lt;/code&amp;gt; werden z.B. die Farben und der Dimmzustand der Lampe als Icon dargestellt.&lt;br /&gt;
Damit das ganze funktioniert, müsst ihr auch noch das &amp;lt;code&amp;gt;attr WEB iconPath fhemSVG:openautomation:default&amp;lt;/code&amp;gt; setzen.&lt;br /&gt;
&lt;br /&gt;
== RaspBee &amp;amp; ConBee ==&lt;br /&gt;
Das HUEBridge Modul unterstützt auch die ZigBee Gateway Module RaspBee und ConBee von Dresden Elektronik über die zugehörige deCONZ Software und die Wireless Light Control WebApp und die Phoscon WebApp (kommt zusammen mit deConz). Die hierzu erhältlichen Funk-Vorschaltgeräte sind noch nicht getestet sollten aber auch funktionieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im {{Link2Forum|Topic=80985|LinkText=Forum}} gibt es eine Betaversion der HUE Module, die das deCONZ PushAPI über Websockets unterstützen. Sensoren müssen hier nicht mehr gepollt werden.&lt;br /&gt;
&lt;br /&gt;
Mittlerweile funktioniert die Einbindung der RaspBee und ConBee Module auf einem sehr einfachen Weg. Dieser ist in  {{Link2Forum|Topic=95288|LinkText=Forum}} zusammengefasst. Zusätzliche Plugins sind nicht mehr nötig.&lt;br /&gt;
&lt;br /&gt;
== HUE auf der Fritzbox ==&lt;br /&gt;
Da auf der FB standardmäßig kein JSON installiert ist, muss dies nachinstalliert werden:  Man lädt das JSON-Paket http://search.cpan.org/CPAN/authors/id/M/MA/MAKAMAKA/JSON-2.53.tar.gz, packt es aus und kopiert den Inhalt vom &amp;lt;b&amp;gt;lib-Verzeichnis&amp;lt;/b&amp;gt; nach \fhem\lib\perl5\site_perl\5.12.2&lt;br /&gt;
&lt;br /&gt;
== HUE auf der Synology Diskstation ==&lt;br /&gt;
Da auf der DS standardmäßig kein JSON installiert ist, muss dies nachinstalliert werden, die Anleitung dazu {{Link2Forum|Topic=19093|Message=224641|LinkText=hier}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:ZigBee Components]]&lt;br /&gt;
[[Kategorie:ZigBee]]&lt;br /&gt;
[[Kategorie:Lichteffektgeräte]]&lt;br /&gt;
[[Kategorie:IP Components]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Creating_Plots&amp;diff=28906</id>
		<title>Creating Plots</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Creating_Plots&amp;diff=28906"/>
		<updated>2019-01-01T20:14:25Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: Änderung 28905 von Kaihs (Diskussion) rückgängig gemacht.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Randnotiz|RNTyp=[g|Info]|RNText=Hier wird das Anlegen per Hand beschrieben, was für Ungeübte umständlich und nicht empfehlenswert ist. &lt;br /&gt;
Mit &amp;quot;Create SVG Plot&amp;quot; in der FileLog-Detail-Ansicht steht inzwischen zur Vereinfachung ein Konfigurations-Frontend zur Verfügung: [[Plots_erzeugen|.gplot-Editor]].}} &lt;br /&gt;
= Howto create a PGM2/SVG plot - Introduction =&lt;br /&gt;
Output using the PGM2 engine is generated through .gplot files. The name is historical and today files can be generated using gnuplot or SVG graphics. This howto lists the most important aspects of generating a SVG configuration file.&lt;br /&gt;
&lt;br /&gt;
Each graphic generated by FHEM is described by one configuration file. It is currently not possible to generate one page with several graphics from one configuration file. &lt;br /&gt;
&lt;br /&gt;
Taking a high level view for each plot the following is needed:&lt;br /&gt;
&lt;br /&gt;
* Data from a logfile (create it using the FileLog facility)&lt;br /&gt;
* Plot configuration (.gplot) file knowing about the internal structure of the logfile&lt;br /&gt;
* Association between the FileLog and the plot configuration (using the &amp;quot;logtype&amp;quot; attribute in the FileLog and the LINK in the WebLink object, also see comments below)&lt;br /&gt;
* Weblink representing the plot itself&lt;br /&gt;
= FileLog objects =&lt;br /&gt;
Digging into the more murky details, first thing is the creation of the FileLog object:&lt;br /&gt;
&lt;br /&gt;
* The FileLog object is always associated with a physical device (but see comments below)&lt;br /&gt;
* The creation of a FileLog object together with the corresponding logfile is automatic if the &amp;quot;autocreate&amp;quot; attribute is set in FHEM (it is set by default)&lt;br /&gt;
* Manual creation is also possible and requires a statement like:&lt;br /&gt;
  &amp;lt;nowiki&amp;gt;&lt;br /&gt;
define FL_KS550 FileLog /var/log/fhem/KS550_%Y.log KS550:T:.*&lt;br /&gt;
define FileLog_ZwSt_1 FileLog /opt/fhem/var/log/ZwSt_1_%Y.log ZwSt_1&lt;br /&gt;
define FL_ZwSt_ALL FileLog /opt/fhem/var/log/ZwSt_ALL_%Y.log ZwSt_.*deviceMsg.*BidCoS_RF.* &lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Be it manual or automatic: the definition of a FileLog object determines (through the regular expression) which of the output lines of FHEM end up in the logfile&lt;br /&gt;
&lt;br /&gt;
= Plot definition =&lt;br /&gt;
Once the logfile is accumulating data, the plot configuration itself is needed. There is no object for this, but plain .gplot files in the share/FHEM directory are used by the system. A good start is to copy an existing one and modify it.&lt;br /&gt;
&lt;br /&gt;
On a side note: if you create your own files instead of using the ones already delivered with FHEM, stick to the convention of prepending them with a &amp;quot;my&amp;quot;. Files of pattern &amp;quot;my*&amp;quot; are guaranteed not to be overwritten during FHEM updates (or so Rudi promised me).&lt;br /&gt;
&lt;br /&gt;
The following entries are recognized in a SVG context:&lt;br /&gt;
&lt;br /&gt;
* #FileLog holds the information which data need to be extracted from the logfile. See below for details.&lt;br /&gt;
* Set commands: title, ylabel, y2label, yrange, y2range, ytics, y2tics, teminal (only &amp;quot;size&amp;quot; parameter is recognized)&lt;br /&gt;
* Plot command: see below for details&lt;br /&gt;
== Placeholders ==&lt;br /&gt;
It is possible to use placeholders in the .gplot files, which will then be replaced by information provided by the actual WebLink attributes listed below. This has the advantage that you can define one .gplot file and re-use it for several devices, changing size, title and lables accordingly instead of maintaining several separated files.&lt;br /&gt;
&lt;br /&gt;
* &amp;amp;lt;OUT&amp;amp;gt; : only relevant for gnuplot&lt;br /&gt;
* &amp;amp;lt;SIZE&amp;amp;gt;: attr plotsize&lt;br /&gt;
* &amp;amp;lt;TL&amp;amp;gt;  : attr title. The attribute is eval&#039;ed by perl at runtime, be careful and protect by double quotes if you just want to enter strings. This gives access to all internal FHEM values, though admittedly not straightforward&lt;br /&gt;
* &amp;amp;lt;Ln&amp;amp;gt;  : attr label. Lables 1-#n can be specified by a double-colon-separated (::) list, see below. This is also eval&#039;ed at runtime, same precautions apply&lt;br /&gt;
* &amp;amp;lt;IN&amp;amp;gt;  : &lt;br /&gt;
&lt;br /&gt;
In general this is good practice and you should especially consider it if you plan to distribute your .gplot files. Using placeholders f.ex. for the title and all the labels and curve descriptors gives other users the possibility to change them without having to touch the .gplot code.&lt;br /&gt;
&lt;br /&gt;
== Data Extraction ==&lt;br /&gt;
The central piece of the plotfile is the #FileLog line (yes, it must be prepended by a hash!), which is a special command und internally triggers the use of the FileLog &amp;quot;get&amp;quot; function, which extracts data from the logfile. The general syntax is: &amp;lt;nowiki&amp;gt;&amp;amp;lt;col&amp;amp;gt;:&amp;amp;lt;regexp&amp;amp;gt;:&amp;amp;lt;default&amp;amp;gt;:&amp;amp;lt;fn&amp;amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
. &lt;br /&gt;
* col: selects the column of the line (columns are white space separated, numbering starts at 1)&lt;br /&gt;
* regexp: validates/selects the line&lt;br /&gt;
* default: default value, if none is present&lt;br /&gt;
* fn: function which operates on values, pre-defined or eval&#039;ed, see below&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;get&amp;quot; function will set the following&amp;amp;#160;%data values (which can e.g. be used in titles, labels, ...) for each requested column (curve), beggining with &amp;amp;lt;x&amp;amp;gt; = 1:&lt;br /&gt;
&lt;br /&gt;
* min&amp;amp;lt;x&amp;amp;gt;, max&amp;amp;lt;x&amp;amp;gt;&lt;br /&gt;
* mindate&amp;amp;lt;x&amp;amp;gt;, maxdate&amp;amp;lt;x&amp;amp;gt;&lt;br /&gt;
* avg&amp;amp;lt;x&amp;amp;gt;, cnt&amp;amp;lt;x&amp;amp;gt;&lt;br /&gt;
* sum&amp;amp;lt;x&amp;amp;gt;&lt;br /&gt;
* currval&amp;amp;lt;x&amp;amp;gt; (last value)&lt;br /&gt;
* currdate&amp;amp;lt;x&amp;amp;gt; (last date)&lt;br /&gt;
So you can do something like &amp;lt;nowiki&amp;gt;attr &amp;amp;lt;weblink&amp;amp;gt; title &amp;amp;quot;Min $data{min1}, Max $data{max1}, Last $data{currval1}&amp;amp;quot;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Also implemented in this function is code which operates on the data retrieved. This can be specified at the &amp;quot;&amp;amp;lt;fn&amp;amp;gt;&amp;quot; tag. Up till now following functions are impemented:&lt;br /&gt;
&lt;br /&gt;
* int (to cut off % from a number, as for the actuator)&lt;br /&gt;
* delta-h / delta-d to get rain/h and rain/d values from continuous data&lt;br /&gt;
* And then there is this: the string is evaluated as a perl expression. @fld is the current line splitted by spaces (0-based). So you can do something like $fld[3]/1000 to plot values divided by 1000 or $fld[3]=~&amp;quot;on&amp;quot;?0.9:0.8 to map the 4th field which contains an on/off information into numerical values to be plotted in a graph. Be warned though: this string/perl expression cannot (!) contain any spaces.&lt;br /&gt;
&lt;br /&gt;
For even more details see [http://fhem.de/commandref.html#FileLog http://fhem.de/commandref.html#FileLog] or the module 92_FileLog.pm.&lt;br /&gt;
&lt;br /&gt;
== Debugging Data Extraction ==&lt;br /&gt;
If you do not get the result you are expecting or, worse, no data at all, you may use the debug facility of FHEM to see what the get-command extracts from the logfile. Use telnet to contact FHEM and then use the arguments detailed below ending with the #FileLog argument you are using in the .gplot file:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;telnet diskstation 7072&lt;br /&gt;
get FileLog_KS550&amp;amp;#160;?&lt;br /&gt;
get FileLog_KS550 - - 2012-01-01 2012-12-31 4::&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
You should get back the data which you have been asking for, followed by a line holding the .gplot argument. Make sure&lt;br /&gt;
&lt;br /&gt;
* you do not select too much data, this will possibly upset your NAS :-)&lt;br /&gt;
* you do select data which really are in the file (beware of year/month changes)&lt;br /&gt;
== Plot Commands ==&lt;br /&gt;
Once you have extracted the data from the logfile, you need to plot it. There is a plot command which does just that. It has several arguments which you can use:&lt;br /&gt;
&lt;br /&gt;
* axes: not needed by default, but if you want to plot curves which use different y axes, then you must tell the plot command, which y-axis the data should be bound to: &amp;quot;axes x1y1&amp;quot; selects the left, &amp;quot;axes x1y2&amp;quot; the right one&lt;br /&gt;
* title: defines the string which is printed in the colour of the curve into the plot. You can (and maybe should) use placeholders like &amp;quot;&amp;amp;lt;Lx&amp;amp;gt;&amp;quot;, x being a number&lt;br /&gt;
* with: defines how to draw the data. only points, steps, histeps and lines (which acts as a catch all) are currently implemented&lt;br /&gt;
* ls: uses CSS definitions, still need to figure out, how this works&lt;br /&gt;
* lw: defines the width of a line&lt;br /&gt;
== Example ==&lt;br /&gt;
A very barebones but functional example of a file using placeholders could be:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;set terminal size &amp;amp;lt;SIZE&amp;amp;gt;&lt;br /&gt;
set title &#039;&amp;amp;lt;TL&amp;amp;gt;&#039;&lt;br /&gt;
set ylabel &#039;&amp;amp;lt;L1&amp;amp;gt;&#039;&lt;br /&gt;
set y2label &#039;&amp;amp;lt;L2&amp;amp;gt;&#039;&lt;br /&gt;
#FileLog 4:::&lt;br /&gt;
plot \&lt;br /&gt;
   axes x1y1 title &#039;&amp;amp;lt;L3&amp;amp;gt;&#039; with steps lw 2&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
It implements the placeholders which can be defined by the user through the WebLink attributes later, selects just one column, without regular expression matches, defaults or subsequent data operations and plot is as a steps diagram. In fact even the &amp;quot;axes x1y1&amp;quot; statement could be left out, it would still work.&lt;br /&gt;
&lt;br /&gt;
== Changing text style ==&lt;br /&gt;
If you need a text style that is different from the style definition in fhemweb:&lt;br /&gt;
Add&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;text { font-family:Arial, Helvetica, sans-serif; font-size:12px; fill:#xxxxxx;}&lt;br /&gt;
text.title {font-family:Arial, Helvetica, sans-serif; font-size:16px; fill:#xxxxxx;}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where #xxxxxx is the color.&lt;br /&gt;
&lt;br /&gt;
== Transparent plots ==&lt;br /&gt;
If you need transparent plots, for example in FLOORPLAN, you have to change the following definitions in svg_style.css&lt;br /&gt;
&lt;br /&gt;
Change&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;.background { fill:#FFFFE7; }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
to:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;.background { fill:#FFFFE7;fill-opacity: 0; }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Change:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;.border { stroke:black; fill:url(#gr_bg); }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
to&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;.border { stroke:black; fill:url(#gr_bg);fill-opacity: 0; }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= WebLink objects =&lt;br /&gt;
Once you have created the FileLog object and written the plot specification, there is not much to be done. Click on the reference to the .gplot file in the FileLog section of a device, then click on the link for WebLink creation and then add the attributes you want to have. Put it into a suitable room and you are done.&lt;br /&gt;
&lt;br /&gt;
If you are using placeholders in your .gplot files and after defining your .gplot file you click onto a FileLog &amp;quot;active&amp;quot; link to create the plot itself and get a message like:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;XML Parsing Error: mismatched tag. Expected: &amp;amp;lt;/L1&amp;amp;gt;.&lt;br /&gt;
...&lt;br /&gt;
Line Number 51, Column 95:&amp;amp;lt;text x=&amp;amp;quot;12&amp;amp;quot; y=&amp;amp;quot;80&amp;amp;quot; text-anchor=&amp;amp;quot;middle&amp;amp;quot; class=&amp;amp;quot;ylabel&amp;amp;quot; transform=&amp;amp;quot;rotate(270,12,80)&amp;amp;quot;&amp;amp;gt;&#039;&amp;amp;lt;L1&amp;amp;gt;&#039;&amp;amp;lt;/text&amp;amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
you can safely ignore it. This is due to the fact, that you are using placeholders in the .gplot definition (which is good, because it favors reuseability) but have not yet defined the corresponding attributes. While annoying, this is not your fault: you can only define attributes once you have a weblink. So click on create weblink and define the attributes you have been using placeholders for. The error message should go away.&lt;br /&gt;
&lt;br /&gt;
The attributes which are generally needed are:&lt;br /&gt;
&lt;br /&gt;
* label: should be defined like &amp;quot;Label 1&amp;quot;::&amp;quot;Label 2&amp;quot;. Do not omit double quotes and use them individually for each label. Separator is a double (!) colon. If you ever manage to do away with the double quotes on the axes, please let us all know&lt;br /&gt;
* title: Can be as simple as &amp;quot;Some Title&amp;quot; or as complicated as &amp;quot;Temperature $data{currval1} ($data{min1}-$data{max1}), Humidity $data{currval2} ($data{min2}-$data{max2}) @ $data{currdate1}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= SVG Programs =&lt;br /&gt;
The SVG programs can be found in the 98_SVG.pm module. Look for example for the string &amp;quot;histeps&amp;quot;. Feel free to adapt and improve. If you ever program a wind rose to plot wind directions, please let me know. &lt;br /&gt;
&lt;br /&gt;
= Details =&lt;br /&gt;
What you also should know:&lt;br /&gt;
&lt;br /&gt;
* All data used in a plot come from one (!) file. It is currently not possible to mix data from several files. So make sure that the regular expression of the FileLog object catches everything which you need in one plot&lt;br /&gt;
* While it first seems evident that FileLog objects are associated with a given device, this must be mitigated. Imagine that you want to plot the state (and changes) of some socket adaptors (ZwischenStecker) over time. You then need to gather all the data (from several devices) in one file. So instead of define FileLog_ZwSt_1 FileLog /opt/fhem/var/log/ZwSt_1_%Y.log ZwSt_1 you need to specify define FL_ZwSt_ALL FileLog /opt/fhem/var/log/ZwSt_ALL_%Y.log ZwSt_.*deviceMsg.*BidCoS_RF.*&lt;br /&gt;
* Be careful when specifying the regular expression which filters the lines for a given logfile. While often it is sufficient to not specify a specific one at all, consider the following case from the Homematic world, where one action results in 4 lines of FHEM output. The switch communicates not only with the CCU, but also with the remote control, issuing 2 lines for each action:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;2012-01-01_07:40:23 ZwSt_3 deviceMsg: on (to Dev.WDisp.Kueche)&lt;br /&gt;
 2012-01-01_07:40:23 ZwSt_3 on&lt;br /&gt;
 2012-01-01_07:40:26 ZwSt_3 deviceMsg: on (to BidCoS_RF)&lt;br /&gt;
 2012-01-01_07:40:26 ZwSt_3 on&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Why one needs to specify a logtype (which is nothing else than a plot definition) for the FileLog has always been a mystery to me. It holds no useful information to the object itself and does not influence the way data is written to the associated logfile. Sure, plots need FileLogs, but not the other way round. And since the WebLink contains (again) the name of the plot definition file, the need to define the logtype attribute seems odd. The master himself says regarding this topic: &amp;quot;Ist eine Eigenschaft, die beschreibt, auf welche Art die Daten angezeigt werden koennen. Steht damit direkt neben den Daten, also da wo ich zuerst suchen wuerde. Ist nicht notwendig, aber so kann FHEMWEB ein &#039;create weblink&#039; anbieten.&amp;quot; I have to admit that this link is useful and I use to use it :-)&lt;br /&gt;
* If you meet on your way PERL-code snippets in the .gplot files, you can just ignore them safely. They are only used in the gnuplot world, not in SVG anymore. Now you may ask, where you find the corresponding features in SVG? They are hidden in functions defined in the FileLog &amp;quot;get&amp;quot; primitive.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
Documentation can be found in several places, it is not complete and you need to piece it together:&lt;br /&gt;
&lt;br /&gt;
* [http://fhem.de/HOWTO.html#plotting http://fhem.de/HOWTO.html#plotting]&lt;br /&gt;
* [http://fhem.de/commandref.html#FileLogget http://fhem.de/commandref.html#FileLogget]&lt;br /&gt;
* [http://fhem.de/commandref.html#label http://fhem.de/commandref.html#label]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Creating_Plots&amp;diff=28905</id>
		<title>Creating Plots</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Creating_Plots&amp;diff=28905"/>
		<updated>2019-01-01T20:13:53Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: Änderung 28904 von Kaihs (Diskussion) rückgängig gemacht.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Randnotiz|RNTyp=[g|Info]|RNText=Hier wird das Anlegen per Hand beschrieben, was für Ungeübte umständlich und nicht empfehlenswert ist. &lt;br /&gt;
Mit &amp;quot;Create SVG Plot&amp;quot; in der FileLog-Detail-Ansicht steht inzwischen zur Vereinfachung ein Konfigurations-Frontend zur Verfügung: [[Plots_erzeugen|.gplot-Editor]].}} &lt;br /&gt;
= Howto create a PGM2/SVG plot - Introduction =&lt;br /&gt;
Output using the PGM2 engine is generated through .gplot files. The name is historical and today files can be generated using gnuplot or SVG graphics. This howto lists the most important aspects of generating a SVG configuration file.&lt;br /&gt;
&lt;br /&gt;
Each graphic generated by FHEM is described by one configuration file. It is currently not possible to generate one page with several graphics from one configuration file. &lt;br /&gt;
&lt;br /&gt;
Taking a high level view for each plot the following is needed:&lt;br /&gt;
&lt;br /&gt;
* Data from a logfile (create it using the FileLog facility)&lt;br /&gt;
* Plot configuration (.gplot) file knowing about the internal structure of the logfile&lt;br /&gt;
* Association between the FileLog and the plot configuration (using the &amp;quot;logtype&amp;quot; attribute in the FileLog and the LINK in the WebLink object, also see comments below)&lt;br /&gt;
* Weblink representing the plot itself&lt;br /&gt;
= FileLog objects =&lt;br /&gt;
Digging into the more murky details, first thing is the creation of the FileLog object:&lt;br /&gt;
&lt;br /&gt;
* The FileLog object is always associated with a physical device (but see comments below)&lt;br /&gt;
* The creation of a FileLog object together with the corresponding logfile is automatic if the &amp;quot;autocreate&amp;quot; attribute is set in FHEM (it is set by default)&lt;br /&gt;
* Manual creation is also possible and requires a statement like:&lt;br /&gt;
  &amp;lt;nowiki&amp;gt;&lt;br /&gt;
define FL_KS550 FileLog /var/log/fhem/KS550_%Y.log KS550:T:.*&lt;br /&gt;
define FileLog_ZwSt_1 FileLog /opt/fhem/var/log/ZwSt_1_%Y.log ZwSt_1&lt;br /&gt;
define FL_ZwSt_ALL FileLog /opt/fhem/var/log/ZwSt_ALL_%Y.log ZwSt_.*deviceMsg.*BidCoS_RF.* &lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Be it manual or automatic: the definition of a FileLog object determines (through the regular expression) which of the output lines of FHEM end up in the logfile&lt;br /&gt;
&lt;br /&gt;
= Plot definition =&lt;br /&gt;
Once the logfile is accumulating data, the plot configuration itself is needed. There is no object for this, but plain .gplot files in the share/FHEM directory are used by the system. A good start is to copy an existing one and modify it.&lt;br /&gt;
&lt;br /&gt;
On a side note: if you create your own files instead of using the ones already delivered with FHEM, stick to the convention of prepending them with a &amp;quot;my&amp;quot;. Files of pattern &amp;quot;my*&amp;quot; are guaranteed not to be overwritten during FHEM updates (or so Rudi promised me).&lt;br /&gt;
&lt;br /&gt;
The following entries are recognized in a SVG context:&lt;br /&gt;
&lt;br /&gt;
* #FileLog holds the information which data need to be extracted from the logfile. See below for details.&lt;br /&gt;
* Set commands: title, ylabel, y2label, yrange, y2range, ytics, y2tics, teminal (only &amp;quot;size&amp;quot; parameter is recognized)&lt;br /&gt;
* Plot command: see below for details&lt;br /&gt;
== Placeholders ==&lt;br /&gt;
It is possible to use placeholders in the .gplot files, which will then be replaced by information provided by the actual WebLink attributes listed below. This has the advantage that you can define one .gplot file and re-use it for several devices, changing size, title and lables accordingly instead of maintaining several separated files.&lt;br /&gt;
&lt;br /&gt;
* &amp;amp;lt;OUT&amp;amp;gt; : only relevant for gnuplot&lt;br /&gt;
* &amp;amp;lt;SIZE&amp;amp;gt;: attr plotsize&lt;br /&gt;
* &amp;amp;lt;TL&amp;amp;gt;  : attr title. The attribute is eval&#039;ed by perl at runtime, be careful and protect by double quotes if you just want to enter strings. This gives access to all internal FHEM values, though admittedly not straightforward&lt;br /&gt;
* &amp;amp;lt;Ln&amp;amp;gt;  : attr label. Lables 1-#n can be specified by a double-colon-separated (::) list, see below. This is also eval&#039;ed at runtime, same precautions apply&lt;br /&gt;
* &amp;amp;lt;IN&amp;amp;gt;  : &lt;br /&gt;
&lt;br /&gt;
In general this is good practice and you should especially consider it if you plan to distribute your .gplot files. Using placeholders f.ex. for the title and all the labels and curve descriptors gives other users the possibility to change them without having to touch the .gplot code.&lt;br /&gt;
&lt;br /&gt;
== Data Extraction ==&lt;br /&gt;
The central piece of the plotfile is the #FileLog line (yes, it must be prepended by a hash!), which is a special command und internally triggers the use of the FileLog &amp;quot;get&amp;quot; function, which extracts data from the logfile. The general syntax is: &amp;lt;nowiki&amp;gt;&amp;amp;lt;col&amp;amp;gt;:&amp;amp;lt;regexp&amp;amp;gt;:&amp;amp;lt;default&amp;amp;gt;:&amp;amp;lt;fn&amp;amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
. &lt;br /&gt;
* col: selects the column of the line (columns are white space separated, numbering starts at 1)&lt;br /&gt;
* regexp: validates/selects the line&lt;br /&gt;
* default: default value, if none is present&lt;br /&gt;
* fn: function which operates on values, pre-defined or eval&#039;ed, see below&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;get&amp;quot; function will set the following&amp;amp;#160;%data values (which can e.g. be used in titles, labels, ...) for each requested column (curve), beggining with &amp;amp;lt;x&amp;amp;gt; = 1:&lt;br /&gt;
&lt;br /&gt;
* min&amp;amp;lt;x&amp;amp;gt;, max&amp;amp;lt;x&amp;amp;gt;&lt;br /&gt;
* mindate&amp;amp;lt;x&amp;amp;gt;, maxdate&amp;amp;lt;x&amp;amp;gt;&lt;br /&gt;
* avg&amp;amp;lt;x&amp;amp;gt;, cnt&amp;amp;lt;x&amp;amp;gt;&lt;br /&gt;
* sum&amp;amp;lt;x&amp;amp;gt;&lt;br /&gt;
* currval&amp;amp;lt;x&amp;amp;gt; (last value)&lt;br /&gt;
* currdate&amp;amp;lt;x&amp;amp;gt; (last date)&lt;br /&gt;
So you can do something like &amp;lt;nowiki&amp;gt;attr &amp;amp;lt;weblink&amp;amp;gt; title &amp;amp;quot;Min $data{min1}, Max $data{max1}, Last $data{currval1}&amp;amp;quot;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Also implemented in this function is code which operates on the data retrieved. This can be specified at the &amp;quot;&amp;amp;lt;fn&amp;amp;gt;&amp;quot; tag. Up till now following functions are impemented:&lt;br /&gt;
&lt;br /&gt;
* int (to cut off % from a number, as for the actuator)&lt;br /&gt;
* delta-h / delta-d to get rain/h and rain/d values from continuous data&lt;br /&gt;
* And then there is this: the string is evaluated as a perl expression. @fld is the current line splitted by spaces (0-based). So you can do something like $fld[3]/1000 to plot values divided by 1000 or $fld[3]=~&amp;quot;on&amp;quot;?0.9:0.8 to map the 4th field which contains an on/off information into numerical values to be plotted in a graph. Be warned though: this string/perl expression cannot (!) contain any spaces.&lt;br /&gt;
&lt;br /&gt;
For even more details see [http://fhem.de/commandref.html#FileLogger http://fhem.de/commandref.html#FileLogget] or the module 92_FileLog.pm.&lt;br /&gt;
&lt;br /&gt;
== Debugging Data Extraction ==&lt;br /&gt;
If you do not get the result you are expecting or, worse, no data at all, you may use the debug facility of FHEM to see what the get-command extracts from the logfile. Use telnet to contact FHEM and then use the arguments detailed below ending with the #FileLog argument you are using in the .gplot file:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;telnet diskstation 7072&lt;br /&gt;
get FileLog_KS550&amp;amp;#160;?&lt;br /&gt;
get FileLog_KS550 - - 2012-01-01 2012-12-31 4::&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
You should get back the data which you have been asking for, followed by a line holding the .gplot argument. Make sure&lt;br /&gt;
&lt;br /&gt;
* you do not select too much data, this will possibly upset your NAS :-)&lt;br /&gt;
* you do select data which really are in the file (beware of year/month changes)&lt;br /&gt;
== Plot Commands ==&lt;br /&gt;
Once you have extracted the data from the logfile, you need to plot it. There is a plot command which does just that. It has several arguments which you can use:&lt;br /&gt;
&lt;br /&gt;
* axes: not needed by default, but if you want to plot curves which use different y axes, then you must tell the plot command, which y-axis the data should be bound to: &amp;quot;axes x1y1&amp;quot; selects the left, &amp;quot;axes x1y2&amp;quot; the right one&lt;br /&gt;
* title: defines the string which is printed in the colour of the curve into the plot. You can (and maybe should) use placeholders like &amp;quot;&amp;amp;lt;Lx&amp;amp;gt;&amp;quot;, x being a number&lt;br /&gt;
* with: defines how to draw the data. only points, steps, histeps and lines (which acts as a catch all) are currently implemented&lt;br /&gt;
* ls: uses CSS definitions, still need to figure out, how this works&lt;br /&gt;
* lw: defines the width of a line&lt;br /&gt;
== Example ==&lt;br /&gt;
A very barebones but functional example of a file using placeholders could be:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;set terminal size &amp;amp;lt;SIZE&amp;amp;gt;&lt;br /&gt;
set title &#039;&amp;amp;lt;TL&amp;amp;gt;&#039;&lt;br /&gt;
set ylabel &#039;&amp;amp;lt;L1&amp;amp;gt;&#039;&lt;br /&gt;
set y2label &#039;&amp;amp;lt;L2&amp;amp;gt;&#039;&lt;br /&gt;
#FileLog 4:::&lt;br /&gt;
plot \&lt;br /&gt;
   axes x1y1 title &#039;&amp;amp;lt;L3&amp;amp;gt;&#039; with steps lw 2&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
It implements the placeholders which can be defined by the user through the WebLink attributes later, selects just one column, without regular expression matches, defaults or subsequent data operations and plot is as a steps diagram. In fact even the &amp;quot;axes x1y1&amp;quot; statement could be left out, it would still work.&lt;br /&gt;
&lt;br /&gt;
== Changing text style ==&lt;br /&gt;
If you need a text style that is different from the style definition in fhemweb:&lt;br /&gt;
Add&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;text { font-family:Arial, Helvetica, sans-serif; font-size:12px; fill:#xxxxxx;}&lt;br /&gt;
text.title {font-family:Arial, Helvetica, sans-serif; font-size:16px; fill:#xxxxxx;}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where #xxxxxx is the color.&lt;br /&gt;
&lt;br /&gt;
== Transparent plots ==&lt;br /&gt;
If you need transparent plots, for example in FLOORPLAN, you have to change the following definitions in svg_style.css&lt;br /&gt;
&lt;br /&gt;
Change&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;.background { fill:#FFFFE7; }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
to:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;.background { fill:#FFFFE7;fill-opacity: 0; }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Change:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;.border { stroke:black; fill:url(#gr_bg); }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
to&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;.border { stroke:black; fill:url(#gr_bg);fill-opacity: 0; }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= WebLink objects =&lt;br /&gt;
Once you have created the FileLog object and written the plot specification, there is not much to be done. Click on the reference to the .gplot file in the FileLog section of a device, then click on the link for WebLink creation and then add the attributes you want to have. Put it into a suitable room and you are done.&lt;br /&gt;
&lt;br /&gt;
If you are using placeholders in your .gplot files and after defining your .gplot file you click onto a FileLog &amp;quot;active&amp;quot; link to create the plot itself and get a message like:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;XML Parsing Error: mismatched tag. Expected: &amp;amp;lt;/L1&amp;amp;gt;.&lt;br /&gt;
...&lt;br /&gt;
Line Number 51, Column 95:&amp;amp;lt;text x=&amp;amp;quot;12&amp;amp;quot; y=&amp;amp;quot;80&amp;amp;quot; text-anchor=&amp;amp;quot;middle&amp;amp;quot; class=&amp;amp;quot;ylabel&amp;amp;quot; transform=&amp;amp;quot;rotate(270,12,80)&amp;amp;quot;&amp;amp;gt;&#039;&amp;amp;lt;L1&amp;amp;gt;&#039;&amp;amp;lt;/text&amp;amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
you can safely ignore it. This is due to the fact, that you are using placeholders in the .gplot definition (which is good, because it favors reuseability) but have not yet defined the corresponding attributes. While annoying, this is not your fault: you can only define attributes once you have a weblink. So click on create weblink and define the attributes you have been using placeholders for. The error message should go away.&lt;br /&gt;
&lt;br /&gt;
The attributes which are generally needed are:&lt;br /&gt;
&lt;br /&gt;
* label: should be defined like &amp;quot;Label 1&amp;quot;::&amp;quot;Label 2&amp;quot;. Do not omit double quotes and use them individually for each label. Separator is a double (!) colon. If you ever manage to do away with the double quotes on the axes, please let us all know&lt;br /&gt;
* title: Can be as simple as &amp;quot;Some Title&amp;quot; or as complicated as &amp;quot;Temperature $data{currval1} ($data{min1}-$data{max1}), Humidity $data{currval2} ($data{min2}-$data{max2}) @ $data{currdate1}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= SVG Programs =&lt;br /&gt;
The SVG programs can be found in the 98_SVG.pm module. Look for example for the string &amp;quot;histeps&amp;quot;. Feel free to adapt and improve. If you ever program a wind rose to plot wind directions, please let me know. &lt;br /&gt;
&lt;br /&gt;
= Details =&lt;br /&gt;
What you also should know:&lt;br /&gt;
&lt;br /&gt;
* All data used in a plot come from one (!) file. It is currently not possible to mix data from several files. So make sure that the regular expression of the FileLog object catches everything which you need in one plot&lt;br /&gt;
* While it first seems evident that FileLog objects are associated with a given device, this must be mitigated. Imagine that you want to plot the state (and changes) of some socket adaptors (ZwischenStecker) over time. You then need to gather all the data (from several devices) in one file. So instead of define FileLog_ZwSt_1 FileLog /opt/fhem/var/log/ZwSt_1_%Y.log ZwSt_1 you need to specify define FL_ZwSt_ALL FileLog /opt/fhem/var/log/ZwSt_ALL_%Y.log ZwSt_.*deviceMsg.*BidCoS_RF.*&lt;br /&gt;
* Be careful when specifying the regular expression which filters the lines for a given logfile. While often it is sufficient to not specify a specific one at all, consider the following case from the Homematic world, where one action results in 4 lines of FHEM output. The switch communicates not only with the CCU, but also with the remote control, issuing 2 lines for each action:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;2012-01-01_07:40:23 ZwSt_3 deviceMsg: on (to Dev.WDisp.Kueche)&lt;br /&gt;
 2012-01-01_07:40:23 ZwSt_3 on&lt;br /&gt;
 2012-01-01_07:40:26 ZwSt_3 deviceMsg: on (to BidCoS_RF)&lt;br /&gt;
 2012-01-01_07:40:26 ZwSt_3 on&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Why one needs to specify a logtype (which is nothing else than a plot definition) for the FileLog has always been a mystery to me. It holds no useful information to the object itself and does not influence the way data is written to the associated logfile. Sure, plots need FileLogs, but not the other way round. And since the WebLink contains (again) the name of the plot definition file, the need to define the logtype attribute seems odd. The master himself says regarding this topic: &amp;quot;Ist eine Eigenschaft, die beschreibt, auf welche Art die Daten angezeigt werden koennen. Steht damit direkt neben den Daten, also da wo ich zuerst suchen wuerde. Ist nicht notwendig, aber so kann FHEMWEB ein &#039;create weblink&#039; anbieten.&amp;quot; I have to admit that this link is useful and I use to use it :-)&lt;br /&gt;
* If you meet on your way PERL-code snippets in the .gplot files, you can just ignore them safely. They are only used in the gnuplot world, not in SVG anymore. Now you may ask, where you find the corresponding features in SVG? They are hidden in functions defined in the FileLog &amp;quot;get&amp;quot; primitive.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
Documentation can be found in several places, it is not complete and you need to piece it together:&lt;br /&gt;
&lt;br /&gt;
* [http://fhem.de/HOWTO.html#plotting http://fhem.de/HOWTO.html#plotting]&lt;br /&gt;
* [http://fhem.de/commandref.html#FileLogget http://fhem.de/commandref.html#FileLogget]&lt;br /&gt;
* [http://fhem.de/commandref.html#label http://fhem.de/commandref.html#label]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Creating_Plots&amp;diff=28904</id>
		<title>Creating Plots</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Creating_Plots&amp;diff=28904"/>
		<updated>2019-01-01T20:10:58Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: /* Data Extraction */ Typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Randnotiz|RNTyp=[g|Info]|RNText=Hier wird das Anlegen per Hand beschrieben, was für Ungeübte umständlich und nicht empfehlenswert ist. &lt;br /&gt;
Mit &amp;quot;Create SVG Plot&amp;quot; in der FileLog-Detail-Ansicht steht inzwischen zur Vereinfachung ein Konfigurations-Frontend zur Verfügung: [[Plots_erzeugen|.gplot-Editor]].}} &lt;br /&gt;
= Howto create a PGM2/SVG plot - Introduction =&lt;br /&gt;
Output using the PGM2 engine is generated through .gplot files. The name is historical and today files can be generated using gnuplot or SVG graphics. This howto lists the most important aspects of generating a SVG configuration file.&lt;br /&gt;
&lt;br /&gt;
Each graphic generated by FHEM is described by one configuration file. It is currently not possible to generate one page with several graphics from one configuration file. &lt;br /&gt;
&lt;br /&gt;
Taking a high level view for each plot the following is needed:&lt;br /&gt;
&lt;br /&gt;
* Data from a logfile (create it using the FileLog facility)&lt;br /&gt;
* Plot configuration (.gplot) file knowing about the internal structure of the logfile&lt;br /&gt;
* Association between the FileLog and the plot configuration (using the &amp;quot;logtype&amp;quot; attribute in the FileLog and the LINK in the WebLink object, also see comments below)&lt;br /&gt;
* Weblink representing the plot itself&lt;br /&gt;
= FileLog objects =&lt;br /&gt;
Digging into the more murky details, first thing is the creation of the FileLog object:&lt;br /&gt;
&lt;br /&gt;
* The FileLog object is always associated with a physical device (but see comments below)&lt;br /&gt;
* The creation of a FileLog object together with the corresponding logfile is automatic if the &amp;quot;autocreate&amp;quot; attribute is set in FHEM (it is set by default)&lt;br /&gt;
* Manual creation is also possible and requires a statement like:&lt;br /&gt;
  &amp;lt;nowiki&amp;gt;&lt;br /&gt;
define FL_KS550 FileLog /var/log/fhem/KS550_%Y.log KS550:T:.*&lt;br /&gt;
define FileLog_ZwSt_1 FileLog /opt/fhem/var/log/ZwSt_1_%Y.log ZwSt_1&lt;br /&gt;
define FL_ZwSt_ALL FileLog /opt/fhem/var/log/ZwSt_ALL_%Y.log ZwSt_.*deviceMsg.*BidCoS_RF.* &lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Be it manual or automatic: the definition of a FileLog object determines (through the regular expression) which of the output lines of FHEM end up in the logfile&lt;br /&gt;
&lt;br /&gt;
= Plot definition =&lt;br /&gt;
Once the logfile is accumulating data, the plot configuration itself is needed. There is no object for this, but plain .gplot files in the share/FHEM directory are used by the system. A good start is to copy an existing one and modify it.&lt;br /&gt;
&lt;br /&gt;
On a side note: if you create your own files instead of using the ones already delivered with FHEM, stick to the convention of prepending them with a &amp;quot;my&amp;quot;. Files of pattern &amp;quot;my*&amp;quot; are guaranteed not to be overwritten during FHEM updates (or so Rudi promised me).&lt;br /&gt;
&lt;br /&gt;
The following entries are recognized in a SVG context:&lt;br /&gt;
&lt;br /&gt;
* #FileLog holds the information which data need to be extracted from the logfile. See below for details.&lt;br /&gt;
* Set commands: title, ylabel, y2label, yrange, y2range, ytics, y2tics, teminal (only &amp;quot;size&amp;quot; parameter is recognized)&lt;br /&gt;
* Plot command: see below for details&lt;br /&gt;
== Placeholders ==&lt;br /&gt;
It is possible to use placeholders in the .gplot files, which will then be replaced by information provided by the actual WebLink attributes listed below. This has the advantage that you can define one .gplot file and re-use it for several devices, changing size, title and lables accordingly instead of maintaining several separated files.&lt;br /&gt;
&lt;br /&gt;
* &amp;amp;lt;OUT&amp;amp;gt; : only relevant for gnuplot&lt;br /&gt;
* &amp;amp;lt;SIZE&amp;amp;gt;: attr plotsize&lt;br /&gt;
* &amp;amp;lt;TL&amp;amp;gt;  : attr title. The attribute is eval&#039;ed by perl at runtime, be careful and protect by double quotes if you just want to enter strings. This gives access to all internal FHEM values, though admittedly not straightforward&lt;br /&gt;
* &amp;amp;lt;Ln&amp;amp;gt;  : attr label. Lables 1-#n can be specified by a double-colon-separated (::) list, see below. This is also eval&#039;ed at runtime, same precautions apply&lt;br /&gt;
* &amp;amp;lt;IN&amp;amp;gt;  : &lt;br /&gt;
&lt;br /&gt;
In general this is good practice and you should especially consider it if you plan to distribute your .gplot files. Using placeholders f.ex. for the title and all the labels and curve descriptors gives other users the possibility to change them without having to touch the .gplot code.&lt;br /&gt;
&lt;br /&gt;
== Data Extraction ==&lt;br /&gt;
The central piece of the plotfile is the #FileLog line (yes, it must be prepended by a hash!), which is a special command und internally triggers the use of the FileLog &amp;quot;get&amp;quot; function, which extracts data from the logfile. The general syntax is: &amp;lt;nowiki&amp;gt;&amp;amp;lt;col&amp;amp;gt;:&amp;amp;lt;regexp&amp;amp;gt;:&amp;amp;lt;default&amp;amp;gt;:&amp;amp;lt;fn&amp;amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
. &lt;br /&gt;
* col: selects the column of the line (columns are white space separated, numbering starts at 1)&lt;br /&gt;
* regexp: validates/selects the line&lt;br /&gt;
* default: default value, if none is present&lt;br /&gt;
* fn: function which operates on values, pre-defined or eval&#039;ed, see below&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;get&amp;quot; function will set the following&amp;amp;#160;%data values (which can e.g. be used in titles, labels, ...) for each requested column (curve), beggining with &amp;amp;lt;x&amp;amp;gt; = 1:&lt;br /&gt;
&lt;br /&gt;
* min&amp;amp;lt;x&amp;amp;gt;, max&amp;amp;lt;x&amp;amp;gt;&lt;br /&gt;
* mindate&amp;amp;lt;x&amp;amp;gt;, maxdate&amp;amp;lt;x&amp;amp;gt;&lt;br /&gt;
* avg&amp;amp;lt;x&amp;amp;gt;, cnt&amp;amp;lt;x&amp;amp;gt;&lt;br /&gt;
* sum&amp;amp;lt;x&amp;amp;gt;&lt;br /&gt;
* currval&amp;amp;lt;x&amp;amp;gt; (last value)&lt;br /&gt;
* currdate&amp;amp;lt;x&amp;amp;gt; (last date)&lt;br /&gt;
So you can do something like &amp;lt;nowiki&amp;gt;attr &amp;amp;lt;weblink&amp;amp;gt; title &amp;amp;quot;Min $data{min1}, Max $data{max1}, Last $data{currval1}&amp;amp;quot;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Also implemented in this function is code which operates on the data retrieved. This can be specified at the &amp;quot;&amp;amp;lt;fn&amp;amp;gt;&amp;quot; tag. Up till now following functions are impemented:&lt;br /&gt;
&lt;br /&gt;
* int (to cut off % from a number, as for the actuator)&lt;br /&gt;
* delta-h / delta-d to get rain/h and rain/d values from continuous data&lt;br /&gt;
* And then there is this: the string is evaluated as a perl expression. @fld is the current line splitted by spaces (0-based). So you can do something like $fld[3]/1000 to plot values divided by 1000 or $fld[3]=~&amp;quot;on&amp;quot;?0.9:0.8 to map the 4th field which contains an on/off information into numerical values to be plotted in a graph. Be warned though: this string/perl expression cannot (!) contain any spaces.&lt;br /&gt;
&lt;br /&gt;
For even more details see [http://fhem.de/commandref.html#FileLog http://fhem.de/commandref.html#FileLog] or the module 92_FileLog.pm.&lt;br /&gt;
&lt;br /&gt;
== Debugging Data Extraction ==&lt;br /&gt;
If you do not get the result you are expecting or, worse, no data at all, you may use the debug facility of FHEM to see what the get-command extracts from the logfile. Use telnet to contact FHEM and then use the arguments detailed below ending with the #FileLog argument you are using in the .gplot file:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;telnet diskstation 7072&lt;br /&gt;
get FileLog_KS550&amp;amp;#160;?&lt;br /&gt;
get FileLog_KS550 - - 2012-01-01 2012-12-31 4::&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
You should get back the data which you have been asking for, followed by a line holding the .gplot argument. Make sure&lt;br /&gt;
&lt;br /&gt;
* you do not select too much data, this will possibly upset your NAS :-)&lt;br /&gt;
* you do select data which really are in the file (beware of year/month changes)&lt;br /&gt;
== Plot Commands ==&lt;br /&gt;
Once you have extracted the data from the logfile, you need to plot it. There is a plot command which does just that. It has several arguments which you can use:&lt;br /&gt;
&lt;br /&gt;
* axes: not needed by default, but if you want to plot curves which use different y axes, then you must tell the plot command, which y-axis the data should be bound to: &amp;quot;axes x1y1&amp;quot; selects the left, &amp;quot;axes x1y2&amp;quot; the right one&lt;br /&gt;
* title: defines the string which is printed in the colour of the curve into the plot. You can (and maybe should) use placeholders like &amp;quot;&amp;amp;lt;Lx&amp;amp;gt;&amp;quot;, x being a number&lt;br /&gt;
* with: defines how to draw the data. only points, steps, histeps and lines (which acts as a catch all) are currently implemented&lt;br /&gt;
* ls: uses CSS definitions, still need to figure out, how this works&lt;br /&gt;
* lw: defines the width of a line&lt;br /&gt;
== Example ==&lt;br /&gt;
A very barebones but functional example of a file using placeholders could be:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;set terminal size &amp;amp;lt;SIZE&amp;amp;gt;&lt;br /&gt;
set title &#039;&amp;amp;lt;TL&amp;amp;gt;&#039;&lt;br /&gt;
set ylabel &#039;&amp;amp;lt;L1&amp;amp;gt;&#039;&lt;br /&gt;
set y2label &#039;&amp;amp;lt;L2&amp;amp;gt;&#039;&lt;br /&gt;
#FileLog 4:::&lt;br /&gt;
plot \&lt;br /&gt;
   axes x1y1 title &#039;&amp;amp;lt;L3&amp;amp;gt;&#039; with steps lw 2&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
It implements the placeholders which can be defined by the user through the WebLink attributes later, selects just one column, without regular expression matches, defaults or subsequent data operations and plot is as a steps diagram. In fact even the &amp;quot;axes x1y1&amp;quot; statement could be left out, it would still work.&lt;br /&gt;
&lt;br /&gt;
== Changing text style ==&lt;br /&gt;
If you need a text style that is different from the style definition in fhemweb:&lt;br /&gt;
Add&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;text { font-family:Arial, Helvetica, sans-serif; font-size:12px; fill:#xxxxxx;}&lt;br /&gt;
text.title {font-family:Arial, Helvetica, sans-serif; font-size:16px; fill:#xxxxxx;}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where #xxxxxx is the color.&lt;br /&gt;
&lt;br /&gt;
== Transparent plots ==&lt;br /&gt;
If you need transparent plots, for example in FLOORPLAN, you have to change the following definitions in svg_style.css&lt;br /&gt;
&lt;br /&gt;
Change&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;.background { fill:#FFFFE7; }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
to:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;.background { fill:#FFFFE7;fill-opacity: 0; }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Change:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;.border { stroke:black; fill:url(#gr_bg); }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
to&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;.border { stroke:black; fill:url(#gr_bg);fill-opacity: 0; }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= WebLink objects =&lt;br /&gt;
Once you have created the FileLog object and written the plot specification, there is not much to be done. Click on the reference to the .gplot file in the FileLog section of a device, then click on the link for WebLink creation and then add the attributes you want to have. Put it into a suitable room and you are done.&lt;br /&gt;
&lt;br /&gt;
If you are using placeholders in your .gplot files and after defining your .gplot file you click onto a FileLog &amp;quot;active&amp;quot; link to create the plot itself and get a message like:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;XML Parsing Error: mismatched tag. Expected: &amp;amp;lt;/L1&amp;amp;gt;.&lt;br /&gt;
...&lt;br /&gt;
Line Number 51, Column 95:&amp;amp;lt;text x=&amp;amp;quot;12&amp;amp;quot; y=&amp;amp;quot;80&amp;amp;quot; text-anchor=&amp;amp;quot;middle&amp;amp;quot; class=&amp;amp;quot;ylabel&amp;amp;quot; transform=&amp;amp;quot;rotate(270,12,80)&amp;amp;quot;&amp;amp;gt;&#039;&amp;amp;lt;L1&amp;amp;gt;&#039;&amp;amp;lt;/text&amp;amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
you can safely ignore it. This is due to the fact, that you are using placeholders in the .gplot definition (which is good, because it favors reuseability) but have not yet defined the corresponding attributes. While annoying, this is not your fault: you can only define attributes once you have a weblink. So click on create weblink and define the attributes you have been using placeholders for. The error message should go away.&lt;br /&gt;
&lt;br /&gt;
The attributes which are generally needed are:&lt;br /&gt;
&lt;br /&gt;
* label: should be defined like &amp;quot;Label 1&amp;quot;::&amp;quot;Label 2&amp;quot;. Do not omit double quotes and use them individually for each label. Separator is a double (!) colon. If you ever manage to do away with the double quotes on the axes, please let us all know&lt;br /&gt;
* title: Can be as simple as &amp;quot;Some Title&amp;quot; or as complicated as &amp;quot;Temperature $data{currval1} ($data{min1}-$data{max1}), Humidity $data{currval2} ($data{min2}-$data{max2}) @ $data{currdate1}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= SVG Programs =&lt;br /&gt;
The SVG programs can be found in the 98_SVG.pm module. Look for example for the string &amp;quot;histeps&amp;quot;. Feel free to adapt and improve. If you ever program a wind rose to plot wind directions, please let me know. &lt;br /&gt;
&lt;br /&gt;
= Details =&lt;br /&gt;
What you also should know:&lt;br /&gt;
&lt;br /&gt;
* All data used in a plot come from one (!) file. It is currently not possible to mix data from several files. So make sure that the regular expression of the FileLog object catches everything which you need in one plot&lt;br /&gt;
* While it first seems evident that FileLog objects are associated with a given device, this must be mitigated. Imagine that you want to plot the state (and changes) of some socket adaptors (ZwischenStecker) over time. You then need to gather all the data (from several devices) in one file. So instead of define FileLog_ZwSt_1 FileLog /opt/fhem/var/log/ZwSt_1_%Y.log ZwSt_1 you need to specify define FL_ZwSt_ALL FileLog /opt/fhem/var/log/ZwSt_ALL_%Y.log ZwSt_.*deviceMsg.*BidCoS_RF.*&lt;br /&gt;
* Be careful when specifying the regular expression which filters the lines for a given logfile. While often it is sufficient to not specify a specific one at all, consider the following case from the Homematic world, where one action results in 4 lines of FHEM output. The switch communicates not only with the CCU, but also with the remote control, issuing 2 lines for each action:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;2012-01-01_07:40:23 ZwSt_3 deviceMsg: on (to Dev.WDisp.Kueche)&lt;br /&gt;
 2012-01-01_07:40:23 ZwSt_3 on&lt;br /&gt;
 2012-01-01_07:40:26 ZwSt_3 deviceMsg: on (to BidCoS_RF)&lt;br /&gt;
 2012-01-01_07:40:26 ZwSt_3 on&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Why one needs to specify a logtype (which is nothing else than a plot definition) for the FileLog has always been a mystery to me. It holds no useful information to the object itself and does not influence the way data is written to the associated logfile. Sure, plots need FileLogs, but not the other way round. And since the WebLink contains (again) the name of the plot definition file, the need to define the logtype attribute seems odd. The master himself says regarding this topic: &amp;quot;Ist eine Eigenschaft, die beschreibt, auf welche Art die Daten angezeigt werden koennen. Steht damit direkt neben den Daten, also da wo ich zuerst suchen wuerde. Ist nicht notwendig, aber so kann FHEMWEB ein &#039;create weblink&#039; anbieten.&amp;quot; I have to admit that this link is useful and I use to use it :-)&lt;br /&gt;
* If you meet on your way PERL-code snippets in the .gplot files, you can just ignore them safely. They are only used in the gnuplot world, not in SVG anymore. Now you may ask, where you find the corresponding features in SVG? They are hidden in functions defined in the FileLog &amp;quot;get&amp;quot; primitive.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
Documentation can be found in several places, it is not complete and you need to piece it together:&lt;br /&gt;
&lt;br /&gt;
* [http://fhem.de/HOWTO.html#plotting http://fhem.de/HOWTO.html#plotting]&lt;br /&gt;
* [http://fhem.de/commandref.html#FileLogget http://fhem.de/commandref.html#FileLogget]&lt;br /&gt;
* [http://fhem.de/commandref.html#label http://fhem.de/commandref.html#label]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Creating_Plots&amp;diff=28903</id>
		<title>Creating Plots</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Creating_Plots&amp;diff=28903"/>
		<updated>2019-01-01T20:09:26Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: /* Data Extraction */ Typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Randnotiz|RNTyp=[g|Info]|RNText=Hier wird das Anlegen per Hand beschrieben, was für Ungeübte umständlich und nicht empfehlenswert ist. &lt;br /&gt;
Mit &amp;quot;Create SVG Plot&amp;quot; in der FileLog-Detail-Ansicht steht inzwischen zur Vereinfachung ein Konfigurations-Frontend zur Verfügung: [[Plots_erzeugen|.gplot-Editor]].}} &lt;br /&gt;
= Howto create a PGM2/SVG plot - Introduction =&lt;br /&gt;
Output using the PGM2 engine is generated through .gplot files. The name is historical and today files can be generated using gnuplot or SVG graphics. This howto lists the most important aspects of generating a SVG configuration file.&lt;br /&gt;
&lt;br /&gt;
Each graphic generated by FHEM is described by one configuration file. It is currently not possible to generate one page with several graphics from one configuration file. &lt;br /&gt;
&lt;br /&gt;
Taking a high level view for each plot the following is needed:&lt;br /&gt;
&lt;br /&gt;
* Data from a logfile (create it using the FileLog facility)&lt;br /&gt;
* Plot configuration (.gplot) file knowing about the internal structure of the logfile&lt;br /&gt;
* Association between the FileLog and the plot configuration (using the &amp;quot;logtype&amp;quot; attribute in the FileLog and the LINK in the WebLink object, also see comments below)&lt;br /&gt;
* Weblink representing the plot itself&lt;br /&gt;
= FileLog objects =&lt;br /&gt;
Digging into the more murky details, first thing is the creation of the FileLog object:&lt;br /&gt;
&lt;br /&gt;
* The FileLog object is always associated with a physical device (but see comments below)&lt;br /&gt;
* The creation of a FileLog object together with the corresponding logfile is automatic if the &amp;quot;autocreate&amp;quot; attribute is set in FHEM (it is set by default)&lt;br /&gt;
* Manual creation is also possible and requires a statement like:&lt;br /&gt;
  &amp;lt;nowiki&amp;gt;&lt;br /&gt;
define FL_KS550 FileLog /var/log/fhem/KS550_%Y.log KS550:T:.*&lt;br /&gt;
define FileLog_ZwSt_1 FileLog /opt/fhem/var/log/ZwSt_1_%Y.log ZwSt_1&lt;br /&gt;
define FL_ZwSt_ALL FileLog /opt/fhem/var/log/ZwSt_ALL_%Y.log ZwSt_.*deviceMsg.*BidCoS_RF.* &lt;br /&gt;
 &amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Be it manual or automatic: the definition of a FileLog object determines (through the regular expression) which of the output lines of FHEM end up in the logfile&lt;br /&gt;
&lt;br /&gt;
= Plot definition =&lt;br /&gt;
Once the logfile is accumulating data, the plot configuration itself is needed. There is no object for this, but plain .gplot files in the share/FHEM directory are used by the system. A good start is to copy an existing one and modify it.&lt;br /&gt;
&lt;br /&gt;
On a side note: if you create your own files instead of using the ones already delivered with FHEM, stick to the convention of prepending them with a &amp;quot;my&amp;quot;. Files of pattern &amp;quot;my*&amp;quot; are guaranteed not to be overwritten during FHEM updates (or so Rudi promised me).&lt;br /&gt;
&lt;br /&gt;
The following entries are recognized in a SVG context:&lt;br /&gt;
&lt;br /&gt;
* #FileLog holds the information which data need to be extracted from the logfile. See below for details.&lt;br /&gt;
* Set commands: title, ylabel, y2label, yrange, y2range, ytics, y2tics, teminal (only &amp;quot;size&amp;quot; parameter is recognized)&lt;br /&gt;
* Plot command: see below for details&lt;br /&gt;
== Placeholders ==&lt;br /&gt;
It is possible to use placeholders in the .gplot files, which will then be replaced by information provided by the actual WebLink attributes listed below. This has the advantage that you can define one .gplot file and re-use it for several devices, changing size, title and lables accordingly instead of maintaining several separated files.&lt;br /&gt;
&lt;br /&gt;
* &amp;amp;lt;OUT&amp;amp;gt; : only relevant for gnuplot&lt;br /&gt;
* &amp;amp;lt;SIZE&amp;amp;gt;: attr plotsize&lt;br /&gt;
* &amp;amp;lt;TL&amp;amp;gt;  : attr title. The attribute is eval&#039;ed by perl at runtime, be careful and protect by double quotes if you just want to enter strings. This gives access to all internal FHEM values, though admittedly not straightforward&lt;br /&gt;
* &amp;amp;lt;Ln&amp;amp;gt;  : attr label. Lables 1-#n can be specified by a double-colon-separated (::) list, see below. This is also eval&#039;ed at runtime, same precautions apply&lt;br /&gt;
* &amp;amp;lt;IN&amp;amp;gt;  : &lt;br /&gt;
&lt;br /&gt;
In general this is good practice and you should especially consider it if you plan to distribute your .gplot files. Using placeholders f.ex. for the title and all the labels and curve descriptors gives other users the possibility to change them without having to touch the .gplot code.&lt;br /&gt;
&lt;br /&gt;
== Data Extraction ==&lt;br /&gt;
The central piece of the plotfile is the #FileLog line (yes, it must be prepended by a hash!), which is a special command und internally triggers the use of the FileLog &amp;quot;get&amp;quot; function, which extracts data from the logfile. The general syntax is: &amp;lt;nowiki&amp;gt;&amp;amp;lt;col&amp;amp;gt;:&amp;amp;lt;regexp&amp;amp;gt;:&amp;amp;lt;default&amp;amp;gt;:&amp;amp;lt;fn&amp;amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
. &lt;br /&gt;
* col: selects the column of the line (columns are white space separated, numbering starts at 1)&lt;br /&gt;
* regexp: validates/selects the line&lt;br /&gt;
* default: default value, if none is present&lt;br /&gt;
* fn: function which operates on values, pre-defined or eval&#039;ed, see below&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;get&amp;quot; function will set the following&amp;amp;#160;%data values (which can e.g. be used in titles, labels, ...) for each requested column (curve), beggining with &amp;amp;lt;x&amp;amp;gt; = 1:&lt;br /&gt;
&lt;br /&gt;
* min&amp;amp;lt;x&amp;amp;gt;, max&amp;amp;lt;x&amp;amp;gt;&lt;br /&gt;
* mindate&amp;amp;lt;x&amp;amp;gt;, maxdate&amp;amp;lt;x&amp;amp;gt;&lt;br /&gt;
* avg&amp;amp;lt;x&amp;amp;gt;, cnt&amp;amp;lt;x&amp;amp;gt;&lt;br /&gt;
* sum&amp;amp;lt;x&amp;amp;gt;&lt;br /&gt;
* currval&amp;amp;lt;x&amp;amp;gt; (last value)&lt;br /&gt;
* currdate&amp;amp;lt;x&amp;amp;gt; (last date)&lt;br /&gt;
So you can do something like &amp;lt;nowiki&amp;gt;attr &amp;amp;lt;weblink&amp;amp;gt; title &amp;amp;quot;Min $data{min1}, Max $data{max1}, Last $data{currval1}&amp;amp;quot;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Also implemented in this function is code which operates on the data retrieved. This can be specified at the &amp;quot;&amp;amp;lt;fn&amp;amp;gt;&amp;quot; tag. Up till now following functions are impemented:&lt;br /&gt;
&lt;br /&gt;
* int (to cut off % from a number, as for the actuator)&lt;br /&gt;
* delta-h / delta-d to get rain/h and rain/d values from continuous data&lt;br /&gt;
* And then there is this: the string is evaluated as a perl expression. @fld is the current line splitted by spaces (0-based). So you can do something like $fld[3]/1000 to plot values divided by 1000 or $fld[3]=~&amp;quot;on&amp;quot;?0.9:0.8 to map the 4th field which contains an on/off information into numerical values to be plotted in a graph. Be warned though: this string/perl expression cannot (!) contain any spaces.&lt;br /&gt;
&lt;br /&gt;
For even more details see [http://fhem.de/commandref.html#FileLogger http://fhem.de/commandref.html#FileLogget] or the module 92_FileLog.pm.&lt;br /&gt;
&lt;br /&gt;
== Debugging Data Extraction ==&lt;br /&gt;
If you do not get the result you are expecting or, worse, no data at all, you may use the debug facility of FHEM to see what the get-command extracts from the logfile. Use telnet to contact FHEM and then use the arguments detailed below ending with the #FileLog argument you are using in the .gplot file:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;telnet diskstation 7072&lt;br /&gt;
get FileLog_KS550&amp;amp;#160;?&lt;br /&gt;
get FileLog_KS550 - - 2012-01-01 2012-12-31 4::&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
You should get back the data which you have been asking for, followed by a line holding the .gplot argument. Make sure&lt;br /&gt;
&lt;br /&gt;
* you do not select too much data, this will possibly upset your NAS :-)&lt;br /&gt;
* you do select data which really are in the file (beware of year/month changes)&lt;br /&gt;
== Plot Commands ==&lt;br /&gt;
Once you have extracted the data from the logfile, you need to plot it. There is a plot command which does just that. It has several arguments which you can use:&lt;br /&gt;
&lt;br /&gt;
* axes: not needed by default, but if you want to plot curves which use different y axes, then you must tell the plot command, which y-axis the data should be bound to: &amp;quot;axes x1y1&amp;quot; selects the left, &amp;quot;axes x1y2&amp;quot; the right one&lt;br /&gt;
* title: defines the string which is printed in the colour of the curve into the plot. You can (and maybe should) use placeholders like &amp;quot;&amp;amp;lt;Lx&amp;amp;gt;&amp;quot;, x being a number&lt;br /&gt;
* with: defines how to draw the data. only points, steps, histeps and lines (which acts as a catch all) are currently implemented&lt;br /&gt;
* ls: uses CSS definitions, still need to figure out, how this works&lt;br /&gt;
* lw: defines the width of a line&lt;br /&gt;
== Example ==&lt;br /&gt;
A very barebones but functional example of a file using placeholders could be:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;set terminal size &amp;amp;lt;SIZE&amp;amp;gt;&lt;br /&gt;
set title &#039;&amp;amp;lt;TL&amp;amp;gt;&#039;&lt;br /&gt;
set ylabel &#039;&amp;amp;lt;L1&amp;amp;gt;&#039;&lt;br /&gt;
set y2label &#039;&amp;amp;lt;L2&amp;amp;gt;&#039;&lt;br /&gt;
#FileLog 4:::&lt;br /&gt;
plot \&lt;br /&gt;
   axes x1y1 title &#039;&amp;amp;lt;L3&amp;amp;gt;&#039; with steps lw 2&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
It implements the placeholders which can be defined by the user through the WebLink attributes later, selects just one column, without regular expression matches, defaults or subsequent data operations and plot is as a steps diagram. In fact even the &amp;quot;axes x1y1&amp;quot; statement could be left out, it would still work.&lt;br /&gt;
&lt;br /&gt;
== Changing text style ==&lt;br /&gt;
If you need a text style that is different from the style definition in fhemweb:&lt;br /&gt;
Add&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;text { font-family:Arial, Helvetica, sans-serif; font-size:12px; fill:#xxxxxx;}&lt;br /&gt;
text.title {font-family:Arial, Helvetica, sans-serif; font-size:16px; fill:#xxxxxx;}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where #xxxxxx is the color.&lt;br /&gt;
&lt;br /&gt;
== Transparent plots ==&lt;br /&gt;
If you need transparent plots, for example in FLOORPLAN, you have to change the following definitions in svg_style.css&lt;br /&gt;
&lt;br /&gt;
Change&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;.background { fill:#FFFFE7; }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
to:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;.background { fill:#FFFFE7;fill-opacity: 0; }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Change:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;.border { stroke:black; fill:url(#gr_bg); }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
to&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;.border { stroke:black; fill:url(#gr_bg);fill-opacity: 0; }&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= WebLink objects =&lt;br /&gt;
Once you have created the FileLog object and written the plot specification, there is not much to be done. Click on the reference to the .gplot file in the FileLog section of a device, then click on the link for WebLink creation and then add the attributes you want to have. Put it into a suitable room and you are done.&lt;br /&gt;
&lt;br /&gt;
If you are using placeholders in your .gplot files and after defining your .gplot file you click onto a FileLog &amp;quot;active&amp;quot; link to create the plot itself and get a message like:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;XML Parsing Error: mismatched tag. Expected: &amp;amp;lt;/L1&amp;amp;gt;.&lt;br /&gt;
...&lt;br /&gt;
Line Number 51, Column 95:&amp;amp;lt;text x=&amp;amp;quot;12&amp;amp;quot; y=&amp;amp;quot;80&amp;amp;quot; text-anchor=&amp;amp;quot;middle&amp;amp;quot; class=&amp;amp;quot;ylabel&amp;amp;quot; transform=&amp;amp;quot;rotate(270,12,80)&amp;amp;quot;&amp;amp;gt;&#039;&amp;amp;lt;L1&amp;amp;gt;&#039;&amp;amp;lt;/text&amp;amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
you can safely ignore it. This is due to the fact, that you are using placeholders in the .gplot definition (which is good, because it favors reuseability) but have not yet defined the corresponding attributes. While annoying, this is not your fault: you can only define attributes once you have a weblink. So click on create weblink and define the attributes you have been using placeholders for. The error message should go away.&lt;br /&gt;
&lt;br /&gt;
The attributes which are generally needed are:&lt;br /&gt;
&lt;br /&gt;
* label: should be defined like &amp;quot;Label 1&amp;quot;::&amp;quot;Label 2&amp;quot;. Do not omit double quotes and use them individually for each label. Separator is a double (!) colon. If you ever manage to do away with the double quotes on the axes, please let us all know&lt;br /&gt;
* title: Can be as simple as &amp;quot;Some Title&amp;quot; or as complicated as &amp;quot;Temperature $data{currval1} ($data{min1}-$data{max1}), Humidity $data{currval2} ($data{min2}-$data{max2}) @ $data{currdate1}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= SVG Programs =&lt;br /&gt;
The SVG programs can be found in the 98_SVG.pm module. Look for example for the string &amp;quot;histeps&amp;quot;. Feel free to adapt and improve. If you ever program a wind rose to plot wind directions, please let me know. &lt;br /&gt;
&lt;br /&gt;
= Details =&lt;br /&gt;
What you also should know:&lt;br /&gt;
&lt;br /&gt;
* All data used in a plot come from one (!) file. It is currently not possible to mix data from several files. So make sure that the regular expression of the FileLog object catches everything which you need in one plot&lt;br /&gt;
* While it first seems evident that FileLog objects are associated with a given device, this must be mitigated. Imagine that you want to plot the state (and changes) of some socket adaptors (ZwischenStecker) over time. You then need to gather all the data (from several devices) in one file. So instead of define FileLog_ZwSt_1 FileLog /opt/fhem/var/log/ZwSt_1_%Y.log ZwSt_1 you need to specify define FL_ZwSt_ALL FileLog /opt/fhem/var/log/ZwSt_ALL_%Y.log ZwSt_.*deviceMsg.*BidCoS_RF.*&lt;br /&gt;
* Be careful when specifying the regular expression which filters the lines for a given logfile. While often it is sufficient to not specify a specific one at all, consider the following case from the Homematic world, where one action results in 4 lines of FHEM output. The switch communicates not only with the CCU, but also with the remote control, issuing 2 lines for each action:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;2012-01-01_07:40:23 ZwSt_3 deviceMsg: on (to Dev.WDisp.Kueche)&lt;br /&gt;
 2012-01-01_07:40:23 ZwSt_3 on&lt;br /&gt;
 2012-01-01_07:40:26 ZwSt_3 deviceMsg: on (to BidCoS_RF)&lt;br /&gt;
 2012-01-01_07:40:26 ZwSt_3 on&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
* Why one needs to specify a logtype (which is nothing else than a plot definition) for the FileLog has always been a mystery to me. It holds no useful information to the object itself and does not influence the way data is written to the associated logfile. Sure, plots need FileLogs, but not the other way round. And since the WebLink contains (again) the name of the plot definition file, the need to define the logtype attribute seems odd. The master himself says regarding this topic: &amp;quot;Ist eine Eigenschaft, die beschreibt, auf welche Art die Daten angezeigt werden koennen. Steht damit direkt neben den Daten, also da wo ich zuerst suchen wuerde. Ist nicht notwendig, aber so kann FHEMWEB ein &#039;create weblink&#039; anbieten.&amp;quot; I have to admit that this link is useful and I use to use it :-)&lt;br /&gt;
* If you meet on your way PERL-code snippets in the .gplot files, you can just ignore them safely. They are only used in the gnuplot world, not in SVG anymore. Now you may ask, where you find the corresponding features in SVG? They are hidden in functions defined in the FileLog &amp;quot;get&amp;quot; primitive.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
Documentation can be found in several places, it is not complete and you need to piece it together:&lt;br /&gt;
&lt;br /&gt;
* [http://fhem.de/HOWTO.html#plotting http://fhem.de/HOWTO.html#plotting]&lt;br /&gt;
* [http://fhem.de/commandref.html#FileLogget http://fhem.de/commandref.html#FileLogget]&lt;br /&gt;
* [http://fhem.de/commandref.html#label http://fhem.de/commandref.html#label]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=EnergyCam&amp;diff=27492</id>
		<title>EnergyCam</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=EnergyCam&amp;diff=27492"/>
		<updated>2018-07-17T15:00:05Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: /* Links */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Hardware&lt;br /&gt;
|Bild=EnergyCam.jpg&lt;br /&gt;
|Bildbeschreibung=EnergyCam mit externer Batterie und externer Antenne montiert auf einem Ferraris-Zähler&lt;br /&gt;
|HWProtocol=Wireless M-Bus &lt;br /&gt;
|HWType=Sensor&lt;br /&gt;
|HWCategory=Energieverbrauchsmessung&lt;br /&gt;
|HWComm=Funk 868MHz, ModBus&lt;br /&gt;
|HWChannels=N/A&lt;br /&gt;
|HWVoltage=3,0 - 3,6V&lt;br /&gt;
|HWPowerConsumption=&amp;lt;0,2W&lt;br /&gt;
|HWPoweredBy=interne CR2450 oder externe Batterie, USB&lt;br /&gt;
|HWSize=B x H x T 48,00 x 55,50 x 15,50 mm&lt;br /&gt;
|HWDeviceFHEM=WMBUS&lt;br /&gt;
|HWManufacturer=Q-loud&lt;br /&gt;
}}&lt;br /&gt;
Die [[EnergyCam]] ist ein Zähleraufsatz der den Zählerstand erfasst und dann drahtlos (Wireless M-Bus) oder drahtgebunden (Modbus) weiterleitet.&lt;br /&gt;
== Features ==&lt;br /&gt;
Eine EnergyCam erfasst optisch den Zählerstand eines herkömmlichen Zählers für Elektrizität, Gas oder Wasser und wandelt diesen per optischer Zeichenerkennung (OCR) in einen Zahlenwert um. Dieser Wert wird dann zyklisch versandt und kann vom Empfänger ausgewertet werden.&lt;br /&gt;
&lt;br /&gt;
Die EnergyCam wird dazu auf den Zähler aufgeklebt. Das Gerät unterstützt dabei durch eine Anzeige die Montage in der richtigen Position. Für die Verwendung mit Gas- und Wasserzählern sind noch zusätzliche Adapter erforderlich.&lt;br /&gt;
Es gibt die EnergyCam sowohl mit interner als auch externer Antenne sowie mit interner und externer Energieversorgung.&lt;br /&gt;
Der aktuelle Zählerstand kann bei Bedarf auch direkt am Gerät abgelesen werden und wird auf dem internen Display dargestellt. &lt;br /&gt;
&lt;br /&gt;
== Hinweise zum Betrieb mit FHEM ==&lt;br /&gt;
Die EnergyCam im Wireless M-Bus Modus wird vom Modul [[WMBUS]] vollständig unterstützt. Das Herstellerkürzel ist FFD.&lt;br /&gt;
&lt;br /&gt;
== Bekannte Probleme ==&lt;br /&gt;
Die Erfassung der Zählerstands erfolgt von schräg unterhalb des eigentlichen Zählwerks. Daher darf dieser Bereich nicht durch Aufdruck oder ähnliches die freie Sicht auf das Zählwerk behindern, sonst ist keine fehlerfreie Erfassung möglich.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Herstellerseite [https://iot.q-loud.de/energycam-automatische-energiedatenerfassung]&lt;br /&gt;
* Dokumentation und Software [http://www.fastforward.ag/#Downloads]&lt;br /&gt;
[[Kategorie:Energieverbrauchsmessung]]&lt;br /&gt;
[[Kategorie:Other Components]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=EnergyCam&amp;diff=27491</id>
		<title>EnergyCam</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=EnergyCam&amp;diff=27491"/>
		<updated>2018-07-17T14:22:24Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: /* Links */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Hardware&lt;br /&gt;
|Bild=EnergyCam.jpg&lt;br /&gt;
|Bildbeschreibung=EnergyCam mit externer Batterie und externer Antenne montiert auf einem Ferraris-Zähler&lt;br /&gt;
|HWProtocol=Wireless M-Bus &lt;br /&gt;
|HWType=Sensor&lt;br /&gt;
|HWCategory=Energieverbrauchsmessung&lt;br /&gt;
|HWComm=Funk 868MHz, ModBus&lt;br /&gt;
|HWChannels=N/A&lt;br /&gt;
|HWVoltage=3,0 - 3,6V&lt;br /&gt;
|HWPowerConsumption=&amp;lt;0,2W&lt;br /&gt;
|HWPoweredBy=interne CR2450 oder externe Batterie, USB&lt;br /&gt;
|HWSize=B x H x T 48,00 x 55,50 x 15,50 mm&lt;br /&gt;
|HWDeviceFHEM=WMBUS&lt;br /&gt;
|HWManufacturer=Q-loud&lt;br /&gt;
}}&lt;br /&gt;
Die [[EnergyCam]] ist ein Zähleraufsatz der den Zählerstand erfasst und dann drahtlos (Wireless M-Bus) oder drahtgebunden (Modbus) weiterleitet.&lt;br /&gt;
== Features ==&lt;br /&gt;
Eine EnergyCam erfasst optisch den Zählerstand eines herkömmlichen Zählers für Elektrizität, Gas oder Wasser und wandelt diesen per optischer Zeichenerkennung (OCR) in einen Zahlenwert um. Dieser Wert wird dann zyklisch versandt und kann vom Empfänger ausgewertet werden.&lt;br /&gt;
&lt;br /&gt;
Die EnergyCam wird dazu auf den Zähler aufgeklebt. Das Gerät unterstützt dabei durch eine Anzeige die Montage in der richtigen Position. Für die Verwendung mit Gas- und Wasserzählern sind noch zusätzliche Adapter erforderlich.&lt;br /&gt;
Es gibt die EnergyCam sowohl mit interner als auch externer Antenne sowie mit interner und externer Energieversorgung.&lt;br /&gt;
Der aktuelle Zählerstand kann bei Bedarf auch direkt am Gerät abgelesen werden und wird auf dem internen Display dargestellt. &lt;br /&gt;
&lt;br /&gt;
== Hinweise zum Betrieb mit FHEM ==&lt;br /&gt;
Die EnergyCam im Wireless M-Bus Modus wird vom Modul [[WMBUS]] vollständig unterstützt. Das Herstellerkürzel ist FFD.&lt;br /&gt;
&lt;br /&gt;
== Bekannte Probleme ==&lt;br /&gt;
Die Erfassung der Zählerstands erfolgt von schräg unterhalb des eigentlichen Zählwerks. Daher darf dieser Bereich nicht durch Aufdruck oder ähnliches die freie Sicht auf das Zählwerk behindern, sonst ist keine fehlerfreie Erfassung möglich.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Herstellerseite [https://iot.q-loud.de/energycam-automatische-energiedatenerfassung]&lt;br /&gt;
[[Kategorie:Energieverbrauchsmessung]]&lt;br /&gt;
[[Kategorie:Other Components]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Rfmode&amp;diff=27292</id>
		<title>Rfmode</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Rfmode&amp;diff=27292"/>
		<updated>2018-07-02T20:44:37Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: WMBus_C&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[CUL]], [[CUN]](O) und {{Link2CmdRef|Lang=de|Anker=STACKABLE_CC|Label=STACKABLE_CC}} können (je nach Firmware) in verschiedenen [[rfmode]]s betrieben werden (vgl. {{Link2CmdRef|Lang=de|Anker=rfmode}}):&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;[[SlowRF]]&amp;quot; -- Für die Kommunikation mit FS20/FHT/HMS/EM1010/S300/Hoermann Geräten @1 kHz Datenrate (Standardeinstellung).&lt;br /&gt;
* &amp;quot;[[HomeMatic]]&amp;quot; -- Für die Kommunikation mit HomeMatic Geräten @10 kHz Datenrate.&lt;br /&gt;
* &amp;quot;[[MAX]]&amp;quot; -- Für die Kommunikation mit MAX! Geräten @10 kHz Datenrate.&lt;br /&gt;
* &amp;quot;[[WMBUS|WMBus_S]]&amp;quot;, &amp;quot;[[WMBUS|WMBus_T]]&amp;quot; und &amp;quot;[[WMBUS|WMBus_C]]&amp;quot; -- Für die Kommunikation mit Wireless M-Bus Geräten wie Wasser-, Gas- oder Elektrozählern. (vgl. Wireless_M-Bus  {{Link2CmdRef|Lang=de|Anker=WMBUS}})&lt;br /&gt;
&lt;br /&gt;
Die Protokolle können nicht zugleich genutzt werden - ein Sende/Empfangsgerät kann also immer nur für einen rfmode genutzt werden. Möchte man mehrere rfmodes bedienen, so braucht man entsprechend viele Sende/Empfangsgeräte.&lt;br /&gt;
&lt;br /&gt;
Technisch wäre es prinzipiell möglich vor jedem Senden den rfmode zu wechseln, jedoch könnten die jeweils anderen Protokolle nicht mehr empfangen werden. Da die Datenübertragung und die Sendehäufigkeit bei diesen Protokollen ziemlich langsam ist, würde man beim ständigen Wechsel der rfmodes zuviele Daten verlieren - selbst bei sehr wenigen Geräten völlig unpraktikabel. &lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [[Kommunikationsprobleme mit FHT]]&lt;br /&gt;
* [[Was ist der Hauscode?]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Glossary]]&lt;br /&gt;
[[Kategorie:CUL]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=HomeMatic_Fenster-Drehgriffkontakt_Community-Nachbau&amp;diff=27280</id>
		<title>HomeMatic Fenster-Drehgriffkontakt Community-Nachbau</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=HomeMatic_Fenster-Drehgriffkontakt_Community-Nachbau&amp;diff=27280"/>
		<updated>2018-06-27T19:08:58Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: Abschnitt Montage&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Der HB-Sec-RHS Funk-Fenster-Drehgriffkontakt ist ein Selbstbau threeStateSensor zur&lt;br /&gt;
Überwachung eines Fenster-Drehgriffs.&lt;br /&gt;
&lt;br /&gt;
Die Firmware ist identisch mit dem [https://www.elv.de/homematic-funk-fenster-drehgriffkontakt-1.html Originalen Sensor von ELV] und verhält sich dementsprechend auch gleich.&lt;br /&gt;
&lt;br /&gt;
== Übersicht ==&lt;br /&gt;
&lt;br /&gt;
Die Grundidee zu diesem Sensor wurde durch {{Link2Forum|Topic=71413.0|LinkText=Kawaci im Forum}} geliefert.&lt;br /&gt;
Die Umsetzung besteht aus einer Atmega328p Platine mit CC1101 Funkmodul (868 MHz) sowie&lt;br /&gt;
einer auf der [https://github.com/pa-pa/AskSinPP AskSin++] Portierung des Homematik Protokolls.&lt;br /&gt;
&lt;br /&gt;
Anfangs gab es zwei Ideen wie der Sensor aussehen sollte. Inzwischen hat sich die HomeMatic Variante mit CR2032 Batteriehalterung auf der Platine durchgesetzt. Somit wird hier nicht näher auf andere Versionen (zwei Platinen zur Erfassung der Fensterstellung) eingegangen.&lt;br /&gt;
&lt;br /&gt;
== Platine ==&lt;br /&gt;
&#039;&#039;&#039;Schaltplan:&#039;&#039;&#039;&lt;br /&gt;
[[Datei:FDGK_v1.0_sch.jpg]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Platine v1.0 (Oberseite mit korrigierter Pinbelegung):&#039;&#039;&#039;&lt;br /&gt;
[[Datei:FDGK_v1.0_top.jpg]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Platine v1.0 (Unterseite, ohne bestücktes Radio):&#039;&#039;&#039;&lt;br /&gt;
[[Datei:FDGK_v1.0_bot.jpg]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Bauteilliste ==&lt;br /&gt;
Die Bauteilliste gibt es auf [https://github.com/pa-pa/HMSensor/blob/master/HMSensor-CR2032/Parts.xls GitHub].&lt;br /&gt;
&lt;br /&gt;
In der Liste sind die Magnete und Reed-Kontakte nicht aufgeführt.&lt;br /&gt;
Folgende können verwendet werden:&lt;br /&gt;
* Reed-Kontakt 2x14mm [https://de.aliexpress.com/item/10pcs-N-O-Reed-switch-Magnetic-Switch-2-14mm-Normally-Open-Magnetic-Induction-switch/32803902404.html Aliexpress]&lt;br /&gt;
* Neodym Magnet 4x2mm [https://de.aliexpress.com/item/32873144013/32873144013.html Aliexpress]&lt;br /&gt;
&lt;br /&gt;
== Zusammenlöten der SMD Bauteile ==&lt;br /&gt;
Die Bestückung der Platine ist im [https://forum.fhem.de/index.php/topic,71413.msg640858.html#msg640858 diesem Post] kurz beschrieben.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Bemerkung:&#039;&#039;&#039;&lt;br /&gt;
Y1 (32 kHz Quarz), C4 und C5 sind nicht erforderlich.&lt;br /&gt;
Vor dem Verlöten der Bauteile sollte kontrolliert werden, ob die Platinen in das Gehäuse passen. Falls nicht, sollte entweder das Gehäuse oder die Platine passend gefeilt werden.&lt;br /&gt;
&lt;br /&gt;
Zuerst auf der Unterseite IC1 bestücken:&lt;br /&gt;
Hierzu einen beliebigen äußeren Pin verzinnen, den Prozessor mit der richtigen Orientierung von Pin 1 (runder Punkt) platzieren und den Pin verlöten.&lt;br /&gt;
Darauf achten, dass der Prozessor mittig auf den Pads aufliegt, ggf. den Pin wieder erhitzen&lt;br /&gt;
und den IC drehen oder verschieben. Auf der gegenüberliegenden Seite ebenfalls einen Pin verlöten, damit der IC fixiert ist.&lt;br /&gt;
Mit einem Flussmittelstift auf allen vier Seiten die Pins bestreichen und auf jeder Seite die Pins einzeln mit einer feinen Lötspitze bzw. feinem Lötzinn verlöten. Kurzschlüsse zwischen einzelnen Pins müssen unbedingt vermieden werden.&lt;br /&gt;
&lt;br /&gt;
Danach auf der Unterseite C1, C2, C3 sowie R1 bestücken.&lt;br /&gt;
Auf der Oberseite R2, D1 (rot), R3, D2 (gelb), C6 und die beiden Taster bestücken.&lt;br /&gt;
&lt;br /&gt;
Nach dem [https://wiki.fhem.de/wiki/HomeMatic_Fenster-Drehgriffkontakt_Community-Nachbau#Firmware Flashen der Firmware] das Radio (IC2) bzw. den Batteriehalter (BT1) bestücken.&lt;br /&gt;
Als Antenne (ANT) wird ein Draht mit 72 mm Länge eingelötet.&lt;br /&gt;
&lt;br /&gt;
== Firmware ==&lt;br /&gt;
&lt;br /&gt;
=== Bootloader ===&lt;br /&gt;
&lt;br /&gt;
Die Sensorfirmware kann OTA (Over The Air) oder über den Arduino Bootloader geladen werden.&lt;br /&gt;
&lt;br /&gt;
=== Erstellen des OTA (Over The Air) Bootloaders ===&lt;br /&gt;
{{Randnotiz|RNText=Firmware für &#039;ID=0030&#039;}}&lt;br /&gt;
Dafür wird, mit Hilfe der [https://forum.fhem.de/index.php?action=dlattach;topic=71413.0;attach=91780 makeota.html] der Bootloader mit den benötigten Daten gefüllt und anschließend generiert.&lt;br /&gt;
&lt;br /&gt;
Die makeota.html wird dazu in einem beliebigen Browser aufgerufen.&lt;br /&gt;
&lt;br /&gt;
Die Felder &#039;&#039;HM ID&#039;&#039; und &#039;&#039;HM-Serial&#039;&#039; innerhalb der makeota.html können jeweils frei gewählt werden (dabei die Vorgaben beachten, so z.B. &#039;&#039;HM ID&#039;&#039;: 6 hexadezimale Zeichen). Das Feld &#039;&#039;Device Type&#039;&#039; muss folgende Nummer beinhalten: &amp;quot;0030&amp;quot;. Das Feld &#039;&#039;Config String&#039;&#039; wird aus den eingegebenen Daten automatisch generiert.&lt;br /&gt;
&lt;br /&gt;
Die zwei o.g. Felder müssen sich von Gerät zu Gerät unterscheiden. Aus diesem Grund ist es sinnvoll, sich die eingegebenen Daten aufzuschreiben oder Screenshots zu erstellen.&lt;br /&gt;
&lt;br /&gt;
Nun muss noch dem Bootloader bekannt gemacht werden, welche Batterien mit dem FDGK verwendet werden. Dies wird über die dropdown Liste &amp;quot;Power Presets&amp;quot; ausgewählt:&lt;br /&gt;
&lt;br /&gt;
Dabei bedeutet:&lt;br /&gt;
&lt;br /&gt;
*No StepUp = CR2032 Batterie&lt;br /&gt;
*StepUp single AA = eine AA Batterie und StepUp&lt;br /&gt;
*StepUp two AAA = zwei AAA Batterien und StepUp&lt;br /&gt;
&lt;br /&gt;
Die Parameter „Step-Up Present“, „Low-Voltage“ und „Critical Voltage” ergeben sich aus der Wahl in der DropDown Liste, können aber individuell angepasst werden. Für den fehlerfreien Betrieb sollten diese aber unverändert bleiben!&lt;br /&gt;
&lt;br /&gt;
Seit 12/2017 kann optional die [https://forum.fhem.de/index.php?action=dlattach;topic=71413.0;attach=91779 aktuelle Firmware] mit angegeben werden, so dass die Firmware gleichzeitig mit dem Bootloader geflasht werden kann. In diesem Fall kann der FDGK sofort in Betrieb genommen werden und nur es wird nur eine aktualisierte Firmware per OTA (Over The Air) geflasht.&lt;br /&gt;
&lt;br /&gt;
Nach drücken der Taste &amp;quot;Create&amp;quot; erscheint eine Schaltfläche &amp;quot;Save Bootloader&amp;quot;, mit welcher der angepasste Boorloader gespeichert werden kann. Es wird hierzu kein Netzzugang benötigt. Alles erfolgt per Javascript im Browser.&lt;br /&gt;
&lt;br /&gt;
Seit 01/2018 gibt es die Firmware auch für das sog. &#039;&#039;lazy config&#039;&#039;. Hierbei können die Register einfach z.B. durch das nächste Öffnen des Fensters ausgelesen werden, ohne dass die Config-Taste gedrückt werden muss.&lt;br /&gt;
Das Update auf &#039;&#039;lazy config&#039;&#039; geht auf zwei Arten:&lt;br /&gt;
&lt;br /&gt;
Keine Änderung der &#039;ID=0030&#039; und Durchführen eines [https://forum.fhem.de/index.php?action=dlattach;topic=71413.0;attach=94541 Firmware] bzw. eines FHEM Updates oder &lt;br /&gt;
{{Randnotiz|RNText=Firmware für &#039;ID=00C3&#039;}}&lt;br /&gt;
Aktualisierung der Firmware auf &#039;ID=00C3&#039;. Die Dateien können hier: [https://forum.fhem.de/index.php?action=dlattach;topic=71413.0;attach=94538 makeota.html], [https://forum.fhem.de/index.php?action=dlattach;topic=71413.0;attach=94542 Firmware (hex)] bzw. [https://forum.fhem.de/index.php?action=dlattach;topic=71413.0;attach=94541 Firmware (eq3)] heruntergeladen werden.&lt;br /&gt;
&lt;br /&gt;
Verwendet man den Sensor in Kombination mit originaler eq3 Hardware, sollte man die zweite Möglichkeit wählen.&lt;br /&gt;
&lt;br /&gt;
=== Flashen des OTA Bootloaders ===&lt;br /&gt;
Anschließend wird per ISP (USBasp oder vergleichbares) der Bootloader geflasht.&lt;br /&gt;
Zum Laden des Bootloaders, sowie der Software werden die Arduino SDK bzw. avrdude und die von makeota.html generierte Datei benötigt.&lt;br /&gt;
&lt;br /&gt;
Der Bootloader lässt sich nun bei gestecktem ISP Programmer über folgende Befehle flashen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;avrdude -p m328p -P usb -c usbasp -B 3 -U lfuse:w:0xE2:m -U hfuse:w:0xD0:m -U efuse:w:0x06:m -U lock:w:0x2F:m&amp;lt;/pre&amp;gt;&lt;br /&gt;
Setzt die Fuses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;avrdude -p m328p -P usb -c usbasp -V -U flash:w:bootloader.hex&amp;lt;/pre&amp;gt;&lt;br /&gt;
lädt den eigentlichen Bootloader. Dabei ist zu achten, dass &amp;quot;bootloader.hex&amp;quot; die Datei mit dem Bootloader (bzw. der Firmware) ist und dementsprechend auch im Verzeichnis sein muss, wo die Datei zu finden ist.&lt;br /&gt;
&lt;br /&gt;
Wenn jetzt die Platine mit Spannung versorgt wird, sollte die rote LED 7x blinken. Das signalisiert, dass der Bootloader erfolgreich gestartet wurde. Er wartet jetzt darauf, dass die Firmware übertragen wird.&lt;br /&gt;
&lt;br /&gt;
=== OTA Update === &lt;br /&gt;
Hierzu wird flash-ota benötigt.&lt;br /&gt;
&lt;br /&gt;
Flash-ota funktioniert aktuell nur mit [[CUL]]/[[COC]] oder [[HM-CFG-USB USB Konfigurations-Adapter|HM-CFG-USB]] unter Linux ([[HomeMatic_Firmware_Update#Firmware_Update_mit_CUL.2FHM-CFG-USB_unter_FHEM|Update mit CUL oder HM-CFG-USB unter Linux]]), mit dem &amp;quot;HomeMatic Firmware Update Tool&amp;quot; unter Windows ([[HomeMatic_Firmware_Update#Firmware_Update_mit_HM-CFG-USB_unter_Windows|Update mit HM-CFG-USB unter Windows]]) oder mit einer CCU2.&lt;br /&gt;
&lt;br /&gt;
Für einen HM-CFG-USB oder den HM-UART sieht der Aufruf wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;./flash-ota -f avr_HM_SEC_RHS_201705271601.eq3 -s RHS0000000&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für einen CUL muss noch die USB Schnittstelle oder der Pfad des USB Geräts mit gegeben werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;./flash-ota -f avr_HM_SEC_RHS_201705271601.eq3 -s RHS0000000 -c /dev/serial/by-path/platform-3f980000.usb-usb-0:1.3:1.0-port0&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Falls Fehler während der Übertragung auftreten, muss die Übertragung nochmals wiederholt werden.&lt;br /&gt;
Wenn die Firmware erfolgreich übertragen werde konnte, kann der Sensor gepairt werden.&lt;br /&gt;
&lt;br /&gt;
== Einlöten der Reedkontakte und Anschluss an A0 &amp;amp; A1 ==&lt;br /&gt;
Den Magneten in den Drehring einbauen und diesen in das Gehäuse einbauen. Die Reedkontakte&lt;br /&gt;
Platzieren und mit einem Ohmmeter Messen, ob die Reedkontakte bei der entsprechenden Position&lt;br /&gt;
der Magnete schalten. Falls nicht, ggf. die Reedkontakte austauschen (Streuung!) bzw. einen stärkeren Magneten verwenden. Danach mittels Silberdraht bzw. Kupferlackdraht (an den zu&lt;br /&gt;
verlötenden Enden den Lack mittels eines Cuttermessers entfernen) die Reedkontakte gemäß&lt;br /&gt;
Bild verlöten und die Enden (GND, A0 bzw. A1) durch die vorgesehenen Öffnungen im Gehäuse führen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Verlötete Reedkontakte:&#039;&#039;&lt;br /&gt;
[[Datei:HM_Fenstersensor-pic15.jpg]]&lt;br /&gt;
&lt;br /&gt;
Danach die Antenne in die dafür vorgesehene Bohrung einführen und die Platine platzieren. Darauf achten, dass die Anschlüsse der Reedkontakte durch die dafür vorgesehenen Kontakte auf der Platine geführt werden.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Einführen der Antenne:&#039;&#039;&lt;br /&gt;
[[Datei:HM_Fenstersensor-pic17.jpg]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Platzierte Platine:&#039;&#039;&lt;br /&gt;
[[Datei:HM_Fenstersensor-pic16.jpg]]&lt;br /&gt;
&lt;br /&gt;
Nach Verlöten der drei Kontaktpunkte ist der Fensterdrehgriff fertig aufgebaut.&lt;br /&gt;
&lt;br /&gt;
== Sensor spezifische Einstellungen ==&lt;br /&gt;
Der Sensor meldet die Position entsprechend welcher Zustand an A0 &amp;amp; A1 an liegt. Derzeit ist folgende Logik implementiert:&lt;br /&gt;
&lt;br /&gt;
A0 &amp;amp; A1 offen - PosA -&amp;gt; OPEN&lt;br /&gt;
&lt;br /&gt;
A0 geschlossen - PosB -&amp;gt; CLOSED&lt;br /&gt;
&lt;br /&gt;
A1 geschlossen - PosC -&amp;gt; TILTED&lt;br /&gt;
&lt;br /&gt;
Die Bedeutung der Positionen kann mittels der entsprechenden Register eingestellt werden.&lt;br /&gt;
&lt;br /&gt;
Ebenfalls kann die CyclicInfoMsg aktiviert werden (zum aktivieren siehe Link am Ende des Artikels). Der Sensor meldet sich dann alle 24 Stunden mit dem aktuellen Status.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Register zum ändern der Position von A0 &amp;amp; A1:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;set &amp;lt;Device_Name&amp;gt; regSet msgRhsPosA &amp;lt;closed|open|noMsg|tilted&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;set &amp;lt;Device_Name&amp;gt; regSet msgRhsPosB &amp;lt;closed|open|noMsg|tilted&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;set &amp;lt;Device_Name&amp;gt; regSet msgRhsPosC &amp;lt;closed|open|noMsg|tilted&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Montage ==&lt;br /&gt;
Bei der Standardeinstellung der Register gilt für die Platzierung des Magneten bei geöffnetem Fenster folgendes:&lt;br /&gt;
Bei links angeschlagenem Fenster muss der Magnet nach unten, bei rechts angeschlagenem nach oben.&lt;br /&gt;
&lt;br /&gt;
== Gehäuse ==&lt;br /&gt;
Für das Gehäuse wurde auf eine 3D-Drucklösung gesetzt. Es gibt inzwischen mehrere Versionen (abgerundete obere Kante, eckige Kante uvm.).&lt;br /&gt;
&lt;br /&gt;
Die Standard Version ist [https://www.thingiverse.com/thing:2354704 hier] zu finden.&lt;br /&gt;
&lt;br /&gt;
Wer keinen 3D-Drucker besitzt kann sich im Forum nach einem 3D-Druckservice um schauen. Einige User bieten gegen kleines Geld einen netten und preiswerten {{Link2Forum|Topic=70413|LinkText=Service}} an.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[https://forum.fhem.de/index.php/topic,71413.0.0.html Link zum Foren-Thread]&lt;br /&gt;
*[https://github.com/pa-pa/AskSinPP AskSinPP  Libary]&lt;br /&gt;
*[https://github.com/pa-pa/HMSensor Alles Mögliche zu dem Projekt auf Github]&lt;br /&gt;
*[[HomeMatic_Type_threeStateSensor|CyclicInfoMsg aktivieren]]&lt;br /&gt;
*{{Link2Forum|Topic=70413|LinkText=3D-Druck service}}&lt;br /&gt;
*[[HomeMatic_Firmware_Update#Firmware_Update_mit_CUL.2FHM-CFG-USB_unter_FHEM|update-ota]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HomeMatic Components‏‎]]&lt;br /&gt;
[[Kategorie:HomeBrew‏‎]]&lt;br /&gt;
[[Kategorie:868MHz]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=WMBUS&amp;diff=27274</id>
		<title>WMBUS</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=WMBUS&amp;diff=27274"/>
		<updated>2018-06-24T20:04:54Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: WMBus_C&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=Dekodierung von Wireless M-Bus Nachrichten&lt;br /&gt;
|ModType=d&lt;br /&gt;
|ModForumArea=Sonstige Systeme&lt;br /&gt;
|ModTechName=36_WMBUS.pm&lt;br /&gt;
|ModOwner=kaihs&lt;br /&gt;
}}&lt;br /&gt;
[[WMBUS]] ist ein Modul zur Dekodierung von Wireless M-Bus Nachrichten. Solche Nachrichten werden z. B. von Zählern für Wasser, Wärme, Gas und Elektrizität ausgestrahlt.&lt;br /&gt;
Wireless M-Bus ist ein Standardprotokoll das von unterschiedlichen Herstellern unterstützt wird.&lt;br /&gt;
Das Protokoll unterstützt unterschiedliche Kodierungen des Funksignals, im wesentlichen den S-Mode, T-Mode und C-Mode. Der Empfänger (z. B. ein CUL) muss den selben Modus nutzen wie der Sender (der Zähler). &lt;br /&gt;
Wireless M-Bus unterstützt optional die Verschlüsselung der Daten per AES.&lt;br /&gt;
Die von einem Zähler gesendeten Daten können sehr unterschiedlich sein und hängen u. a. vom Zählertyp und dessen Hersteller ab.&lt;br /&gt;
&lt;br /&gt;
== Voraussetzungen ==&lt;br /&gt;
Das Modul interpretiert nur die Nachrichten die von einen geeigneten Empfänger empfangen werden. Aktuell kann ein [[CUL]] und verwandte Geräte die die culfw[http://culfw.de/culfw.html] verwenden sowie ein Amber Wireless AMB8465M dafür verwendet werden. In der culfw muss die Unterstützung des WMBUS-Protokolls aktiviert sein (#define HAS_MBUS). Bei einem CUL mit der Hardwareversion V4 ist das nicht der Fall.&lt;br /&gt;
&lt;br /&gt;
Der CUL muss in FHEM mittels Attribut rfmode=WMBus_S, WMBus_T oder WMBus_C in den zum Zähler passenden Empfangsmodus versetzt werden.&lt;br /&gt;
&lt;br /&gt;
== Anwendung ==&lt;br /&gt;
Die Erzeugung des passenden Devices in FHEM geschieht automatisch beim Empfang des ersten Datenpakets eines Zählers. Voraussetzung dafür ist, dass [[autocreate]] aktiv ist.&lt;br /&gt;
Alternativ kann ein Device manuell angelegt werden. Dazu wird der Hersteller, die Seriennummer, die Version und der Typ (Wasser, Gas, ...) des Zählers benötigt.&lt;br /&gt;
Sind die Daten verschlüsselt wird auch noch der passende Schlüssel benötigt um die Daten entschlüsseln zu können.&lt;br /&gt;
&lt;br /&gt;
== Anwendungsbeispiele ==&lt;br /&gt;
Ein per [[EnergyCam]] abgelesener Elektrizitätszähler sieht in FHEM z. B. so aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 Internals: &lt;br /&gt;
   CUL_MBUS_MSGCNT 29 &lt;br /&gt;
   CUL_MBUS_RAWMSG b1944C4189985051701028A7D7A540000A00405FAD4080002FD08222C1295B8::-67.5 &lt;br /&gt;
   CUL_MBUS_RSSI -67.5 &lt;br /&gt;
   CUL_MBUS_TIME 2014-10-24 22:57:53 &lt;br /&gt;
   DEF        FFD 17058599 1 2 &lt;br /&gt;
   DeviceMedium Electricity &lt;br /&gt;
   DeviceType 2 &lt;br /&gt;
   IODev      CUL_MBUS &lt;br /&gt;
   IdentNumber 17058599 &lt;br /&gt;
   LASTInputDev CUL_MBUS &lt;br /&gt;
   MSGCNT     29 &lt;br /&gt;
   Manufacturer FFD &lt;br /&gt;
   NAME       WMBUS_FFD_17058599_1_2 &lt;br /&gt;
   NR         49 &lt;br /&gt;
   STATE      no errors &lt;br /&gt;
   TYPE       WMBUS &lt;br /&gt;
   Version    1 &lt;br /&gt;
   addr       FFD_17058599_1_2 &lt;br /&gt;
   Readings: &lt;br /&gt;
     2014-10-24 22:57:53   1_storage_no    0 &lt;br /&gt;
     2014-10-24 22:57:53   1_type          VIF_ENERGY_WATT &lt;br /&gt;
     2014-10-24 22:57:53   1_unit          Wh &lt;br /&gt;
     2014-10-24 22:57:53   1_value         57881000 &lt;br /&gt;
     2014-10-24 22:57:53   2_storage_no    0 &lt;br /&gt;
     2014-10-24 22:57:53   2_type          VIF_ACCESS_NO &lt;br /&gt;
     2014-10-24 22:57:53   2_unit &lt;br /&gt;
     2014-10-24 22:57:53   2_value         11298 &lt;br /&gt;
     2014-10-24 22:57:53   LQI             184 &lt;br /&gt;
     2014-10-24 22:57:53   RSSI            -67.5 &lt;br /&gt;
     2014-10-24 22:57:53   battery         ok &lt;br /&gt;
     2014-10-24 22:57:53   decryption_ok   1 &lt;br /&gt;
     2014-10-24 22:57:53   energy          57881 &lt;br /&gt;
     2014-10-24 22:57:53   is_encrypted    0 &lt;br /&gt;
     2014-10-24 22:57:53   state           no errors &lt;br /&gt;
     2014-10-24 22:57:53   unit            kWh &lt;br /&gt;
 Attributes: &lt;br /&gt;
   IODev      CUL_MBUS &lt;br /&gt;
   room       WMBUS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Bekannte Probleme ==&lt;br /&gt;
Obwohl Wireless M-Bus ein standardisiertes Protokoll ist, scheint sich kaum ein Hersteller vollständig daran zu halten bzw. verwendet sog. herstellerspezifische Felder um wichtige Daten zu verpacken.&lt;br /&gt;
Aus den bisher beobachteten Datenpaketen ergibt sich &lt;br /&gt;
* Qundis (Herstellerkürzel LSE) verwendet herstellerspezifische Datenblöcke für den eigentlichen Zählerstand&lt;br /&gt;
* Techem und Hydrometer verwenden ein undokumentiertes Datenformat (CI-Field A2)&lt;br /&gt;
:&#039;&#039;(Techem Heizkostenverteiler (CI-Field A0) können über das Modul [[TechemHKV]] ausgewertet werden)&#039;&#039;&lt;br /&gt;
* RWE SmartHome Powercontrol[http://www.rwe-smarthome.de/web/cms/de/1776202/smarthome/informieren/geraete/power-control/] sendet verschlüsselt und der Hersteller gibt nicht den vollständigen Schlüssel an{{Link2Forum|Topic=24517|Message=315949}}&lt;br /&gt;
&lt;br /&gt;
Daher werden bisher erst die [[EnergyCam]] der Firma Q-loud, Zähler von Easymeter und der Kamstrup Multical 21 vollständig unterstützt.&lt;br /&gt;
Für den Multical 21 muss eine culfw mit Unterstützung für WMBUS C verwendet werden. Diese ist in der culfw ab dem 24.6.2018 enthalten.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Forumsthread {{Link2Forum|Topic=24517}}&lt;br /&gt;
* Protokoll Beschreibung [http://oms-group.org/download4all/]&lt;br /&gt;
* Beschreibung des M-BUS Protokolls [http://www.m-bus.com/files/MBDOC48.PDF]&lt;br /&gt;
[[Kategorie:Energieverbrauchsmessung]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=System%C3%BCbersicht&amp;diff=27273</id>
		<title>Systemübersicht</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=System%C3%BCbersicht&amp;diff=27273"/>
		<updated>2018-06-24T20:02:42Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: /* Protokolle */ WMBus_C&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Ein FHEM &#039;&#039;&#039;System&#039;&#039;&#039; besteht im Prinzip aus den in der nachfolgenden &#039;&#039;&#039;Übersicht&#039;&#039;&#039; aufgeführten Bestandteilen.&lt;br /&gt;
[[Datei:Systemübersicht.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;float: right;&amp;quot;&amp;gt;__TOC__&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Server ==&lt;br /&gt;
Bei der Komponente &#039;&#039;&#039;Server&#039;&#039;&#039; muss unterschieden werden zwischen dem eigentlichen &#039;&#039;&#039;FHEM&#039;&#039;&#039; Hausautomations-Server (implementiert in der Perl-Datei fhem.pl) und der Hardware, auf der dieser Server ausgeführt wird.&lt;br /&gt;
&lt;br /&gt;
Als Server &#039;&#039;&#039;Hardware&#039;&#039;&#039; sind (z.&amp;amp;nbsp;B.) möglich:&lt;br /&gt;
* Windows Rechner&lt;br /&gt;
* Linux Rechner&lt;br /&gt;
* OS X Rechner&lt;br /&gt;
* Router (z.&amp;amp;nbsp;B. [[AVM Fritz!Box|FritzBox]])&lt;br /&gt;
* Einplatinencomputer, wie [[:Kategorie:Raspberry Pi|Raspberry Pi]], [[BeagleBone Black]]&lt;br /&gt;
* DockStar, PogoPlug, etc.&lt;br /&gt;
* diverse NAS Systeme wie Buffalo Linkstation, Synology Diskstation&lt;br /&gt;
&lt;br /&gt;
(Diese Aufstellung ist nur eine unvollständige Auswahl; Details zu unterstützten Server Systemen finden sich in der Kategorie [[:Kategorie:Server Hardware|Server Hardware]]).&lt;br /&gt;
&lt;br /&gt;
== Perl ==&lt;br /&gt;
Auf dem Server muss Perl installiert sein. Zur erforderlichen Version gibt es widersprüchliche Aussagen, die vor allem daraus resultieren, dass verschiedene FHEM-Module von verschiedenen Entwicklern stammen und daher unterschiedliche Anforderungen stellen. Laut FHEM-Webseite wird mindestens Version 5.6 benötigt, faktisch setzen aber viele Module 5.10 oder sogar 5.12 voraus. Der Betrieb mit Grundfunktionen ist jedoch zumindest ab Version 5.8.8 mit Einschränkungen möglich.&lt;br /&gt;
&lt;br /&gt;
== Konfiguration ==&lt;br /&gt;
Das Hausautomations-System wird definiert über die [[Konfiguration]], die im Regelfall aus der &lt;br /&gt;
* reinen Textdatei &amp;lt;code&amp;gt;fhem.cfg&amp;lt;/code&amp;gt; (Standard nach der Erstinstallation) oder alternativ einer&lt;br /&gt;
* [[configdb|SQL-Datenbank]]&lt;br /&gt;
besteht.&lt;br /&gt;
&lt;br /&gt;
Die Konfiguration enthält Definitionen für die Bestandteile (Geräte) und Funktionen des jeweiligen Hausautomations-Systems. Die verfügbaren Befehle und deren Syntax sind in der Befehlsreferenz ({{Link2CmdRef}}) aufgeführt und beschrieben. Zu einigen Hilfsmodulen gibt es [[:Kategorie:Hilfsmodul|detaillierte Beschreibungen]] mit Beispielen.&lt;br /&gt;
&lt;br /&gt;
== Benutzeroberfläche ==&lt;br /&gt;
Der Zugriff auf FHEM erfolgt mittels Webbrowser oder App über die verfügbaren &#039;&#039;&#039;[[:Kategorie:FHEM Frontends|FHEM Benutzeroberflächen]]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
In den FHEM Server integriert ist ein Webserver ([[PGM2]]), der im Prinzip immer zur Verfügung steht. Abhängig vom benutzten Klienten ist PGM2 über &lt;br /&gt;
* &amp;lt;code&amp;gt;serverhostnameoderIP:8083/fhem&amp;lt;/code&amp;gt; (Desktop-Darstellung = Port 8083),&lt;br /&gt;
* &amp;lt;code&amp;gt;serverhostnameoderIP:8084/fhem&amp;lt;/code&amp;gt; (Smartphone-Darstellung = Port 8084) oder &lt;br /&gt;
* &amp;lt;code&amp;gt;serverhostnameoderIP:8085/fhem&amp;lt;/code&amp;gt; (Tablet-Darstellung = Port 8085) &lt;br /&gt;
erreichbar.&lt;br /&gt;
&lt;br /&gt;
Eine Auswahl der Benutzeroberflächen:&lt;br /&gt;
* PGM2 - das Standardinterface&lt;br /&gt;
* [[FLOORPLAN]]&lt;br /&gt;
* [[FHEM Tablet UI]]&lt;br /&gt;
* [[SmartVISU]]&lt;br /&gt;
* diverse Apps für iOS und Android (Auswahl unter: [[:Kategorie:FHEM Frontends|FHEM Benutzeroberflächen]])&lt;br /&gt;
&lt;br /&gt;
Beispielhafte Screenshots diverser Benutzeroberflächen: http://fhem.de/fhem.html#Screenshots&lt;br /&gt;
&lt;br /&gt;
== Module ==&lt;br /&gt;
Die Funktionalität von FHEM kann über &#039;&#039;&#039;Module&#039;&#039;&#039; erweitert werden. Module können die unterschiedlichsten Aufgaben übernehmen vom Anbinden eines Hardwaresystems&lt;br /&gt;
über die Bereitstellung eines Frontends bis zur Automatisierung von Aufgaben. Beispiele für Module:&lt;br /&gt;
* 00_CUL.pm - Implementierung der Unterstützung für den [[CUL]]&lt;br /&gt;
* 11_FHT.pm - Unterstützung der [[:Kategorie:FHT Components|FHT]] Heizungssteuerung&lt;br /&gt;
* 95_FLOORPLAN.pm - Grundriss (oder Ähnliches) als Benutzeroberfläche &lt;br /&gt;
* uvm.&lt;br /&gt;
&lt;br /&gt;
Module können unterteilt werden in&lt;br /&gt;
* [[:Kategorie:FHEM Befehl|Befehlsmodule]] (FHEM-Befehle sind teilweise eigenständige Module) &lt;br /&gt;
* [[:Kategorie:Hilfsmodul|Hilfsmodule]]&lt;br /&gt;
* [[:Kategorie:Gerätemodul|Gerätemodule]]&lt;br /&gt;
Die offiziell in FHEM enthaltenen Module sind in der {{Link2CmdRef}} beschrieben. Sie werden über den [[Update]]-Befehl von FHEM verteilt und aktualisiert. Voraussetzung für die Aufnahme als offizielles Modul sind Supportwille durch den Entwickler und Dokumentation des Moduls.&lt;br /&gt;
&lt;br /&gt;
Zusätzlich existiert eine Vielzahl von [[:Kategorie:Modul (Inoffiziell)|inoffiziellen Modulen]], die manuell in FHEM installiert werden können. Auch die Aktualisierung erfolgt nicht über den Update-Befehl, sondern muss durch den Nutzer selbst erfolgen. Inoffizielle Module sind an den verschiedensten Stellen zu finden:&lt;br /&gt;
* [[:Kategorie:Modul (Contrib)|Contrib]]-Verzeichnis im offiziellen FHEM-Sourcecode-SVN [http://svn.fhem.de/trac/browser/trunk/fhem/contrib]&lt;br /&gt;
* Beiträge im [https://forum.fhem.de/ FHEM-Forum]&lt;br /&gt;
* private Homepages&lt;br /&gt;
&lt;br /&gt;
== Interfaces ==&lt;br /&gt;
Die Verbindung zu den angeschlossenen &#039;&#039;&#039;Geräten&#039;&#039;&#039; der Hausautomation wird im Allgemeinen - geräteabhängig - über [[Interface|Interfaces]] (manchmal auch als &#039;&#039;&#039;Gateway&#039;&#039;&#039; bezeichnet) hergestellt. Das kann z.&amp;amp;nbsp;B. im Falle von [[HomeMatic]] ein [[HMLAN Konfigurator]] sein, ein mittels LAN mit dem FHEM Server verbundenes Gerät, das die FHEM Steuerbefehle  in das HomeMatic Funkprotokoll umsetzt - und auch die Funktelegramme der HomeMatic Komponenten an FHEM zurückgibt. Bei HomeMatic-Komponenten ist der Einsatz von Interfaces des Hersteller dieser Geräte (eQ-3) zu empfehlen, da bei CUL und seinen Derivaten Probleme mit dem Timing auftreten können. Eine Übersicht hierzu ist [[HomeMatic#FHEM_als_Zentrale|hier]] zu finden. &lt;br /&gt;
&lt;br /&gt;
Entsprechende Interfaces gibt es auch für andere Funkprotokolle und für die drahtgebundenen Systeme.&lt;br /&gt;
&lt;br /&gt;
Eine (unvollständige) Liste solcher Interfaces (siehe auch [[:Kategorie:Interfaces|Kategorie Interfaces]]):&lt;br /&gt;
* [[CUL]] - je nach Einstellung für die Kommunikation mit [[:Kategorie:FS20 Components|FS20]], [[:Kategorie:FHT Components|FHT]] und andere [[SlowRF]] Protokolle, [[MAX|MAX!]] Heizungssteuerung oder [[:Kategorie:HomeMatic Components|HomeMatic]] und, mit Einschränkungen, InterTechno (nur senden)&lt;br /&gt;
* [[CUNO]], ähnlich CUL, jedoch nicht per USB sondern per IP angebunden (z.Zt. -Stand Januar 2014 - nicht für HomeMatic empfohlen)&lt;br /&gt;
* [[HMLAN Konfigurator|HomeMatic LAN Konfigurations-Adapter]] - HomeMatic&lt;br /&gt;
* [[HM-MOD-RPI-PCB HomeMatic Funkmodul für Raspberry Pi|HomeMatic Funkmodul für Raspberry Pi]] - Homematic&lt;br /&gt;
* [[HMCCU|Homematic CCU2]] - HomeMatic und HomeMatic IP&lt;br /&gt;
* [[MAX#MAXLAN|MAX! Cube LAN-Gateway]]&lt;br /&gt;
* Schnittstellen(karten) für [[:Kategorie:1-Wire|1-Wire]]&lt;br /&gt;
* TCM(120/310) zur Anbindung von [[:Kategorie:EnOcean Components|EnOcean]]&lt;br /&gt;
* [[Arduino]] mit Firmata über USB oder Netzwerk&lt;br /&gt;
* [[panStamp]] als Möglichkeit Arduinos mit diversen Sensor- und I/O- Boards per 868MHz Funk über das SWAP protokoll anzubinden&lt;br /&gt;
* [[JeeLink]], ein weiteres USB-Stick Interface (ebenfalls arduino basiert) für diverse 433MHz und 868MHz Komponenten&lt;br /&gt;
* [[RFXtrx]] für InterTechno, RSL, ELRO etc., Wetter-Sensoren (Oregon-Scientific, Cresta, La Crosse, TFA, UPM) und andere 433&amp;amp;nbsp;Mhz Geräte.&lt;br /&gt;
* manche Komponenten ([[:Kategorie:IP Components|IP Komponenten]]) können über TCP/IP (LAN) direkt vom FHEM Server aus angesprochen werden; hier ist dann kein weiteres Interface im eigentlichen Sinne erforderlich. Dies gilt auch für diverse Module die Geräte über WEB Dienste des Herstellers anbinden (z.&amp;amp;nbsp;B. [[Withings]], [[netatmo]], [[MQTT]]).&lt;br /&gt;
&lt;br /&gt;
== Protokolle ==&lt;br /&gt;
Der Kommunikation zwischen Interfaces und Geräten liegt jeweils ein bestimmtes Protokoll zugrunde. Unterstützte Protokolle mit ihren Eigenschaften sind in der folgenden Tabelle aufgelistet.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|+ Übersicht über unterstützte Funkprotokolle&lt;br /&gt;
|-&lt;br /&gt;
! Name !! rfMode !! Frequenz !! Modulation !! Datenrate !! class=&amp;quot;unsortable&amp;quot; | Interfaces !! class=&amp;quot;unsortable&amp;quot; | Modul !! class=&amp;quot;unsortable&amp;quot; | Geräte (Beispiel) !! class=&amp;quot;unsortable&amp;quot; | Bemerkungen&lt;br /&gt;
|-&lt;br /&gt;
| [[FS20_Allgemein|FS20]] || SlowRF || 868,35MHz || AM || 1kHz || CU*, FHZ || {{Link2CmdRef|Anker=FS20|Label=FS20}} || - || -&lt;br /&gt;
|-&lt;br /&gt;
| FHT  || SlowRF || 868,35MHz || AM || 1kHz || CU*, FHZ || {{Link2CmdRef|Anker=CUL_FHTTK|Label=FHTTK}}, {{Link2CmdRef|Anker=FHT|Label=FHT}} || Heizungsregelung || -&lt;br /&gt;
|-&lt;br /&gt;
| S300 || SlowRF || 868,35MHz || AM || 1kHz || CU*, FHZ || {{Link2CmdRef|Anker=CUL_WS|Label=CUL_WS}} || Temperatur-/Feuchtesensoren || -&lt;br /&gt;
|-&lt;br /&gt;
| HMS || SlowRF || 868,35MHz || AM || 1kHz || CU*O, FHZ || - || ?? || -&lt;br /&gt;
|-&lt;br /&gt;
| EM || SlowRF || 868,35MHz || AM || 1kHz || CU*, FHZ || {{Link2CmdRef|Anker=CUL_EM|Label=CUL_EM}} || Energiemonitore (Strom, Gas) || -&lt;br /&gt;
|-&lt;br /&gt;
| [[HomeMatic ]]|| HomeMatic || 868,3MHz || FM || 10kHz || CU*, [[HM-CFG-LAN_LAN_Konfigurations-Adapter|HMLan]], [[HM-CFG-USB_USB_Konfigurations-Adapter|HMUsb]], [[HM-MOD-RPI-PCB HomeMatic Funkmodul für Raspberry Pi|HomeMatic Funkmodul für Raspberry Pi]] || {{Link2CmdRef|Anker=CUL_HM|Label=CUL_HM}}, {{Link2CmdRef|Anker=HMUARTLGW|Label=HMUARTLGW }}  || [[:Kategorie:HomeMatic_Components|diverse]] || -&lt;br /&gt;
|-&lt;br /&gt;
| [[MAX|MAX!]] || MAX || 868,3MHz || FM || 20kHz || CU*, [[MAX#MAXLAN|MAXLAN]] ||  {{Link2CmdRef|Lang=de|Anker=MAX|Label=MAX}} ||  [[:Kategorie:MAX|Wandthermostat, Heizkörperthermostate, Fensterkontakt, Zwischenstecker]] ||  -&lt;br /&gt;
|-&lt;br /&gt;
| IT || - || 433MHz || AM? || 1kHz || CU*433, || - || - || -&lt;br /&gt;
|-&lt;br /&gt;
| Firmata WiFi || - || 2,4/5 GHz ||  ||  ||  || {{Link2CmdRef|Anker=FRM|Label=FRM}} || Arduino || -&lt;br /&gt;
|-&lt;br /&gt;
| SWAP || - || 868 (433/915) MHz || GFSK || 38.3835 Kbps || panStamp (+panStick) || {{Link2CmdRef|Anker=SWAP|Label=SWAP}} || RGB LED Driver, diverse Sensoren und Aktoren || -&lt;br /&gt;
|-&lt;br /&gt;
| [[:Kategorie:EnOcean  Components|EnOcean]] || - || 315 / 868 / 902 / 928MHz || ASK || 125 kbit/s || {{Link2CmdRef|Anker=TCM|Label=TCM}} || {{Link2CmdRef|Anker=EnOcean|Label=EnOcean}} || Batterielose Funksensoren, diverse Aktoren || -&lt;br /&gt;
|-&lt;br /&gt;
| PCA || - || 868,35MHz || ?? || ?? || [[JeeLink]] || {{Link2CmdRef|Anker=PCA301|Label=PCA301}} || [[PCA301 Funkschaltsteckdose mit Energieverbrauchsmessung|PCA301]] || -&lt;br /&gt;
|-&lt;br /&gt;
| [[La Crosse]] || - || 868,35MHz || ?? || ?? || [[JeeLink]], LGW || {{Link2CmdRef|Anker=Lacrosse|Label=Lacrosse}} || LaCrosse IT+ (Technoline) Sensoren || -&lt;br /&gt;
|-&lt;br /&gt;
| ZigBee Light Link || - || 2,4 GHz ||  ||  || HUE Bridge (RaspBee) || {{Link2CmdRef|Anker=HUEBridge|Label=HUEBridge}} || Philips HUE und LightLink Lampen (auch Osram LIGHTIFY an der HUE-Bridge)|| [http://www.developers.meethue.com/documentation/how-hue-works]&lt;br /&gt;
|-&lt;br /&gt;
| [[MySensors]] || - || 2,4 GHz, 868/433 MHz, RS485 (2-Draht) ||  ||  || MySensors Gateway, [[MQTT]]  || [[MYSENSORS]] || [http://www.mysensors.org/build/ Selbstbau-Sensoren] || auch LoRa möglich&lt;br /&gt;
|-&lt;br /&gt;
| [[:Kategorie:Z-Wave Components|Z-Wave]] || - || 868MHz || 2-FSK || 9.600 bit/s oder 40 Kbit/s || {{Link2CmdRef|Anker=ZWDongle|Label=ZWDongle}} || {{Link2CmdRef|Anker=ZWave|Label=ZWave}} || - || -&lt;br /&gt;
|-&lt;br /&gt;
| [[WMBUS]] || WMBus_T, WMBus_S, WMBus_C || 868MHz || ?? || 100 kbit/s / 32.768 kbit/s || CU* || {{Link2CmdRef|Anker=WMBUS|Label=WMBUS}} || Wasseruhren, Wärmezähler, Elektrozähler || - &lt;br /&gt;
|-&lt;br /&gt;
| colspan=&amp;quot;9&amp;quot; | &#039;&#039;Tabelle muss noch vervollständigt werden&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| colspan=&amp;quot;2&amp;quot; | &#039;&#039;&#039;Legende:&#039;&#039;&#039; &lt;br /&gt;
| colspan=&amp;quot;7&amp;quot; | CU* = CUL, CUN, CUNO / &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|+ Übersicht über drahtgebundene Systeme&lt;br /&gt;
|-&lt;br /&gt;
! Name !!  class=&amp;quot;unsortable&amp;quot; | Interfaces (Hardware) !! class=&amp;quot;unsortable&amp;quot; | Modul !! class=&amp;quot;unsortable&amp;quot; | Geräte (Beispiel) !! class=&amp;quot;unsortable&amp;quot; | Bemerkungen&lt;br /&gt;
|-&lt;br /&gt;
| [[1-Wire]]  || [[Interfaces für 1-Wire|diverse]] || {{Link2CmdRef|Anker=OWX|Label=OWX}} || [[:Kategorie:1-Wire|1-Wire]] || -&lt;br /&gt;
|-&lt;br /&gt;
| [[EIB_/_KNX|EIB/KNX]]  || {{Link2CmdRef|Anker=TUL|Label=TUL}} || {{Link2CmdRef|Anker=EIB|Label=EIB}} || [[:Kategorie:EIB/KNX|EIB/KNX]] || -&lt;br /&gt;
|-&lt;br /&gt;
| Firmata || RS-232, USB, Ethernet || {{Link2CmdRef|Anker=FRM|Label=FRM}} || Arduino || -&lt;br /&gt;
|-&lt;br /&gt;
| [[HomeMatic Wired]]  || [[HomeMatic Wired RS485 LAN Gateway|HM485 LAN Gateway]] || {{Link2CmdRef|Anker=HM485_LAN|Label=HM485_LAN}} || [[:Kategorie:HomeMatic Components|Präfix HMW]] || -&lt;br /&gt;
|-&lt;br /&gt;
| colspan=&amp;quot;5&amp;quot; | &#039;&#039;Tabelle muss noch vervollständigt werden&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| colspan=&amp;quot;2&amp;quot; | &#039;&#039;&#039;Legende:&#039;&#039;&#039; &lt;br /&gt;
| colspan=&amp;quot;3&amp;quot; | ...&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Komponenten ==&lt;br /&gt;
Der eigentliche Zweck eines Hausautomatisierungs-Projekts sind dann letztendlich die &#039;&#039;&#039;Geräte&#039;&#039;&#039; (Komponenten / Aktoren / [[:Kategorie:Schalter (Empfänger)|Empfänger]]), die automatisch gesteuert werden sollen, bzw. auch Auslöser für Aktionen ([[:Kategorie:Schalter (Sender)|Sender]]) und Lieferant von Datenmaterial ([[:Kategorie:Hardware Typen|Sensoren]]) sind.&lt;br /&gt;
&lt;br /&gt;
Diese Geräte sind, sofern es eine detaillierte Beschreibung dazu gibt, in den jeweiligen Unterseiten der [[:Kategorie:Hardware|Hardwareliste]] aufgeführt.&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
* [http://www.enocean.com/de/home/ EnOcean] Homepage&lt;br /&gt;
* [http://www.elv.de ELV], (Haupt-)Lieferant von FS20, FHT, HomeMatic, MAX!&lt;br /&gt;
* [https://github.com/firmata/protocol Firmata] Protokoll&lt;br /&gt;
* [http://www.panstamp.com panStamp], panStamp Hersteller&lt;br /&gt;
* [http://jeelabs.com/products/jeelink Jeelabs], JeeLink Hersteller&lt;br /&gt;
* [http://www.zigbee.org/ Zigbee] Homepage&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:FHEM]]&lt;br /&gt;
[[Kategorie:FHEM-Verwendung]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=WMBUS&amp;diff=27272</id>
		<title>WMBUS</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=WMBUS&amp;diff=27272"/>
		<updated>2018-06-24T20:01:45Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: Umterstützung für Kamstrup Multical&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=Dekodierung von Wireless M-Bus Nachrichten&lt;br /&gt;
|ModType=d&lt;br /&gt;
|ModForumArea=Sonstige Systeme&lt;br /&gt;
|ModTechName=36_WMBUS.pm&lt;br /&gt;
|ModOwner=kaihs&lt;br /&gt;
}}&lt;br /&gt;
[[WMBUS]] ist ein Modul zur Dekodierung von Wireless M-Bus Nachrichten. Solche Nachrichten werden z. B. von Zählern für Wasser, Wärme, Gas und Elektrizität ausgestrahlt.&lt;br /&gt;
Wireless M-Bus ist ein Standardprotokoll das von unterschiedlichen Herstellern unterstützt wird.&lt;br /&gt;
Das Protokoll unterstützt unterschiedliche Kodierungen des Funksignals, im wesentlichen den sogenannten S-Mode und den T-Mode. Der Empfänger (z. B. ein CUL) muss den selben Modus nutzen wie der Sender (der Zähler). &lt;br /&gt;
Wireless M-Bus unterstützt optional die Verschlüsselung der Daten per AES.&lt;br /&gt;
Die von einem Zähler gesendeten Daten können sehr unterschiedlich sein und hängen u. a. vom Zählertyp und dessen Hersteller ab.&lt;br /&gt;
&lt;br /&gt;
== Voraussetzungen ==&lt;br /&gt;
Das Modul interpretiert nur die Nachrichten die von einen geeigneten Empfänger empfangen werden. Aktuell kann ein [[CUL]] und verwandte Geräte die die culfw[http://culfw.de/culfw.html] verwenden sowie ein Amber Wireless AMB8465M dafür verwendet werden. In der culfw muss die Unterstützung des WMBUS-Protokolls aktiviert sein (#define HAS_MBUS). Bei einem CUL mit der Hardwareversion V4 ist das nicht der Fall.&lt;br /&gt;
&lt;br /&gt;
Der CUL muss in FHEM mittels Attribut rfmode=WMBus_S oder WMBus_T in den zum Zähler passenden Empfangsmodus versetzt werden.&lt;br /&gt;
&lt;br /&gt;
== Anwendung ==&lt;br /&gt;
Die Erzeugung des passenden Devices in FHEM geschieht automatisch beim Empfang des ersten Datenpakets eines Zählers. Voraussetzung dafür ist, dass [[autocreate]] aktiv ist.&lt;br /&gt;
Alternativ kann ein Device manuell angelegt werden. Dazu wird der Hersteller, die Seriennummer, die Version und der Typ (Wasser, Gas, ...) des Zählers benötigt.&lt;br /&gt;
Sind die Daten verschlüsselt wird auch noch der passende Schlüssel benötigt um die Daten entschlüsseln zu können.&lt;br /&gt;
&lt;br /&gt;
== Anwendungsbeispiele ==&lt;br /&gt;
Ein per [[EnergyCam]] abgelesener Elektrizitätszähler sieht in FHEM z. B. so aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 Internals: &lt;br /&gt;
   CUL_MBUS_MSGCNT 29 &lt;br /&gt;
   CUL_MBUS_RAWMSG b1944C4189985051701028A7D7A540000A00405FAD4080002FD08222C1295B8::-67.5 &lt;br /&gt;
   CUL_MBUS_RSSI -67.5 &lt;br /&gt;
   CUL_MBUS_TIME 2014-10-24 22:57:53 &lt;br /&gt;
   DEF        FFD 17058599 1 2 &lt;br /&gt;
   DeviceMedium Electricity &lt;br /&gt;
   DeviceType 2 &lt;br /&gt;
   IODev      CUL_MBUS &lt;br /&gt;
   IdentNumber 17058599 &lt;br /&gt;
   LASTInputDev CUL_MBUS &lt;br /&gt;
   MSGCNT     29 &lt;br /&gt;
   Manufacturer FFD &lt;br /&gt;
   NAME       WMBUS_FFD_17058599_1_2 &lt;br /&gt;
   NR         49 &lt;br /&gt;
   STATE      no errors &lt;br /&gt;
   TYPE       WMBUS &lt;br /&gt;
   Version    1 &lt;br /&gt;
   addr       FFD_17058599_1_2 &lt;br /&gt;
   Readings: &lt;br /&gt;
     2014-10-24 22:57:53   1_storage_no    0 &lt;br /&gt;
     2014-10-24 22:57:53   1_type          VIF_ENERGY_WATT &lt;br /&gt;
     2014-10-24 22:57:53   1_unit          Wh &lt;br /&gt;
     2014-10-24 22:57:53   1_value         57881000 &lt;br /&gt;
     2014-10-24 22:57:53   2_storage_no    0 &lt;br /&gt;
     2014-10-24 22:57:53   2_type          VIF_ACCESS_NO &lt;br /&gt;
     2014-10-24 22:57:53   2_unit &lt;br /&gt;
     2014-10-24 22:57:53   2_value         11298 &lt;br /&gt;
     2014-10-24 22:57:53   LQI             184 &lt;br /&gt;
     2014-10-24 22:57:53   RSSI            -67.5 &lt;br /&gt;
     2014-10-24 22:57:53   battery         ok &lt;br /&gt;
     2014-10-24 22:57:53   decryption_ok   1 &lt;br /&gt;
     2014-10-24 22:57:53   energy          57881 &lt;br /&gt;
     2014-10-24 22:57:53   is_encrypted    0 &lt;br /&gt;
     2014-10-24 22:57:53   state           no errors &lt;br /&gt;
     2014-10-24 22:57:53   unit            kWh &lt;br /&gt;
 Attributes: &lt;br /&gt;
   IODev      CUL_MBUS &lt;br /&gt;
   room       WMBUS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Bekannte Probleme ==&lt;br /&gt;
Obwohl Wireless M-Bus ein standardisiertes Protokoll ist, scheint sich kaum ein Hersteller vollständig daran zu halten bzw. verwendet sog. herstellerspezifische Felder um wichtige Daten zu verpacken.&lt;br /&gt;
Aus den bisher beobachteten Datenpaketen ergibt sich &lt;br /&gt;
* Qundis (Herstellerkürzel LSE) verwendet herstellerspezifische Datenblöcke für den eigentlichen Zählerstand&lt;br /&gt;
* Techem und Hydrometer verwenden ein undokumentiertes Datenformat (CI-Field A2)&lt;br /&gt;
:&#039;&#039;(Techem Heizkostenverteiler (CI-Field A0) können über das Modul [[TechemHKV]] ausgewertet werden)&#039;&#039;&lt;br /&gt;
* RWE SmartHome Powercontrol[http://www.rwe-smarthome.de/web/cms/de/1776202/smarthome/informieren/geraete/power-control/] sendet verschlüsselt und der Hersteller gibt nicht den vollständigen Schlüssel an{{Link2Forum|Topic=24517|Message=315949}}&lt;br /&gt;
&lt;br /&gt;
Daher werden bisher erst die [[EnergyCam]] der Firma Q-loud, Zähler von Easymeter und der Kamstrup Multical 21 vollständig unterstützt.&lt;br /&gt;
Für den Multical 21 muss eine culfw mit Unterstützung für WMBUS C verwendet werden. Diese ist in der culfw ab dem 24.6.2018 enthalten.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Forumsthread {{Link2Forum|Topic=24517}}&lt;br /&gt;
* Protokoll Beschreibung [http://oms-group.org/download4all/]&lt;br /&gt;
* Beschreibung des M-BUS Protokolls [http://www.m-bus.com/files/MBDOC48.PDF]&lt;br /&gt;
[[Kategorie:Energieverbrauchsmessung]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FHEM_Tablet_UI&amp;diff=27271</id>
		<title>FHEM Tablet UI</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FHEM_Tablet_UI&amp;diff=27271"/>
		<updated>2018-06-24T09:56:58Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: /* Icons */ Typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=Oberfläche für FHEM&lt;br /&gt;
|ModType=x&lt;br /&gt;
|ModFTopic=34233&lt;br /&gt;
|ModForumArea=TabletUI&lt;br /&gt;
|ModTechName=n.a.&lt;br /&gt;
|ModOwner=setstate ({{Link2FU|7023|Forum}})&lt;br /&gt;
}}&lt;br /&gt;
[[FHEM Tablet UI]] (FTUI) ist ein leichtgewichtiges aber funktionsreiches Frontend-Framework zum Steuern und Überwachen von in FHEM integrierten Geräten. Es basiert auf HTML/CSS/JavaScript und stellt somit keine zusätzlichen Anforderungen an den FHEM-Server.&lt;br /&gt;
&lt;br /&gt;
Mit Hilfe zahlreicher Widgets, die sehr leicht mit HTML Code konfiguriert werden können, ist es möglich, innerhalb kurzer Zeit ein den eigenen Wünschen entsprechendes User-Interface aufzubauen.&lt;br /&gt;
&lt;br /&gt;
Für den Betrieb ist nur eine FHEM-Installation mit [[HTTPSRV|HTTPSRV-Modul]] sowie ein gängiger Webbrowser notwendig.&lt;br /&gt;
&lt;br /&gt;
Mit wenigen Anpassungen ist es auch möglich das UI auf anderen Webservern (Apache, u.a.) zu betreiben. Somit können FHEM und FHEM Tablet UI auch auf getrennten Systemen ausgeführt werden.&lt;br /&gt;
&lt;br /&gt;
[[File:tablet_ui.png|thumb|500px|center|Beispiel für ein mit [[FHEM Tablet UI]] erstelltes User-Interface]]&lt;br /&gt;
&lt;br /&gt;
{{Todo|Design-Möglichkeiten erklären, Navigationsmethoden ausformulieren}} &lt;br /&gt;
&lt;br /&gt;
== Installation ==&lt;br /&gt;
Die Installation von FHEM Tablet UI erzeugt keinen großen Aufwand und besteht im Großen und Ganzen aus drei Schritten:&lt;br /&gt;
*Dateien aus dem GitHub-Repository herunterladen&lt;br /&gt;
*FHEM konfigurieren ([[HTTPSRV]]-Device erstellen, [[FHEMWEB]]-Attribut longpoll einstellen)&lt;br /&gt;
*Eine Beispieldatei anlegen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|Diese Anleitung geht davon aus, dass FHEM unter Debian nach der Anleitung [https://debian.fhem.de Stable build using apt] installiert wurde.&lt;br /&gt;
Ist dies nicht der Fall, muss der Pfad &#039;&#039;&#039;/opt/fhem&#039;&#039;&#039; dementsprechend angepasst werden.}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;1.&#039;&#039;&#039; Zuerst müssen alle Dateien von FHEM Tablet UI in das FHEM-Verzeichnis &#039;&#039;&#039;/opt/fhem/www&#039;&#039;&#039; kopiert werden. Das geht mit folgendem &#039;&#039;&#039;update&#039;&#039;&#039;-Befehl über die FHEM-Befehlszeile.&lt;br /&gt;
:&amp;lt;code&amp;gt;update all https://raw.githubusercontent.com/knowthelist/fhem-tablet-ui/master/controls_fhemtabletui.txt&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:[[Datei:FTUI_Installation_01.png|thumb|none|Schritt 1: Dateien kopieren]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;2.&#039;&#039;&#039; Anschließend ist ein neues [[HTTPSRV]]-Device in FHEM anzulegen, welches auf den Ordner mit den gerade heruntergeladenen Dateien verweist.&lt;br /&gt;
:&amp;lt;code&amp;gt;define TABLETUI HTTPSRV ftui/ ./www/tablet/ Tablet-UI&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:[[Datei:FTUI_Installation_02.png|thumb|none|Schritt 2: HTTPSRV-Device anlegen]]&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|Dieser Schritt kann ausgelassen werden, wenn die Funktionalitäten von [[FHEMWEB]] ausreichend sind. Dann muss FTUI aber in weiterer Folge unter der URL &#039;&#039;&#039;&amp;lt;nowiki&amp;gt;http(s)://&amp;lt;fhem-server&amp;gt;:8083/fhem/tablet/index.html&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039; aufgerufen werden und es wird kein Link auf FTUI in der FHEM GUI erstellt. Vorteil ist aber, dass das FHEMWEB-Caching verwendet werden kann. Siehe dieser {{Link2Forum|Topic=86362|Message=788258}}.}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;3.&#039;&#039;&#039; Damit FHEM Tablet UI mit FHEM kommunizieren kann, ist noch die &#039;&#039;&#039;longpoll&#039;&#039;&#039;-Einstellung im [[FHEMWEB]] Device festzulegen.&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;attr WEB longpoll websocket&amp;lt;/code&amp;gt;&lt;br /&gt;
:bzw. bei Problemen mit &#039;&#039;websocket&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;attr WEB longpoll 1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:[[Datei:FTUI_Installation_03.png|thumb|none|Schritt 3: longpoll einstellen]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;4.&#039;&#039;&#039; Weil FTUI noch nichts anzuzeigen hat, wird die Datei &#039;&#039;&#039;/opt/fhem/www/tablet/index-example.html&#039;&#039;&#039; nach &#039;&#039;&#039;/opt/fhem/www/tablet/index.html&#039;&#039;&#039; kopiert.&lt;br /&gt;
:&amp;lt;code&amp;gt;sudo cp -a /opt/fhem/www/tablet/index-example.html /opt/fhem/www/tablet/index.html&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:[[Datei:FTUI_Installation_04.png|thumb|none|Schritt 4: index.html erstellen]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;5.&#039;&#039;&#039; Abschließend muss FHEM noch &#039;&#039;&#039;neu gestartet&#039;&#039;&#039; werden (&#039;&#039;shutdown restart&#039;&#039;) da das Attribut &#039;&#039;&#039;longpoll&#039;&#039;&#039; geändert wurde.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Somit ist FHEM Tablet UI bereit zur Verwendung und kann durch Aufruf der URL &#039;&#039;&#039;&amp;lt;nowiki&amp;gt;http://&amp;lt;fhem-server&amp;gt;:8083/fhem/ftui/&amp;lt;/nowiki&amp;gt;&#039;&#039;&#039; oder den Link im FHEM-Menü geöffnet werden&lt;br /&gt;
&lt;br /&gt;
== Update ==&lt;br /&gt;
Ein Update von FTUI kann ebenfalls über die FHEM-Kommandozeile erfolgen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;1.&#039;&#039;&#039; Prüfen der Änderungen seit dem letzten Download/Update durch Eingabe von:&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;update check https://raw.githubusercontent.com/knowthelist/fhem-tablet-ui/master/controls_fhemtabletui.txt&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;2.&#039;&#039;&#039; Update der geänderten Dateien durch Eingabe von:&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;update all https://raw.githubusercontent.com/knowthelist/fhem-tablet-ui/master/controls_fhemtabletui.txt&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Eine weitere Option ist das Hinzufügen des FTUI-Git-Repositories zum allgemeinem Update-Vorgang von FHEM. Dabei wird dann bei einem FHEM-Update auch gleich FHEM Tablet UI aktualisiert, bzw. die Änderungen angezeigt.&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;update add https://raw.githubusercontent.com/knowthelist/fhem-tablet-ui/master/controls_fhemtabletui.txt&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Konfiguration ==&lt;br /&gt;
===DOCTYPE===&lt;br /&gt;
In allen HTML-Dateien, die im Browser geladen werden und das typische HTML-Gerüst besitzen (also alle Hauptseiten, jedoch keine Template-Dateien), sollte eine &#039;&#039;Document Type Declaration&#039;&#039; (DTDT) eingefügt werden. Mit ihr wird festgelegt, welche &#039;&#039;Document Type Definition&#039;&#039; hier verwendet wird (das kommt aus der Metasprache XML), konkret also, in welcher Version der nachfolgende HTML-Code vom Browser interpretiert werden soll. Lässt man die DTDT weg, oder definiert sie auf verschiedenen Seiten unterschiedlich, kann ein und der selbe HTML-Code zu unterschiedlichen Darstellungen führen. Die DTDT erfolgt immer auf der ersten Zeile, noch vor dem &amp;lt;code&amp;gt;&amp;lt;html&amp;gt;&amp;lt;/code&amp;gt;-Tag. Nachfolgend wird HTML5 verwendet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE html&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
    &amp;lt;head&amp;gt;...&amp;lt;/head&amp;gt;&lt;br /&gt;
    &amp;lt;body&amp;gt;...&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===META-Parameter===&lt;br /&gt;
Das Tablet UI lässt sich über die META-Parameter konfigurieren. Diese Parameter sind in jeder &#039;&#039;&#039;.html&#039;&#039;&#039; Datei (z.B. index.html) im Abschnitt &#039;&#039;&#039;&amp;lt;head&amp;gt;&#039;&#039;&#039; einzutragen. Ausgenommen davon sind Dateien, die als Template, Pagebutton-Zielseiten oder ähnliches eingebunden werden.&lt;br /&gt;
&lt;br /&gt;
Die Parameter sind immer nach diesem Schema aufgebaut:&lt;br /&gt;
 &amp;lt;meta name=&amp;quot;[Parameter-Name]&amp;quot; content=&amp;quot;[Parameter-Wert]&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Verbindung zu FHEM===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!Parameter-Name!!Standard-Wert!!Mögliche Werte!!Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
|web_device||WEB||String||FHEM-Device, welches für das Polling verwendet wird&lt;br /&gt;
|-&lt;br /&gt;
|longpoll||1||0, 1||&lt;br /&gt;
&#039;&#039;&#039;0&#039;&#039;&#039;: Longpoll deaktiviert; alle 30s ein Shortpoll (Neuladen der gesamten Statusänderungen)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;1&#039;&#039;&#039;: Longpoll aktiv; geänderte Stati werden sofort aktualisiert, zusätzlich werden alle 15min die gesamten Statusänderungen geladen.&lt;br /&gt;
|-&lt;br /&gt;
|longpoll_type||websocket||websocket, ajax, 0||&lt;br /&gt;
&#039;&#039;&#039;websocket&#039;&#039;&#039;: Für die Aktualisierung der Daten wird das Websocket-Protokoll verwendet. Werden vom Browser keine Websockets unterstützt, gibt es einen automatischen Fallback auf Ajax.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ajax&#039;&#039;&#039;: Ajax wird für die Aktualisierung verwendet.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;0&#039;&#039;&#039;: Longpoll deaktiviert, Shortpoll wird verwendet.&lt;br /&gt;
|-&lt;br /&gt;
|longpoll_filter||.*||RegEx||Event-Filter. Kann verwendet werden, wenn z.B. Devices, die in FTUI angezeigt werden, in einem eigenen FHEM-Room sind.&lt;br /&gt;
|-&lt;br /&gt;
|longpoll_maxage||240||Integer||Kommen in diesem Zeitraum (Sekunden) keine Longpoll-Events bei FTUI an, wird die Verbindung als &amp;quot;disconnected&amp;quot; angesehen und ein neuer Verbindungsversuch wird gestartet.&lt;br /&gt;
|-&lt;br /&gt;
|shortpoll_interval||900||Integer||Zeitraum in Sekunden, nach dem ein vollständiger Refresh stattfindet&lt;br /&gt;
|-&lt;br /&gt;
|shortpoll_only_interval||30||Integer||Zeitraum in Sekunden, nach dem ein vollständiger Refresh stattfindet, sollte Longpoll deaktiviert sein&lt;br /&gt;
|-&lt;br /&gt;
|fhemweb_url||/fhem/||Integer||URL zu FHEM. Wird benötigt wenn FTUI auf einem anderen als dem FHEM Server läuft oder nicht im Standard-Pfad installiert ist. &lt;br /&gt;
Hinweis: Wenn FHEM auf einem anderem Server/Domain läuft muss man das &amp;quot;CORS&amp;quot; Attribut im FHEMWEB Modul (s.o.) auf 1 setzen, sonst bekommt man Cross Origin Fehler. &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Funktionalität===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!Parameter-Name!!Standard-Wert!!Mögliche Werte!!Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
|debug||0||0 - 5||Log-Level&lt;br /&gt;
|-&lt;br /&gt;
|toast||5||Integer||Anzahl an gleichzeitig angezeigten Toast-Nachrichten. Um keine anzuzeigen, ist der Wert auf 0 zu setzen.&lt;br /&gt;
|-&lt;br /&gt;
|toast_position||bottom-left||||Position im Browserfenster, wo die Toast-Nachrichten angezeigt werden.&lt;br /&gt;
|-&lt;br /&gt;
|lang||de||de||Sprache der Oberfläche (für z.B. Datums-/Zeitfunktionen)&lt;br /&gt;
|-&lt;br /&gt;
|username||||String||Benutzername für eine Basic-Authentifierung *&lt;br /&gt;
|-&lt;br /&gt;
|password||||String||Passwort für eine Basic-Authentifizierung *&lt;br /&gt;
|}&lt;br /&gt;
&#039;&#039;&#039;*&#039;&#039;&#039; Derzeit wird die Basic-Authentifizierung in Kombination mit WebSockets nicht unterstützt. Die Verwendung von &#039;&#039;&#039;longpoll=1&#039;&#039;&#039; (ajax) ist daher notwendig.&lt;br /&gt;
&lt;br /&gt;
===Toast-Nachrichten===&lt;br /&gt;
[[Datei:Ftui_toast.png|thumb|Toast-Nachrichten]]&lt;br /&gt;
Tablet-UI liefert Informationen darüber, was im Moment gerade passiert. Das geschieht über Toast-Nachrichten, die in der Standardeinstellung unten links im Browser auftauchen.&lt;br /&gt;
&lt;br /&gt;
Wird beispielsweise ein Gerät eingeschaltet, so erscheint eine kleine Nachricht mit dem abgesetzten Befehl. Auch Fehlermeldungen und Statusinformationen werden angezeigt. Ob überhaupt und was konkret angezeigt wird, richtet sich nach dem eingestellten Debug-Level (siehe oben). Beim Debug-Level 5 werden alle Nachrichten angezeigt, bei 0 keine.&lt;br /&gt;
&lt;br /&gt;
Die Position der Toast-Nachrichten kann über den Meta-Tag &amp;lt;code&amp;gt;meta name=&#039;toast_position&#039;&amp;lt;/code&amp;gt; festgelegt werden. Für oben-mittig müsste folgender Code eingefügt werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;meta name=&#039;toast_position&#039; content=&#039;top-center&#039;&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Möglich sind folgende Positionen:&lt;br /&gt;
* &amp;lt;code&amp;gt;top-left&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;top-right&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;bottom-left&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;bottom-right&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;top-center&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;bottom-center&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;mid-center&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die maximale Anzahl an Nachrichten, die gleichzeitig angezeigt werden können, lässt sich mit &amp;lt;code&amp;gt;meta name=&#039;toast&#039;&amp;lt;/code&amp;gt; Sind maximal 2 Nachrichten gewünscht, muss folgender Meta-Tag gesetzt werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;meta name=&#039;toast&#039; content=&#039;2&#039;&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Navigationsmethoden==&lt;br /&gt;
{{Todo|Dieser Abschnitt dient derzeit lediglich als Sammlung von Stichpunkten und muss vollständig überarbeitet werden.}} &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Unterschied zwischen Pagetab und Pagebutton:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Pagetab:&#039;&#039;&#039; Ganze Seite austauschen -&amp;gt; Menü muss auf jede Seite&lt;br /&gt;
[[FTUI_Widget_Pagetab]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Pagebutton:&#039;&#039;&#039; Teil der Seite austauschen -&amp;gt; Menü nur in erster Seite&lt;br /&gt;
[[FTUI_Widget_Pagebutton]]&lt;br /&gt;
&lt;br /&gt;
==Gestaltung==&lt;br /&gt;
===Layout-Optionen===&lt;br /&gt;
* [[FTUI Layout Gridster|Gridster]]&lt;br /&gt;
* [[FTUI Layout Flex|Flex]]&lt;br /&gt;
* [[FTUI Layout Sheet|Tabelle]]&lt;br /&gt;
* [[FTUI Layout Row|Reihen]]&lt;br /&gt;
&lt;br /&gt;
=== Farben ===&lt;br /&gt;
Es besteht die Möglichkeit, die Farbwerte in hexadezimaler Form, als RGB-Wert oder mit dem Farbnamen anzugeben. Zum Beispiel: &lt;br /&gt;
&lt;br /&gt;
*HEX: #ADD8E6&lt;br /&gt;
*RBG: rgb(173, 216, 230)&lt;br /&gt;
*Namen: lightblue&lt;br /&gt;
&lt;br /&gt;
Knallige Farben wie &#039;&#039;&#039;&amp;lt;span style=&amp;quot;color: #ff0000;&amp;quot;&amp;gt;#ff0000&amp;lt;/span&amp;gt;&#039;&#039;&#039; für Rot oder &#039;&#039;&#039;&amp;lt;span style=&amp;quot;color: #00ff00;&amp;quot;&amp;gt;#00ff00&amp;lt;/span&amp;gt;&#039;&#039;&#039; für Grün sollten vermieden werden.&lt;br /&gt;
Es ist besser unterhalb von #D0 (208) für die Grundfarben zu bleiben.&lt;br /&gt;
&lt;br /&gt;
Empfohlene Farben sind z.B.:&lt;br /&gt;
&lt;br /&gt;
*Orange: &amp;lt;span style=&amp;quot;color: #aa6900;&amp;quot;&amp;gt;#aa6900&amp;lt;/span&amp;gt;&lt;br /&gt;
*Rot: &amp;lt;span style=&amp;quot;color: #ad3333;&amp;quot;&amp;gt;#ad3333&amp;lt;/span&amp;gt;&lt;br /&gt;
*Grün: &amp;lt;span style=&amp;quot;color: #32a054;&amp;quot;&amp;gt;#32a054&amp;lt;/span&amp;gt;&lt;br /&gt;
*Blau: &amp;lt;span style=&amp;quot;color: #6699FF;&amp;quot;&amp;gt;#6699FF&amp;lt;/span&amp;gt;&lt;br /&gt;
*Grau: &amp;lt;span style=&amp;quot;color: #8C8C8C;&amp;quot;&amp;gt;#8C8C8C&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hilfreich bei der Suche nach den Farbwerten ist zum Beispiel der Color-Picker auf dieser Seite: http://www.colorpicker.com. Für die Suche nach Farben, die einen guten Kontrast bilden, diese Webseite: http://vanisoft.pl/~lopuszanski/public/colors/&lt;br /&gt;
&lt;br /&gt;
Im Ordner &#039;&#039;css&#039;&#039; der FTUI Installation finden sich einige vorbereitete Farbschemas. Diese können mit einem zusätzlichen Eintrag im &amp;lt;nowiki&amp;gt;&amp;lt;head&amp;gt;&amp;lt;/nowiki&amp;gt;-Bereich der FTUI-Seite(n) aktiviert werden.&lt;br /&gt;
&lt;br /&gt;
Hier am Beispiel eines blauen Farbschemas:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
   [...]&lt;br /&gt;
   &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;/fhem/tablet/css/fhem-blue-ui.css&amp;quot; /&amp;gt;&lt;br /&gt;
   [...]&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Schema-Dateien ändern alle Widgets. Einzelne Widgets können durch Hinzufügen der jeweiligen [[#CSS-Klassen|CSS-Klasse]] geändert werden.&lt;br /&gt;
&lt;br /&gt;
===CSS-Styles===&lt;br /&gt;
Das Layout und das Aussehen des UI kann durch diverse vorgegebene CSS-Klassen beeinflusst werden. Die verfügbaren Klassen sind im Abschnitt [[#CSS-Klassen|CSS-Klassen]] aufgeführt.&lt;br /&gt;
&lt;br /&gt;
Soll das Aussehen des UI durch eigene CSS-Klassen oder durch Überschreiben der vorhandenen verändert werden, kann eine eigene CSS-Datei erstellt werden, die dann bei einem eventuellen Update von FTUI nicht überschrieben wird. Diese Datei muss den Dateinamen &#039;&#039;&#039;fhem-tablet-ui-user.css&#039;&#039;&#039; haben und im Ordner &#039;&#039;&#039;/fhem/tablet/css&#039;&#039;&#039; abgelegt werden. Sie wird dann beim Aufruf von FTUI automatisch mitgeladen.&lt;br /&gt;
&lt;br /&gt;
=== CSS-Klassen ===&lt;br /&gt;
Nicht alle Widgets unterstützen alle hier angegebenen Klassen. Welche genau unterstützt werden, kann auf der jeweiligen Widget-Seite nachgelesen werden.&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: left;&amp;quot;|sheet/row/cell-Layout&lt;br /&gt;
|-&lt;br /&gt;
!class=&amp;quot;mw-collapsible-content&amp;quot;|Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|sheet}}{{FTUI Klasse|row}}{{FTUI Klasse|cell}}{{FTUI Klasse|cell-1-x}}{{FTUI Klasse|cell-x}}{{FTUI Klasse|left-align}}{{FTUI Klasse|right-align}}{{FTUI Klasse|bottom-align}}{{FTUI Klasse|top-align}}{{FTUI Klasse|center-align}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: left;&amp;quot;|row/col-Layout&lt;br /&gt;
|-&lt;br /&gt;
!class=&amp;quot;mw-collapsible-content&amp;quot;|Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|col}}{{FTUI Klasse|col-1-x}}{{FTUI Klasse|col-x}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: left;&amp;quot;|hbox/vbox-Layout&lt;br /&gt;
|-&lt;br /&gt;
!class=&amp;quot;mw-collapsible-content&amp;quot;|Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|vbox}}{{FTUI Klasse|hbox}}{{FTUI Klasse|card}}{{FTUI Klasse|phone-width}}{{FTUI Klasse|full-height}}{{FTUI Klasse|full-width}}{{FTUI Klasse|grow-0}}{{FTUI Klasse|grow-1}}{{FTUI Klasse|grow-2}}{{FTUI Klasse|grow-x}}{{FTUI Klasse|items-top}}{{FTUI Klasse|items-center}}{{FTUI Klasse|items-bottom}}{{FTUI Klasse|items-space-between}}{{FTUI Klasse|items-space-around}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: left;&amp;quot;|Generelle Klassen für die Positionierung&lt;br /&gt;
|-&lt;br /&gt;
!class=&amp;quot;mw-collapsible-content&amp;quot;|Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|inline}}{{FTUI Klasse|newline}}{{FTUI Klasse|top-space}}{{FTUI Klasse|top-space-2x}}{{FTUI Klasse|top-space-3x}}{{FTUI Klasse|left-space}}{{FTUI Klasse|left-space-2x}}{{FTUI Klasse|left-space-3x}}{{FTUI Klasse|right-space}}{{FTUI Klasse|right-space-2x}}{{FTUI Klasse|right-space-3x}}{{FTUI Klasse|top-narrow}}{{FTUI Klasse|top-narrow-2x}}{{FTUI Klasse|top-narrow-10}}{{FTUI Klasse|left-narrow}}{{FTUI Klasse|left-narrow-2x}}{{FTUI Klasse|left-narrow-3x}}{{FTUI Klasse|right-narrow}}{{FTUI Klasse|right-narrow-2x}}{{FTUI Klasse|right-narrow-3x}}{{FTUI Klasse|centered}}{{FTUI Klasse|wider}}{{FTUI Klasse|narrow}}{{FTUI Klasse|fullsize}}{{FTUI Klasse|compressed}}{{FTUI Klasse|height-narrow}}{{FTUI Klasse|w1x}}{{FTUI Klasse|w2x}}{{FTUI Klasse|w3x}}{{FTUI Klasse|maxw40}}{{FTUI Klasse|doublebox-v}}{{FTUI Klasse|doublebox-h}}{{FTUI Klasse|triplebox-v}}{{FTUI Klasse|right}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: left;&amp;quot;|Vordergrundfarben&lt;br /&gt;
|-&lt;br /&gt;
!class=&amp;quot;mw-collapsible-content&amp;quot;|Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|red}}{{FTUI Klasse|green}}{{FTUI Klasse|blue}}{{FTUI Klasse|lightblue}}{{FTUI Klasse|orange}}{{FTUI Klasse|gray}}{{FTUI Klasse|lightgray}}{{FTUI Klasse|white}}{{FTUI Klasse|black}}{{FTUI Klasse|mint}}{{FTUI Klasse|yellow}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: left;&amp;quot;|Hintergrundfarben&lt;br /&gt;
|-&lt;br /&gt;
!class=&amp;quot;mw-collapsible-content&amp;quot;|Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|bg-red}}{{FTUI Klasse|bg-green}}{{FTUI Klasse|bg-blue}}{{FTUI Klasse|bg-lightblue}}{{FTUI Klasse|bg-orange}}{{FTUI Klasse|bg-gray}}{{FTUI Klasse|bg-lightgray}}{{FTUI Klasse|bg-white}}{{FTUI Klasse|bg-black}}{{FTUI Klasse|bg-mint}}{{FTUI Klasse|bg-yellow}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: left;&amp;quot;|Rahmen&lt;br /&gt;
|-&lt;br /&gt;
!class=&amp;quot;mw-collapsible-content&amp;quot;|Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|verticalLine}}{{FTUI Klasse|border-black}}{{FTUI Klasse|border-white}}{{FTUI Klasse|border-orange}}{{FTUI Klasse|border-red}}{{FTUI Klasse|border-green}}{{FTUI Klasse|border-mint}}{{FTUI Klasse|border-lightblue}}{{FTUI Klasse|border-blue}}{{FTUI Klasse|border-gray}}{{FTUI Klasse|border-yellow}}{{FTUI Klasse|border-lightgray}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: left;&amp;quot;|Größen&lt;br /&gt;
|-&lt;br /&gt;
!class=&amp;quot;mw-collapsible-content&amp;quot;|Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|mini}}{{FTUI Klasse|tiny}}{{FTUI Klasse|small}}{{FTUI Klasse|normal}}{{FTUI Klasse|large}}{{FTUI Klasse|big}}{{FTUI Klasse|bigger}}{{FTUI Klasse|tall}}{{FTUI Klasse|great}}{{FTUI Klasse|grande}}{{FTUI Klasse|gigantic}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: left;&amp;quot;|Schriftstil&lt;br /&gt;
|-&lt;br /&gt;
!class=&amp;quot;mw-collapsible-content&amp;quot;|Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|thin}}{{FTUI Klasse|bold}}{{FTUI Klasse|darker}}{{FTUI Klasse|truncate}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot; style=&amp;quot;width: 100%;&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; style=&amp;quot;text-align: left;&amp;quot;|Sonstiges&lt;br /&gt;
|-&lt;br /&gt;
!class=&amp;quot;mw-collapsible-content&amp;quot;|Klasse!!Beschreibung&lt;br /&gt;
{{FTUI Klasse|blank}}{{FTUI Klasse|transparent}}{{FTUI Klasse|half-transparent}}{{FTUI Klasse|blurry}}{{FTUI Klasse|shake}}{{FTUI Klasse|fail-shake}}{{FTUI Klasse|marquee}}{{FTUI Klasse|icon round}}{{FTUI Klasse|icon square}}{{FTUI Klasse|readonly}}{{FTUI Klasse|blink}}{{FTUI Klasse|rotate-90}}{{FTUI Klasse|horizontal}}{{FTUI Klasse|circleborder}}{{FTUI Klasse|autohide}}{{FTUI Klasse|notransmit}}{{FTUI Klasse|tap}}{{FTUI Klasse|FS20}}{{FTUI Klasse|value}}{{FTUI Klasse|novalue}}{{FTUI Klasse|timestamp}}{{FTUI Klasse|percent}}{{FTUI Klasse|nocache}}{{FTUI Klasse|fade}}{{FTUI Klasse|rotate}}{{FTUI Klasse|nolabels}}{{FTUI Klasse|default}}{{FTUI Klasse|prefetch}}{{FTUI Klasse|circulate}}{{FTUI Klasse|valueonly}}{{FTUI Klasse|positiononly}}{{FTUI Klasse|lineIndicator}}{{FTUI Klasse|barIndicator}}{{FTUI Klasse|roundIndicator}}{{FTUI Klasse|dim-tick}}{{FTUI Klasse|dim-front}}{{FTUI Klasse|dim-back}}{{FTUI Klasse|hue-tick}}{{FTUI Klasse|hue-front}}{{FTUI Klasse|hue-back}}{{FTUI Klasse|warn}}{{FTUI Klasse|activate}}{{FTUI Klasse|labelright}}{{FTUI Klasse|interlock}}{{FTUI Klasse|keepopen}}{{FTUI Klasse|noshade}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Icons ===&lt;br /&gt;
FTUI bringt einige Icons-&amp;quot;Schriftarten&amp;quot; mit, die für die Darstellung genützt werden können. Diese werden automatisch beim Start des UI eingebunden, sobald ein entsprechendes Icon-Präfix im Code der Seite vorkommt.&lt;br /&gt;
&lt;br /&gt;
Verfügbare Icon-Schriftarten sind:&lt;br /&gt;
* Eingebaute Icons &#039;&#039;ftui-window&#039;&#039; und &#039;&#039;ftui-door&#039;&#039;. Präfix &#039;&#039;&#039;ftui-&#039;&#039;&#039;. Beispiel: &amp;lt;code&amp;gt;data-icon=&amp;quot;ftui-door&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
* [http://fontawesome.io/icons/ Font-Awesome]: Mehr als 500 Icons zur Auswahl. Präfix &#039;&#039;&#039;fa-&#039;&#039;&#039;. Beispiel: &amp;lt;code&amp;gt;data-icon=&amp;quot;fa-volume-up&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
* [https://material.io/icons/ Material Icons]: Mehr als 900 Icons zur Auswahl. Präfix &#039;&#039;&#039;mi-&#039;&#039;&#039;. Beispiel: &amp;lt;code&amp;gt;data-icon=&amp;quot;mi-local_gas_station&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
* FHEM und OpenAutomation Icons: Präfix &#039;&#039;&#039;fs-&#039;&#039;&#039; und &#039;&#039;&#039;oa-&#039;&#039;&#039;. Beispiel: &amp;lt;code&amp;gt;data-icon=&amp;quot;oa-secur_locked&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
* [https://erikflowers.github.io/weather-icons/ Weather-Icons]: Präfix &#039;&#039;&#039;wi &#039;&#039;&#039;. Beispiel: &amp;lt;code&amp;gt;data-icon=&amp;quot;wi wi-day-rain-mix&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternativ können auch Bilder Icons (bspw. png) über CSS verwendet werden. Bspw:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html5&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
  &amp;lt;style type=&amp;quot;text/css&amp;quot;&amp;gt;&lt;br /&gt;
        .logo-fhem {&lt;br /&gt;
            background: url(https://wiki.fhem.de/fhemlogo.png) no-repeat;&lt;br /&gt;
            width: 120px;&lt;br /&gt;
            height: 132px;&lt;br /&gt;
            background-size: contain;&lt;br /&gt;
        }&lt;br /&gt;
  &amp;lt;/style&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
  &amp;lt;div data-type=&amp;quot;symbol&amp;quot; data-icon=&amp;quot;logo-fhem&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Widgets ==&lt;br /&gt;
===Allgemeine Attribute===&lt;br /&gt;
Jedes Widget kann über verschiedene Attribute konfiguriert werden. Folgende Attribute gelten für alle Widgets:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+allgemeine Attribute&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-type&lt;br /&gt;
|Widget-Typ&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-device&lt;br /&gt;
|FHEM-Name des Gerätes (mit dem Befehl &#039;list&#039; bekommt man im FHEM die kpl. Liste)&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |class&lt;br /&gt;
|CSS-Klassen für Aussehen und Formatierung des Widgets&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Daten Empfangen&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-get&lt;br /&gt;
|Reading Name&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-get-on&lt;br /&gt;
|Wert für den Status on&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-get-off&lt;br /&gt;
|Wert für den Status off&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Daten Senden&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-set&lt;br /&gt;
|Reading Name&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-set-on&lt;br /&gt;
|Wert für den Status on&lt;br /&gt;
|-&lt;br /&gt;
!align=&amp;quot;right&amp;quot; |data-set-off&lt;br /&gt;
|Wert für den Status off&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Widget-spezifische Attribute können auf der jeweiligen Widget-Seite nachgelesen werden.&lt;br /&gt;
&lt;br /&gt;
=== Integrierte Widgets ===&lt;br /&gt;
Folgende Widgets sind direkt in FHEM Tablet UI integriert und können &amp;quot;out of the box&amp;quot; verwendet werden.&lt;br /&gt;
&lt;br /&gt;
* [[FTUI Widget Button|button]]: Variante der push und switch Widgets, die entweder einen URL ansteuern oder einen FHEM-Befehl absetzen kann&lt;br /&gt;
* [[FTUI Widget Checkbox|checkbox]]: Umschalter zwischen zwei definierten Zuständen&lt;br /&gt;
* [[FTUI Widget Circlemenu|circlemenu]]: Mehrere Widgets hinter einem Widget verborgen, trotz des &#039;circle&#039; im Namen kann das Menue jetzt auch horizontal oder vertikal ausgeklappt werden &lt;br /&gt;
* [[FTUI Widget Clock|clock]]: Stellt eine einfach Uhr zur Verfügung&lt;br /&gt;
* [[FTUI Widget Colorwheel|colorwheel]]: Farbpalette zur Auswahl von Farben&lt;br /&gt;
* [[FTUI Widget Controlbutton|controlbutton]]: iOS-ähnlicher Button zum Schalten zwischen zwei Zuständen (z.B. on / off)&lt;br /&gt;
* [[FTUI Widget Controller|controller]]: iOS-ähnlicher vertikaler Schieberegler zum Einstellen eines Wertes&lt;br /&gt;
* [[FTUI Widget Datetimepicker|datetimepicker]]: Erstellt eine Auswahl für Datum/Uhrzeit&lt;br /&gt;
* [[FTUI Widget Departure|departure]]: Abfahrtszeiten öffentlicher Verkehrsmittel&lt;br /&gt;
* [[FTUI Widget Dimmer|dimmer]]: Ein-/Aus-Button mit integriertem Schieberegler für z.B. einen Dim-Wert&lt;br /&gt;
* [[FTUI Widget Eventmonitor|eventmonitor]]:&lt;br /&gt;
* [[FTUI Widget Homestatus|homestatus]]: Auswahl für vier oder fünf definierte Stati eines Objects (z.B.: FHEM Residents)&lt;br /&gt;
* [[FTUI Widget Html|html]]:&lt;br /&gt;
* [https://github.com/nesges/Widgets-for-fhem-tablet-ui/wiki/iframe iframe]: Widget zum Einbinden externer Inhalte in einem Iframe&lt;br /&gt;
* [[FTUI Widget Image|image]]: Zeigt ein Bild, dessen URL fest vorgegeben oder aus einem Device-Reading gelesen werden kann&lt;br /&gt;
* [[FTUI Widget Input|input]]: Erstellen eines Texteingabefeldes&lt;br /&gt;
* [https://github.com/nesges/Widgets-for-fhem-tablet-ui/wiki/joinedlabel joinedlabel]: verbindet mehrere Readings zu einem Feld&lt;br /&gt;
* [[FTUI Widget Klimatrend|klimatrend]]: wandelt Daten aus dem statistics-Modul in einen Pfeil um, der den aktuellen Trend anzeigt&lt;br /&gt;
* [[FTUI Widget Knob|knob]]: Erstellt einen Statusbalken auf einer Kreisbahn&lt;br /&gt;
* [[FTUI Widget Label|label]]: Reading als Text anzeigen&lt;br /&gt;
* [[FTUI Widget Level|level]]: Vertikale oder horizontale Leiste zur Anzeige von Werten zwischen einem Minimal- und einem Maximalwert&lt;br /&gt;
* [[FTUI Widget Link|link]]: Erstellt einen Link oder Button zum Aufrufen von URLs oder Senden von Befehlen an FHEM&lt;br /&gt;
* [[FTUI Widget Medialist|medialist]]:&lt;br /&gt;
* [[FTUI Widget Multistatebutton|multistatebutton]]: Variante des push-Widgets, welches den set-Befehl abhängig vom gelesenen Status ändert&lt;br /&gt;
* [[FTUI Widget Notify|notify]]: Blendet ein Hinweisfenster im Browser ein&lt;br /&gt;
* [[FTUI Widget Pagebutton|pagebutton]]: Button, mit dem auf andere Seiten gesprungen werden kann. Eignet sich gut für eine Navigation&lt;br /&gt;
* [[FTUI Widget Pagetab|pagetab]]: Tauscht den Inhalt einer Seite durch den einer anderen. Eignet sich gut für ein Navigationsmenü&lt;br /&gt;
* [[FTUI Widget Playstream|playstream]]: Abspielen eines Webradio-Streams per Button&lt;br /&gt;
* [[FTUI Widget Popup|popup]]: Öffnet ein Popup nach einem Klick auf ein Widget oder HTML-Element &lt;br /&gt;
* [[FTUI Widget Progress|progress]]: Zeigt einen Prozentwert in Form einer runden Fortschrittsleiste&lt;br /&gt;
* [[FTUI_Widget_Push|push]]: Button, mir dem ein Befehl an FHEM gesendet werden kann&lt;br /&gt;
* [[FTUI Widget Range|range]]: Erstellt vertikale Balken, die einen Wertebereich in unterschiedlichen Farben darstellen&lt;br /&gt;
* [[FTUI Widget Readingsgroup|readingsgroup]]: Zeigt eine Readingsgroup an, wie sie in FHEM definiert wurde&lt;br /&gt;
* [[FTUI Widget Rotor|rotor]]: Animiertes Umschalten von zwei oder mehr Widgets an einer Position&lt;br /&gt;
* [[FTUI Widget Scale|scale]]: Vertikale oder horizontale Leiste zur Anzeige von Werten zwischen einem Minimal- und einem Maximalwert&lt;br /&gt;
* [[FTUI_Widget_Select|select]]: Combobox, die eine Liste an Werten zur Auswahl anzeigt&lt;br /&gt;
* [https://github.com/nesges/Widgets-for-fhem-tablet-ui/wiki/settimer settimer]: Zum Anzeigen und Einstellen einer Uhrzeit&lt;br /&gt;
* [[FTUI Widget Simplechart|simplechart]]: Einfaches XY-Diagramm zur Anzeige eines Wertes, der direkt aus einem FHEM-Logfile gelesen wird&lt;br /&gt;
* [[FTUI Widget Slideout|slideout]]:&lt;br /&gt;
* [[FTUI Widget Slider|slider]]: Vertikaler Schieberegler zum Einstellen eines Wertes &lt;br /&gt;
* [[FTUI Widget Spinner|spinner]]: Element um Werte durch Drücken auf Plus- und Minus- oder Höher-/Tiefer-Icons zu ändern&lt;br /&gt;
* [[FTUI Widget Swiper|swiper]]: Bietet die Möglichkeit, durch Wischen zwischen verschiedenen Seiten zu wechseln&lt;br /&gt;
* [[FTUI Widget Switch|switch]]: Button um zwischen zwei Zuständen zu schalten (z.B. on / off)&lt;br /&gt;
* [[FTUI Widget Symbol|symbol]]: Status eines Devices als Symbol darstellen (z.B. Fenster offen)&lt;br /&gt;
* [[FTUI Widget Thermostat|thermostat]]: Anzeige für Heizungsthermostate, mit der die gewünschte Temperatur eingestellt werden kann&lt;br /&gt;
* [[FTUI Widget Volume|volume]]: Einstellscheibe zur Änderung eines einzelnen Wertes&lt;br /&gt;
* [[FTUI Widget Weather|weather]]: Wettersymbol anzeigen&lt;br /&gt;
* [[FTUI Widget WindDirection|wind_direction]]: Anzeige der Windrichtung auf einer Windrose&lt;br /&gt;
&lt;br /&gt;
===3rd Party Widgets===&lt;br /&gt;
Für diese Widgets kann nicht sichergestellt werden, dass sie mit der jeweils aktuellen Version von FTUI funktionieren.&lt;br /&gt;
* [[FTUI Widget Agenda|agenda]]: Zeigt Kalendereinträge in einer Listenform an&lt;br /&gt;
* [[FTUI Widget Calview|calview]]: Zeigt Einträge aus einem [[CALVIEW]]-Device an&lt;br /&gt;
* [[FTUI Widget Chart|chart]]: Diagramm mit ähnlichen Möglichkeiten wie die FHEM-Plots&lt;br /&gt;
* [[FTUI Widget Classchanger|classchanger]]: Ändert seine CSS-Klassen je nach Status eines Devices&lt;br /&gt;
* [[FTUI Widget Clicksound|clicksound]]: Mit dem Widget &amp;quot;clicksound&amp;quot; können Sounds an Click-Events von Elementen gebunden werden.&lt;br /&gt;
* [[FTUI Widget Filelog|filelog]]:&lt;br /&gt;
* [[FTUI Widget Fullcalview|fullcalview]]:&lt;br /&gt;
* [[FTUI Widget Gds|gds]]:&lt;br /&gt;
* [https://forum.fhem.de/index.php/topic,78379.msg703359.html#msg703359 gmaps]: Kartendarstellung mit Google Maps API&lt;br /&gt;
* [[FTUI Widget Highchart|highchart]]:&lt;br /&gt;
* [[FTUI Widget Highchart3d|highchart3d]]:&lt;br /&gt;
* [https://github.com/nesges/Widgets-for-fhem-tablet-ui/wiki/itunes_artwork itunes_artwork]: itunes_artwork durchsucht die iTunes-Datenbank anhand eines Arrays von beliebigen Suchworten nach einem Cover-Artwork und zeigt dieses an. &lt;br /&gt;
* [https://github.com/nesges/Widgets-for-fhem-tablet-ui/wiki/javascript javascript]: Ermöglicht die Ausführung beliebigen Javascript-Codes aus einem Reading.&lt;br /&gt;
* [https://github.com/nesges/Widgets-for-fhem-tablet-ui/wiki/kodinowplaying kodinowplaying]: zeigt Informationen zu grade in KODI gespielten Medien in Form eines Labels an.&lt;br /&gt;
* [[FTUI Widget Loading|loading]]:&lt;br /&gt;
* [[FTUI Widget Meteogram|meteogram]]:&lt;br /&gt;
* [https://github.com/nesges/Widgets-for-fhem-tablet-ui/wiki/mpdnowplaying mpdnowplaying]: Zeigt Titelinformationen eines per MPD-Modul angebundenen Music Player Daemon an.&lt;br /&gt;
* [https://forum.fhem.de/index.php/topic,79283.msg712855.html#msg712855 pinpad]: Pinpad für z.B. eine Alarmanlage&lt;br /&gt;
* [https://forum.fhem.de/index.php/topic,76643.msg685472.html#msg685472 postme]: Liste des PostMe-Devices anzeigen&lt;br /&gt;
* [https://github.com/nesges/Widgets-for-fhem-tablet-ui/wiki/reload reload]: auslösen eine Pagereloads&lt;br /&gt;
* [[FTUI Widget Screensaver|screensaver]]:&lt;br /&gt;
* [https://forum.fhem.de/index.php/topic,73497.0.html scrolllabel]: Texte in Laufschrift darstellen&lt;br /&gt;
* [[FTUI Widget Svgplot|svgplot]]:&lt;br /&gt;
* [https://forum.fhem.de/index.php?topic=82883.msg750237#msg750237 todoist]: einfaches widget für todoist&lt;br /&gt;
* [[FTUI Widget Tts|tts]]: Sprachausgabe eines Textes aus einem Reading auf dem Endgerät.&lt;br /&gt;
* [[FTUI Widget UWZ|uwz]]: Anzeige der Warnungen der Unwetterzentrale&lt;br /&gt;
* [[FTUI Widget Wakeup|wakeup]]:&lt;br /&gt;
* [https://github.com/svenson08/ftui-weekdaytimer-widget wdtimer]: Visualisierung des [[WeekdayTimer]] Modul&lt;br /&gt;
* [[FTUI Widget Weekprofile|weekprofile]]: Visualisierung des [[weekprofile]] Moduls&lt;br /&gt;
&lt;br /&gt;
==Templates==&lt;br /&gt;
Kommt ein bestimmtes &amp;quot;Code-Fragment&amp;quot; auf mehreren Seiten oder öfter pro Seite vor, bietet FTUI die Option, Templates zu erstellen. Diese werden einmal gebaut und können dann mit dem Attribut &#039;&#039;&#039;data-template&#039;&#039;&#039; nach Belieben in eine Seite eingefügt werden. Dabei besteht auch die Möglichkeit, Variablen zu verwenden.&lt;br /&gt;
&lt;br /&gt;
Die Variablennamen sollten möglichst eindeutig und unverwechselbar gewählt werden, da bei der Verwendung von Templates im Prinzip Suchen &amp;amp; Ersetzen angewendet wird. Verwendet man beispielsweise die Variablen &#039;&#039;&#039;dev:Thermostat_Kueche&#039;&#039;&#039; und &#039;&#039;&#039;dev_temp:temperatue&#039;&#039;&#039;, so kann es passieren, dass die Ergebnisse im erzeugten Code dann &#039;&#039;&#039;Thermostat_Kueche&#039;&#039;&#039; und &#039;&#039;&#039;Thermostat_Kueche_temp&#039;&#039;&#039; lauten, statt wie gewünscht &#039;&#039;&#039;Thermostat_Kueche&#039;&#039;&#039; und &#039;&#039;&#039;temperature&#039;&#039;&#039;. Um dies zu vermeiden, sollten die Variablen besser &#039;&#039;&#039;device:Thermostat_Kueche&#039;&#039;&#039; und &#039;&#039;&#039;temp:temperatue&#039;&#039;&#039; lauten.&lt;br /&gt;
&lt;br /&gt;
Im Folgenden ein paar Beispiele, wie Templates verwendet werden können.&lt;br /&gt;
&lt;br /&gt;
===Einzelnes Widget===&lt;br /&gt;
Soll ein Widget an mehreren Stellen in exakt der selben Ausführung eingebunden werden, kann diese Widget in einer eigenen Datei erstellt und diese dann auf den Zielseiten automatisch mitgeladen werden.&lt;br /&gt;
&lt;br /&gt;
;Template-Seite&lt;br /&gt;
Die Template-Seite soll in diesem Beispiel &#039;&#039;template_symbol.html&#039;&#039; genannt werden. Diese wird daher zuerst im FTUI-Verzeichnis erstellt.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;symbol&amp;quot;&lt;br /&gt;
     data-device=&amp;quot;dummy1&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Haupt-Seite&lt;br /&gt;
Die oben erstellte Template-Seite kann nun in jeder gewünschten Seite eingebunden werden.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; highlight=&amp;quot;6&amp;quot;&amp;gt;&lt;br /&gt;
[...]&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;gridster&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;ul&amp;gt;&lt;br /&gt;
      &amp;lt;li data-row=&amp;quot;1&amp;quot; data-col=&amp;quot;1&amp;quot; data-sizey=&amp;quot;1&amp;quot; data-sizex=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
         &amp;lt;div data-template=&amp;quot;template_symbol.html&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
      &amp;lt;/li&amp;gt;&lt;br /&gt;
   &amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
[...]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Gridster-Element===&lt;br /&gt;
Natürlich kann auch ein ganzes Gridster-Element - in diesem Fall ein Menü - als Template eingebunden werden.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;li data-row=&amp;quot;1&amp;quot; data-col=&amp;quot;1&amp;quot; data-sizex=&amp;quot;1&amp;quot; data-sizey=&amp;quot;4&amp;quot; data-template=&amp;quot;menu.html&amp;quot;&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Widget-Gruppen ===&lt;br /&gt;
Die Template-Datei des [[#Einzelnes Widget|ersten Beispiels]] kann natürlich auch mehrere Widgets auf einmal enthalten.&lt;br /&gt;
&lt;br /&gt;
=== Verwendung von Variablen ===&lt;br /&gt;
==== Einfaches Beispiel ====&lt;br /&gt;
Oft wird ein und dasselbe Widget für verschiedenen Devices verwendet. Um nicht für jedes Device das Widget neu kopieren zu müssen (bzw. bei Änderungen alle Seiten ausbessern zu müssen), kann ein Template verwendet werden, dem einfach per Parameter mitgeteilt wird, von welchem Device es gerade die Daten empfangen soll.&lt;br /&gt;
&lt;br /&gt;
In diesem Beispiel wird ein Template erzeugt, dass nur die Temperatur verschiedenen Thermostate mittels eines [[FTUI Widget Label|Label-Widgets]] anzeigt.&lt;br /&gt;
&lt;br /&gt;
;Template-Seite&lt;br /&gt;
Die Template-Seite enthält nur ein einfaches Label-Widget und wird in diesem Beispiel &#039;&#039;template_label.html&#039;&#039; genannt. Um sie für mehrere Devices verwenden zu können, wird im Attribut &#039;&#039;&#039;data-device&#039;&#039;&#039; der Name des eigentlichen Devices durch den Parameter &#039;&#039;&#039;par01&#039;&#039;&#039; ersetzt.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot; highlight=&amp;quot;2&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot;&lt;br /&gt;
     data-device=&amp;quot;par01&amp;quot;&lt;br /&gt;
     data-get=&amp;quot;measured-temp&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Haupt-Seite&lt;br /&gt;
Auf der Haupt-Seite wird die Template-Seite mit dem Attribut &#039;&#039;&#039;data-template&#039;&#039;&#039; eingebunden und ihr via Attribut &#039;&#039;&#039;data-parameter&#039;&#039;&#039; das jeweils gewünschte Device übergeben.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
[...]&lt;br /&gt;
&amp;lt;div data-template=&amp;quot;template_label.html&amp;quot; data-parameter=&#039;{&amp;quot;par01&amp;quot;:&amp;quot;Thermostat1&amp;quot;}&#039;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-template=&amp;quot;template_label.html&amp;quot; data-parameter=&#039;{&amp;quot;par01&amp;quot;:&amp;quot;Thermostat2&amp;quot;}&#039;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div data-template=&amp;quot;template_label.html&amp;quot; data-parameter=&#039;{&amp;quot;par01&amp;quot;:&amp;quot;Thermostat3&amp;quot;}&#039;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
[...]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Wetter-Slider mit Template ====&lt;br /&gt;
In diesem Beispiel wird ein [[FTUI Widget Slider|Slider-Widget]] erstellt, welches die verschiedenen Tage eines Wetterberichtes anzeigt. Dabei wird für den Wetterbericht des jeweiligen Tages immer dasselbe Template verwendet um nicht für jeden Tag ein eigenes Widget schreiben zu müssen.&lt;br /&gt;
&lt;br /&gt;
;Template-Seite&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;left&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;AgroWeather&amp;quot; data-get=&amp;quot;par01&amp;quot; data-unit=&amp;quot;&amp;amp;deg;C&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
   &amp;lt;div class=&amp;quot;inline&amp;quot;&amp;gt;&lt;br /&gt;
       &amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;AgroWeather&amp;quot; data-get=&amp;quot;par02&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
       &amp;lt;div data-type=&amp;quot;weather&amp;quot; data-device=&amp;quot;AgroWeather&amp;quot; data-get=&amp;quot;par02&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
       min:&amp;amp;nbsp;&amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;AgroWeather&amp;quot; data-get=&amp;quot;par03&amp;quot; data-unit=&amp;quot;&amp;amp;deg;C&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
   &amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;left&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;AgroWeather&amp;quot; data-get=&amp;quot;par04&amp;quot; data-substitution=&amp;quot;toDate().eeee()+&#039;,&#039;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
   &amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;AgroWeather&amp;quot; data-get=&amp;quot;par04&amp;quot; data-substitution=&amp;quot;toDate().ddmm()&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Haupt-Seite&lt;br /&gt;
In der Haupt-Seite wird das Template dann für jede Slider-Seite eingebunden und das Reading für den jeweiligen Tag via Parameter übergeben.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
[...]&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;swiper&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
   &amp;lt;li data-template=&amp;quot;templates/wetter.html&amp;quot; data-parameter=&#039;{&amp;quot;par01&amp;quot;:&amp;quot;fc0_tempMax&amp;quot;,&amp;quot;par02&amp;quot;:&amp;quot;fc0_weatherDay&amp;quot;,&amp;quot;par03&amp;quot;:&amp;quot;fc0_tempMin&amp;quot;,&amp;quot;par04&amp;quot;:&amp;quot;fc0_date&amp;quot;}&#039;&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
   &amp;lt;li data-template=&amp;quot;templates/wetter.html&amp;quot; data-parameter=&#039;{&amp;quot;par01&amp;quot;:&amp;quot;fc1_tempMax&amp;quot;,&amp;quot;par02&amp;quot;:&amp;quot;fc1_weatherDay&amp;quot;,&amp;quot;par03&amp;quot;:&amp;quot;fc1_tempMin&amp;quot;,&amp;quot;par04&amp;quot;:&amp;quot;fc1_date&amp;quot;}&#039;&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
   &amp;lt;li data-template=&amp;quot;templates/wetter.html&amp;quot; data-parameter=&#039;{&amp;quot;par01&amp;quot;:&amp;quot;fc2_tempMax&amp;quot;,&amp;quot;par02&amp;quot;:&amp;quot;fc2_weatherDay&amp;quot;,&amp;quot;par03&amp;quot;:&amp;quot;fc2_tempMin&amp;quot;,&amp;quot;par04&amp;quot;:&amp;quot;fc2_date&amp;quot;}&#039;&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
   &amp;lt;li data-template=&amp;quot;templates/wetter.html&amp;quot; data-parameter=&#039;{&amp;quot;par01&amp;quot;:&amp;quot;fc3_tempMax&amp;quot;,&amp;quot;par02&amp;quot;:&amp;quot;fc3_weatherDay&amp;quot;,&amp;quot;par03&amp;quot;:&amp;quot;fc3_tempMin&amp;quot;,&amp;quot;par04&amp;quot;:&amp;quot;fc3_date&amp;quot;}&#039;&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
[...]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== JavaScript-Funktionen ==&lt;br /&gt;
Neben den Widgets können auch einige JavaScript-Funktionen verwendet werden, um Befehle an FHEM zu senden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Folgende Zeile setzt einen direkten Befehl an FHEM ab (&amp;lt;code&amp;gt;set dummy1 off&amp;lt;/code&amp;gt;):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;div onclick=&amp;quot;ftui.setFhemStatus(&#039;set dummy1 off&#039;)&amp;quot;&amp;gt;Dummy1 aus&amp;lt;/div&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Diese Zeile veranlasst FHEM dazu, eine Funktion aus der 99_myUtils.pm auszuführen (&amp;lt;code&amp;gt;myUtils_HeizungUpDown(&amp;quot;WZ.Thermostat_Climate&amp;quot;,&amp;quot;up&amp;quot;)&amp;lt;/code&amp;gt;):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;div onclick=&amp;quot;ftui.setFhemStatus(&#039;{myUtils_HeizungUpDown(&amp;amp;quot;WZ.Thermostat_Climate&amp;amp;quot;,&amp;amp;quot;up&amp;amp;quot;)}&#039;)&amp;quot;&amp;gt;+&amp;lt;/div&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ein Beispiel, wie ein Kommando an FHEM gesendet wird und gleichzeitig der Wert eines bereits in FTUI angezeigten Readings verwendet werden kann:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;label&amp;quot; data-device=&amp;quot;dummy1&amp;quot; data-get=&amp;quot;temperature&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div onClick=&amp;quot;ftui.setFhemStatus(&#039;set dummy2 &#039;+ftui.getDeviceParameter(&#039;dummy1&#039;,&#039;temperature&#039;).val);&amp;quot;&amp;gt;Senden&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Eigene Widgets erstellen ==&lt;br /&gt;
Wie eigenen Widgets für FTUI erstellt werden können, ist auf der Seite [[FTUI eigene Widgets]] beschrieben.&lt;br /&gt;
&lt;br /&gt;
== FAQ ==&lt;br /&gt;
Häufig gestellte Fragen zum FHEM Tablet UI sind in der [[FHEM Tablet UI FAQ]] zusammengestellt.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [https://github.com/knowthelist/fhem-tablet-ui Projekt auf Github]&lt;br /&gt;
* {{Link2Forum|Topic=34233|LinkText=Forums-Beitrag}}&lt;br /&gt;
* [[FTUI_Snippets|Snippets]]&lt;br /&gt;
* [http://knowthelist.github.io/fhem/tablet/demo_widgets.html Live-Demos]&lt;br /&gt;
* [https://waschto.eu/fhem-und-tabletui-livedemo/ FHEM und TabletUI Live-Demo]&lt;br /&gt;
* {{Link2Forum|Topic=37378|LinkText=User-Demos}}&lt;br /&gt;
* [https://github.com/ovibox/fhem-ftui-user-demos Download der User-Demo-Dateien]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:FHEM Tablet UI|!]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=HomeMatic_Fenster-Drehgriffkontakt_Community-Nachbau&amp;diff=26412</id>
		<title>HomeMatic Fenster-Drehgriffkontakt Community-Nachbau</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=HomeMatic_Fenster-Drehgriffkontakt_Community-Nachbau&amp;diff=26412"/>
		<updated>2018-04-15T13:22:34Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: /* Erstellen des OTA (Over The Air) Bootloaders */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Der HB-Sec-RHS Funk-Fenster-Drehgriffkontakt ist ein Selbstbau threeStateSensor zur&lt;br /&gt;
Überwachung eines Fenster-Drehgriffs.&lt;br /&gt;
&lt;br /&gt;
Die Firmware ist identisch mit dem [https://www.elv.de/homematic-funk-fenster-drehgriffkontakt-1.html Originalen Sensor von ELV] und verhält sich dementsprechend auch gleich.&lt;br /&gt;
&lt;br /&gt;
== Übersicht ==&lt;br /&gt;
&lt;br /&gt;
Die Grundidee zu diesem Sensor wurde durch {{Link2Forum|Topic=71413.0|LinkText=Kawaci im Forum}} geliefert.&lt;br /&gt;
Die Umsetzung besteht aus einer Atmega328p Platine mit CC1101 Funkmodul (868 MHz) sowie&lt;br /&gt;
einer auf der [https://github.com/pa-pa/AskSinPP AskSin++] Portierung des Homematik Protokolls.&lt;br /&gt;
&lt;br /&gt;
Anfangs gab es zwei Ideen wie der Sensor aussehen sollte. Inzwischen hat sich die HomeMatic Variante mit CR2032 Batteriehalterung auf der Platine durchgesetzt. Somit wird hier nicht näher auf andere Versionen (zwei Platinen zur Erfassung der Fensterstellung) eingegangen.&lt;br /&gt;
&lt;br /&gt;
== Platine ==&lt;br /&gt;
&#039;&#039;&#039;Schaltplan:&#039;&#039;&#039;&lt;br /&gt;
[[Datei:FDGK_v1.0_sch.jpg]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Platine v1.0 (Oberseite mit korrigierter Pinbelegung):&#039;&#039;&#039;&lt;br /&gt;
[[Datei:FDGK_v1.0_top.jpg]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Platine v1.0 (Unterseite, ohne bestücktes Radio):&#039;&#039;&#039;&lt;br /&gt;
[[Datei:FDGK_v1.0_bot.jpg]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Bauteilliste ==&lt;br /&gt;
Die Bauteilliste gibt es auf [https://github.com/pa-pa/HMSensor/blob/master/HMSensor-CR2032/Parts.xls GitHub].&lt;br /&gt;
&lt;br /&gt;
In der Liste sind die Magnete und Reed-Kontakte nicht aufgeführt.&lt;br /&gt;
Folgende können verwendet werden:&lt;br /&gt;
* Reed-Kontakt 2x14mm [https://de.aliexpress.com/item/10pcs-N-O-Reed-switch-Magnetic-Switch-2-14mm-Normally-Open-Magnetic-Induction-switch/32803902404.html Aliexpress]&lt;br /&gt;
* Neodym Magnet 2x2mm [https://de.aliexpress.com/item/100pcs-2x2mm-magnet-2x2-Super-strong-neo-neodymium-magnet-N35-D2x2-D2x2mm-permanent-magnet-D2-2mm/32693530575.html Aliexpress]&lt;br /&gt;
&lt;br /&gt;
== Zusammenlöten der SMD Bauteile ==&lt;br /&gt;
Die Bestückung der Platine ist im [https://forum.fhem.de/index.php/topic,71413.msg640858.html#msg640858 diesem Post] kurz beschrieben.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Bemerkung:&#039;&#039;&#039;&lt;br /&gt;
Y1 (32 kHz Quarz), C4 und C5 sind nicht erforderlich.&lt;br /&gt;
Vor dem Verlöten der Bauteile sollte kontrolliert werden, ob die Platinen in das Gehäuse passen. Falls nicht, sollte entweder das Gehäuse oder die Platine passend gefeilt werden.&lt;br /&gt;
&lt;br /&gt;
Zuerst auf der Unterseite IC1 bestücken:&lt;br /&gt;
Hierzu einen beliebigen äußeren Pin verzinnen, den Prozessor mit der richtigen Orientierung von Pin 1 (runder Punkt) platzieren und den Pin verlöten.&lt;br /&gt;
Darauf achten, dass der Prozessor mittig auf den Pads aufliegt, ggf. den Pin wieder erhitzen&lt;br /&gt;
und den IC drehen oder verschieben. Auf der gegenüberliegenden Seite ebenfalls einen Pin verlöten, damit der IC fixiert ist.&lt;br /&gt;
Mit einem Flussmittelstift auf allen vier Seiten die Pins bestreichen und auf jeder Seite die Pins einzeln mit einer feinen Lötspitze bzw. feinem Lötzinn verlöten. Kurzschlüsse zwischen einzelnen Pins müssen unbedingt vermieden werden.&lt;br /&gt;
&lt;br /&gt;
Danach auf der Unterseite C1, C2, C3 sowie R1 bestücken.&lt;br /&gt;
Auf der Oberseite R2, D1 (rot), R3, D2 (gelb), C6 und die beiden Taster bestücken.&lt;br /&gt;
&lt;br /&gt;
Nach dem [https://wiki.fhem.de/wiki/HomeMatic_Fenster-Drehgriffkontakt_Community-Nachbau#Firmware Flashen der Firmware] das Radio (IC2) bzw. den Batteriehalter (BT1) bestücken.&lt;br /&gt;
Als Antenne (ANT) wird ein Draht mit 72 mm Länge eingelötet.&lt;br /&gt;
&lt;br /&gt;
== Firmware ==&lt;br /&gt;
&lt;br /&gt;
=== Bootloader ===&lt;br /&gt;
&lt;br /&gt;
Die Sensorfirmware kann OTA (Over The Air) oder über den Arduino Bootloader geladen werden.&lt;br /&gt;
&lt;br /&gt;
=== Erstellen des OTA (Over The Air) Bootloaders ===&lt;br /&gt;
{{Randnotiz|RNText=Firmware für &#039;ID=0030&#039;}}&lt;br /&gt;
Dafür wird, mit Hilfe der [https://forum.fhem.de/index.php?action=dlattach;topic=71413.0;attach=91780 makeota.html] der Bootloader mit den benötigten Daten gefüllt und anschließend generiert.&lt;br /&gt;
&lt;br /&gt;
Die makeota.html wird dazu in einem beliebigen Browser aufgerufen.&lt;br /&gt;
&lt;br /&gt;
Die Felder &#039;&#039;HM ID&#039;&#039; und &#039;&#039;HM-Serial&#039;&#039; innerhalb der makeota.html können jeweils frei gewählt werden (dabei die Vorgaben beachten, so z.B. &#039;&#039;HM ID&#039;&#039;: 6 hexadezimale Zeichen). Das Feld &#039;&#039;Device Type&#039;&#039; muss folgende Nummer beinhalten: &amp;quot;0030&amp;quot;. Das Feld &#039;&#039;Config String&#039;&#039; wird aus den eingegebenen Daten automatisch generiert.&lt;br /&gt;
&lt;br /&gt;
Die zwei o.g. Felder müssen sich von Gerät zu Gerät unterscheiden. Aus diesem Grund ist es sinnvoll, sich die eingegebenen Daten aufzuschreiben oder Screenshots zu erstellen.&lt;br /&gt;
&lt;br /&gt;
Nun muss noch dem Bootloader bekannt gemacht werden, welche Batterien mit dem FDGK verwendet werden. Dies wird über die dropdown Liste &amp;quot;Power Presets&amp;quot; ausgewählt:&lt;br /&gt;
&lt;br /&gt;
Dabei bedeutet:&lt;br /&gt;
&lt;br /&gt;
*No StepUp = CR2032 Batterie&lt;br /&gt;
*StepUp single AA = eine AA Batterie und StepUp&lt;br /&gt;
*StepUp two AAA = zwei AAA Batterien und StepUp&lt;br /&gt;
&lt;br /&gt;
Die Parameter „Step-Up Present“, „Low-Voltage“ und „Critical Voltage” ergeben sich aus der Wahl in der DropDown Liste, können aber individuell angepasst werden. Für den fehlerfreien Betrieb sollten diese aber unverändert bleiben!&lt;br /&gt;
&lt;br /&gt;
Seit 12/2017 kann optional die [https://forum.fhem.de/index.php?action=dlattach;topic=71413.0;attach=91779 aktuelle Firmware] mit angegeben werden, so dass die Firmware gleichzeitig mit dem Bootloader geflasht werden kann. In diesem Fall kann der FDGK sofort in Betrieb genommen werden und nur es wird nur eine aktualisierte Firmware per OTA (Over The Air) geflasht.&lt;br /&gt;
&lt;br /&gt;
Nach drücken der Taste &amp;quot;Create&amp;quot; erscheint eine Schaltfläche &amp;quot;Save Bootloader&amp;quot;, mit welcher der angepasste Boorloader gespeichert werden kann. Es wird hierzu kein Netzzugang benötigt. Alles erfolgt per Javascript im Browser.&lt;br /&gt;
&lt;br /&gt;
Seit 01/2018 gibt es die Firmware auch für das sog. &#039;&#039;lazy config&#039;&#039;. Hierbei können die Register einfach z.B. durch das nächste Öffnen des Fensters ausgelesen werden, ohne dass die Config-Taste gedrückt werden muss.&lt;br /&gt;
Das Update auf &#039;&#039;lazy config&#039;&#039; geht auf zwei Arten:&lt;br /&gt;
&lt;br /&gt;
Keine Änderung der &#039;ID=0030&#039; und Durchführen eines [https://forum.fhem.de/index.php?action=dlattach;topic=71413.0;attach=94541 Firmware] bzw. eines FHEM Updates oder &lt;br /&gt;
{{Randnotiz|RNText=Firmware für &#039;ID=00C3&#039;}}&lt;br /&gt;
Aktualisierung der Firmware auf &#039;ID=00C3&#039;. Die Dateien können hier: [https://forum.fhem.de/index.php?action=dlattach;topic=71413.0;attach=94538 makeota.html], [https://forum.fhem.de/index.php?action=dlattach;topic=71413.0;attach=94542 Firmware (hex)] bzw. [https://forum.fhem.de/index.php?action=dlattach;topic=71413.0;attach=94541 Firmware (eq3)] heruntergeladen werden.&lt;br /&gt;
&lt;br /&gt;
Verwendet man den Sensor in Kombination mit originaler eq3 Hardware, sollte man die zweite Möglichkeit wählen.&lt;br /&gt;
&lt;br /&gt;
=== Flashen des OTA Bootloaders ===&lt;br /&gt;
Anschließend wird per ISP (USBasp oder vergleichbares) der Bootloader geflasht.&lt;br /&gt;
Zum Laden des Bootloaders, sowie der Software werden die Arduino SDK bzw. avrdude und die von makeota.html generierte Datei benötigt.&lt;br /&gt;
&lt;br /&gt;
Der Bootloader lässt sich nun bei gestecktem ISP Programmer über folgende Befehle flashen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;avrdude -p m328p -P usb -c usbasp -B 3 -U lfuse:w:0xE2:m -U hfuse:w:0xD0:m -U efuse:w:0x06:m -U lock:w:0x2F:m&amp;lt;/pre&amp;gt;&lt;br /&gt;
Setzt die Fuses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;avrdude -p m328p -P usb -c usbasp -V -U flash:w:bootloader.hex&amp;lt;/pre&amp;gt;&lt;br /&gt;
lädt den eigentlichen Bootloader. Dabei ist zu achten, dass &amp;quot;bootloader.hex&amp;quot; die Datei mit dem Bootloader (bzw. der Firmware) ist und dementsprechend auch im Verzeichnis sein muss, wo die Datei zu finden ist.&lt;br /&gt;
&lt;br /&gt;
Wenn jetzt die Platine mit Spannung versorgt wird, sollte die rote LED 7x blinken. Das signalisiert, dass der Bootloader erfolgreich gestartet wurde. Er wartet jetzt darauf, dass die Firmware übertragen wird.&lt;br /&gt;
&lt;br /&gt;
=== OTA Update === &lt;br /&gt;
Hierzu wird flash-ota benötigt.&lt;br /&gt;
&lt;br /&gt;
Flash-ota funktioniert aktuell nur mit [[CUL]]/[[COC]] oder [[HM-CFG-USB USB Konfigurations-Adapter|HM-CFG-USB]] unter Linux ([[HomeMatic_Firmware_Update#Firmware_Update_mit_CUL.2FHM-CFG-USB_unter_FHEM|Update mit CUL oder HM-CFG-USB unter Linux]]), mit dem &amp;quot;HomeMatic Firmware Update Tool&amp;quot; unter Windows ([[HomeMatic_Firmware_Update#Firmware_Update_mit_HM-CFG-USB_unter_Windows|Update mit HM-CFG-USB unter Windows]]) oder mit einer CCU2.&lt;br /&gt;
&lt;br /&gt;
Für einen HM-CFG-USB oder den HM-UART sieht der Aufruf wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;./flash-ota -f avr_HM_SEC_RHS_201705271601.eq3 -s RHS0000000&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für einen CUL muss noch die USB Schnittstelle oder der Pfad des USB Geräts mit gegeben werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;./flash-ota -f avr_HM_SEC_RHS_201705271601.eq3 -s RHS0000000 -c /dev/serial/by-path/platform-3f980000.usb-usb-0:1.3:1.0-port0&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Falls Fehler während der Übertragung auftreten, muss die Übertragung nochmals wiederholt werden.&lt;br /&gt;
Wenn die Firmware erfolgreich übertragen werde konnte, kann der Sensor gepairt werden.&lt;br /&gt;
&lt;br /&gt;
== Einlöten der Reedkontakte und Anschluss an A0 &amp;amp; A1 ==&lt;br /&gt;
Den Magneten in den Drehring einbauen und diesen in das Gehäuse einbauen. Die Reedkontakte&lt;br /&gt;
Platzieren und mit einem Ohmmeter Messen, ob die Reedkontakte bei der entsprechenden Position&lt;br /&gt;
der Magnete schalten. Falls nicht, ggf. die Reedkontakte austauschen (Streuung!) bzw. einen stärkeren Magneten verwenden. Danach mittels Silberdraht bzw. Kupferlackdraht (an den zu&lt;br /&gt;
verlötenden Enden den Lack mittels eines Cuttermessers entfernen) die Reedkontakte gemäß&lt;br /&gt;
Bild verlöten und die Enden (GND, A0 bzw. A1) durch die vorgesehenen Öffnungen im Gehäuse führen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Verlötete Reedkontakte:&#039;&#039;&lt;br /&gt;
[[Datei:HM_Fenstersensor-pic15.jpg]]&lt;br /&gt;
&lt;br /&gt;
Danach die Antenne in die dafür vorgesehene Bohrung einführen und die Platine platzieren. Darauf achten, dass die Anschlüsse der Reedkontakte durch die dafür vorgesehenen Kontakte auf der Platine geführt werden.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Einführen der Antenne:&#039;&#039;&lt;br /&gt;
[[Datei:HM_Fenstersensor-pic17.jpg]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Platzierte Platine:&#039;&#039;&lt;br /&gt;
[[Datei:HM_Fenstersensor-pic16.jpg]]&lt;br /&gt;
&lt;br /&gt;
Nach Verlöten der drei Kontaktpunkte ist der Fensterdrehgriff fertig aufgebaut.&lt;br /&gt;
&lt;br /&gt;
== Sensor spezifische Einstellungen ==&lt;br /&gt;
Der Sensor meldet die Position entsprechend welcher Zustand an A0 &amp;amp; A1 an liegt. Derzeit ist folgende Logik implementiert:&lt;br /&gt;
&lt;br /&gt;
A0 &amp;amp; A1 offen - PosA -&amp;gt; OPEN&lt;br /&gt;
&lt;br /&gt;
A0 geschlossen - PosB -&amp;gt; CLOSED&lt;br /&gt;
&lt;br /&gt;
A1 geschlossen - PosC -&amp;gt; TILTED&lt;br /&gt;
&lt;br /&gt;
Die Bedeutung der Positionen kann mittels der entsprechenden Register eingestellt werden.&lt;br /&gt;
&lt;br /&gt;
Ebenfalls kann die CyclicInfoMsg aktiviert werden (zum aktivieren siehe Link am Ende des Artikels). Der Sensor meldet sich dann alle 24 Stunden mit dem aktuellen Status.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Register zum ändern der Position von A0 &amp;amp; A1:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;set &amp;lt;Device_Name&amp;gt; regSet msgRhsPosA &amp;lt;closed|open|noMsg|tilted&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;set &amp;lt;Device_Name&amp;gt; regSet msgRhsPosB &amp;lt;closed|open|noMsg|tilted&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;set &amp;lt;Device_Name&amp;gt; regSet msgRhsPosC &amp;lt;closed|open|noMsg|tilted&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Gehäuse ==&lt;br /&gt;
Für das Gehäuse wurde auf eine 3D-Drucklösung gesetzt. Es gibt inzwischen mehrere Versionen (abgerundete obere Kante, eckige Kante uvm.).&lt;br /&gt;
&lt;br /&gt;
Die Standard Version ist [https://www.thingiverse.com/thing:2354704 hier] zu finden.&lt;br /&gt;
&lt;br /&gt;
Wer keinen 3D-Drucker besitzt kann sich im Forum nach einem 3D-Druckservice um schauen. Einige User bieten gegen kleines Geld einen netten und preiswerten {{Link2Forum|Topic=70413|LinkText=Service}} an.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
*[https://forum.fhem.de/index.php/topic,71413.0.0.html Link zum Foren-Thread]&lt;br /&gt;
*[https://github.com/pa-pa/AskSinPP AskSinPP  Libary]&lt;br /&gt;
*[https://github.com/pa-pa/HMSensor Alles Mögliche zu dem Projekt auf Github]&lt;br /&gt;
*[[HomeMatic_Type_threeStateSensor|CyclicInfoMsg aktivieren]]&lt;br /&gt;
*{{Link2Forum|Topic=70413|LinkText=3D-Druck service}}&lt;br /&gt;
*[[HomeMatic_Firmware_Update#Firmware_Update_mit_CUL.2FHM-CFG-USB_unter_FHEM|update-ota]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HomeMatic Components‏‎]]&lt;br /&gt;
[[Kategorie:HomeBrew‏‎]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Pagetab&amp;diff=25694</id>
		<title>FTUI Widget Pagetab</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Pagetab&amp;diff=25694"/>
		<updated>2018-03-05T19:19:43Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: Typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das [[{{PAGENAME}}|Pagetab Widget]] ist ein Widget für [[FHEM Tablet UI]], welches es erlaubt, den Inhalt einer Seite durch den einer anderen zu ersetzen. Es kann zum Beispiel für ein Menü verwendet werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
File:FTUI_Widget_Pagetab_03.png&lt;br /&gt;
File:FTUI_Widget_Pagetab_04.png&lt;br /&gt;
File:FTUI_Widget_Pagetab_01.png&lt;br /&gt;
File:FTUI_Widget_Pagetab_02.png&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Attribute==&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Standard-Wert&lt;br /&gt;
!Beispiel&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-device&#039;&#039;&#039;||FHEM Device, dessen Status das Aussehen des Widgets bestimmt||||data-device=&amp;quot;dummy1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-url&#039;&#039;&#039;||URL der neuen Seite, die angezeigt werden soll||||data-url=&amp;quot;content_main.html&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-icon&#039;&#039;&#039;||Vordergrund-Icon des Widgets||fa-power-off||data-icon=&amp;quot;mi-home&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-background-icon&#039;&#039;&#039;||Hintergrund-Icon des Widgets||fa-circle||data-background-icon=&amp;quot;fa-square&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-on-background-color&#039;&#039;&#039;||Farbe des Hintergrund-Icons, wenn der gewünschte Inhalt angezeigt wird||#606060||data-on-background-color=&amp;quot;gray&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-off-background-color&#039;&#039;&#039;||Farbe des Vordergrund-Icons, wenn der gewünschte Inhalt nicht angezeigt wird||transparent||data-off-background-color=&amp;quot;#cccccc&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-on-color&#039;&#039;&#039;||Farbe des Vordergrund-Icons, wenn der gewünschte Inhalt angezeigt wird||#222222||data-on-color=&amp;quot;yellow&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-off-color&#039;&#039;&#039;||Farbe des Vordergrund-Icons, wenn der gewünschte Inhalt nicht angezeigt wird||#505050||data-off-color=&amp;quot;#000000&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-get-on&#039;&#039;&#039;||Ein Array an Stati eines Devices. Je nach Status wird ein anderes Icon aus &#039;&#039;data-icons&#039;&#039; angezeigt.||||data-get-on=&#039;[&amp;quot;Ein&amp;quot;,&amp;quot;Pause&amp;quot;,&amp;quot;Aus&amp;quot;]&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-icons&#039;&#039;&#039;||Ein Array an Icons, die in Abhängigkeit von &#039;&#039;data-get-on&#039;&#039; angezeigt werden||||data-icons=&#039;[&amp;quot;mi-play_arrow&amp;quot;,&amp;quot;mi-pause&amp;quot;,&amp;quot;mi-stop&amp;quot;]&#039;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-return-time&#039;&#039;&#039;||Kehrt nach der angegebenen Zeit in Sekunden wieder zur &amp;quot;Startseite&amp;quot; zurück. Muss auf dem ersten Pagetab gesetzt werden||0 (endlos)||data-return-time=&amp;quot;5&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-text&#039;&#039;&#039;||Text für die Beschreibung||||data-text=&amp;quot;Home&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==CSS Klassen==&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
{{FTUI Klasse|warn}}{{FTUI Klasse|activate}}{{FTUI Klasse|labelright}}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Hinweise==&lt;br /&gt;
* Das Attribut &#039;&#039;&#039;data-return-time&#039;&#039;&#039; muss auf dem &amp;quot;Haupt-Pagetab&amp;quot; (dem ersten; index 0) platziert werden&lt;br /&gt;
&lt;br /&gt;
==Beispiele==&lt;br /&gt;
===Einfacher Link===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;pagetab&amp;quot;&lt;br /&gt;
     data-url=&amp;quot;index.html&amp;quot;&lt;br /&gt;
     data-icon=&amp;quot;mi-home&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[File:FTUI_Widget_Pagetab_03.png]]&lt;br /&gt;
&lt;br /&gt;
===Einfacher Link mit Beschreibungstext===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div data-type=&amp;quot;pagetab&amp;quot;&lt;br /&gt;
     data-url=&amp;quot;index.html&amp;quot;&lt;br /&gt;
     data-icon=&amp;quot;mi-home&amp;quot;&lt;br /&gt;
     data-text=&amp;quot;home&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
[[File:FTUI_Widget_Pagetab_04.png]]&lt;br /&gt;
&lt;br /&gt;
===Navigationsleiste===&lt;br /&gt;
Ein guter Anwendungszweck für das Pagetab-Widget ist eine Navigationsleiste. Dazu braucht es allerdings mehrere Seiten:&lt;br /&gt;
*Eine mit der Navigation selbst. Die wird später als Template auf den Zielseiten eingebunden&lt;br /&gt;
*Eine Startseite&lt;br /&gt;
*Eine oder mehrere Zielseiten, auf die navigiert werden kann&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Menü-Seite (menu.html)&lt;br /&gt;
Eine Menü-Seite könnte z.B. wie folgt aussehen. Auf dieser Seite sind drei Pagetab-Widgets platziert.&lt;br /&gt;
*Das erste ist ein ganz einfacher Link mit einem Beschreibungstext. Die Seite unter &#039;&#039;data-url&#039;&#039; wird beim Aufruf der Startseite automatisch geladen.&lt;br /&gt;
*Das zweite Widget ändert sein Icon je nach Status-Wert des Dummies &#039;&#039;dummy1&#039;&#039;. Ist der Status 0, wird nur das Icon &#039;&#039;fa-fax&#039;&#039; angezeigt. Ist der Status größer 0, erscheint rechts über dem Icon noch ein &amp;quot;Warnhinweis&amp;quot; mit dem Status-Wert des Dummies. Außerdem ist der Beschreibungstext nach rechts gerückt.&lt;br /&gt;
*Das dritte Widget funktioniert im Prinzip wie das zweite. Außer der Status-Wert des Dummies ist &#039;&#039;on&#039;&#039;. Dann wird die im Widget verlinkte Seite automatisch geöffnet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE html&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;sheet&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;div class=&amp;quot;row&amp;quot;&amp;gt;&lt;br /&gt;
		&amp;lt;div data-type=&amp;quot;pagetab&amp;quot;&lt;br /&gt;
			 data-url=&amp;quot;pagetab01.html&amp;quot;&lt;br /&gt;
			 data-icon=&amp;quot;fa-home&amp;quot;&lt;br /&gt;
			 data-text=&amp;quot;home&amp;quot;&lt;br /&gt;
			 class=&amp;quot;cell&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
	&amp;lt;div class=&amp;quot;row&amp;quot;&amp;gt;&lt;br /&gt;
		&amp;lt;div data-type=&amp;quot;pagetab&amp;quot;&lt;br /&gt;
			 data-device=&amp;quot;dummy1&amp;quot;&lt;br /&gt;
			 data-get-on=&#039;[&amp;quot;0&amp;quot;,&amp;quot;1&amp;quot;]&#039;&lt;br /&gt;
			 data-icons=&#039;[&amp;quot;fa-fax&amp;quot;,&amp;quot;fa-fax warn&amp;quot;]&#039;&lt;br /&gt;
			 data-url=&amp;quot;pagetab02.html&amp;quot;	&lt;br /&gt;
			 data-text=&amp;quot;anrufe&amp;quot;&lt;br /&gt;
			 class=&amp;quot;cell labelright&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
	&amp;lt;div class=&amp;quot;row&amp;quot;&amp;gt;&lt;br /&gt;
		&amp;lt;div data-type=&amp;quot;pagetab&amp;quot;&lt;br /&gt;
			 data-device=&amp;quot;dummy2&amp;quot;&lt;br /&gt;
			 data-get-on=&#039;[&amp;quot;0&amp;quot;,&amp;quot;(?:[1-9][0-9]*)&amp;quot;,&amp;quot;on&amp;quot;]&#039;&lt;br /&gt;
			 data-icons=&#039;[&amp;quot;fa-fax&amp;quot;,&amp;quot;fa-fax warn&amp;quot;,&amp;quot;fa-fax warn activate&amp;quot;]&#039;&lt;br /&gt;
			 data-url=&amp;quot;pagetab03.html&amp;quot;&lt;br /&gt;
			 class=&amp;quot;cell&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
	&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Startseite (index.html)&lt;br /&gt;
Auf der Startseite müssen keine Inhalte sein. Durch das erste Pagetab-Widget wird dessen URL automatisch geladen. Allerdings ist das Menü-Template einzubinden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE html&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&lt;br /&gt;
    &amp;lt;script src=&amp;quot;js/fhem-tablet-ui.js&amp;quot; defer&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;title&amp;gt;FHEM-Tablet-UI&amp;lt;/title&amp;gt;&lt;br /&gt;
&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;gridster&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;ul&amp;gt;&lt;br /&gt;
		&amp;lt;li data-row=&amp;quot;1&amp;quot; data-col=&amp;quot;1&amp;quot; data-sizex=&amp;quot;1&amp;quot; data-sizey=&amp;quot;4&amp;quot; data-template=&amp;quot;menu.html&amp;quot;&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;li data-row=&amp;quot;1&amp;quot; data-col=&amp;quot;2&amp;quot; data-sizex=&amp;quot;4&amp;quot; data-sizey=&amp;quot;4&amp;quot;&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
	&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Zielseiten (pagetab01.html, pagetab02.html, pagetab03.html)&lt;br /&gt;
Die Zielseiten können ganz normal gestaltet werden. Es ist nur darauf zu achten, dass auf jeder Zielseite auch das Menü-Template eingebunden wird. Eine Zielseite könnte so aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE html&amp;gt;&lt;br /&gt;
&amp;lt;html&amp;gt;&lt;br /&gt;
&amp;lt;head&amp;gt;&amp;lt;/head&amp;gt;&lt;br /&gt;
&amp;lt;body&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;gridster&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;ul&amp;gt;&lt;br /&gt;
		&amp;lt;li data-row=&amp;quot;1&amp;quot; data-col=&amp;quot;1&amp;quot; data-sizex=&amp;quot;1&amp;quot; data-sizey=&amp;quot;4&amp;quot; data-template=&amp;quot;menu.html&amp;quot;&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
		&amp;lt;li data-row=&amp;quot;1&amp;quot; data-col=&amp;quot;2&amp;quot; data-sizex=&amp;quot;4&amp;quot; data-sizey=&amp;quot;4&amp;quot; class=&amp;quot;left-align&amp;quot;&amp;gt;Pagetab02.html&amp;lt;/li&amp;gt;&lt;br /&gt;
	&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/body&amp;gt;&lt;br /&gt;
&amp;lt;/html&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wird nun auf eines der Icons geklickt, blendet die aktuelle Seite aus und die Zielseite wird eingeblendet.&lt;br /&gt;
&lt;br /&gt;
[[File:FTUI_Widget_Pagetab_02.png]]&lt;br /&gt;
&lt;br /&gt;
==Weblinks==&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:FHEM Tablet UI|Pagetab]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=PRESENCE&amp;diff=24693</id>
		<title>PRESENCE</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=PRESENCE&amp;diff=24693"/>
		<updated>2018-01-24T19:40:06Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: Typos&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=Anwesenheitserkennung&lt;br /&gt;
|ModType=h&lt;br /&gt;
&amp;lt;!-- |ModCmdRef= --&amp;gt;&lt;br /&gt;
|ModTechName=73_PRESENCE.pm&lt;br /&gt;
|ModOwner=markusbloch&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Das [[PRESENCE]] Modul bietet für die Anwesenheitserkennung mehrere Varianten an: &lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;lan-ping&#039;&#039;&#039; - Das Überwachen via PING Checks, die durch den FHEM Server versandt werden.&lt;br /&gt;
* &#039;&#039;&#039;fritzbox&#039;&#039;&#039; - Das Überwachen von Geräten auf einer FritzBox via ctlmgr_ctl (Nur auf einer FritzBox möglich)&lt;br /&gt;
* &#039;&#039;&#039; Bluetooth&#039;&#039;&#039;&lt;br /&gt;
:- &#039;&#039;&#039;local-bluetooth&#039;&#039;&#039; - Das Überwachen via Bluetooth Checks, die vom FHEM Server direkt durchgeführt werden (angeschlossener Bluetooth-Stick und die Software bluez voraussgesetzt)&lt;br /&gt;
:- &#039;&#039;&#039;lan-bluetooth&#039;&#039;&#039;   - Das Überwachen von Bluetoothgeräten, über Netzwerk. Auf einer oder mehreren Maschinen im Netzwerk (z.B. [[:Kategorie:Raspberry Pi|Raspberry Pi]]) läuft ein Presence-Daemon, der nach Bluetooth-Geräten sucht. Um mehrere Presence-Daemon mit FHEM zu verbinden, gibt es den Collector-Daemon, der sich zu allen Presence-Damons im Netzwerk verbindet und das Ergebnis von allen zusammenfasst.&lt;br /&gt;
* &#039;&#039;&#039;function&#039;&#039;&#039; - Das Überwachen mithilfe einer selbst geschrieben Perl-Funktion, die den Anwesenheitsstatus zurückgibt (0 oder 1)&lt;br /&gt;
* &#039;&#039;&#039;shell-script&#039;&#039;&#039; - Das Überwachen mithilfe eines selbst geschriebenen Shell-Programms/Skript, das eine 0 oder 1 ausgibt, um den Anwesenheitsstatus mitzuteilen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Überwachen mittels Ping im WLAN/LAN =&lt;br /&gt;
{{Randnotiz|RNText=Um diese Methode auf einer FritzBox nutzen zu können, muss FHEM mit root-Rechten laufen. Dies ist standardmäßig nicht der Fall. Bitte dazu den Wiki Artikel [[FritzBox: fhem unter root starten]] beachten.}}&lt;br /&gt;
Um ein Gerät via Ping zu überwachen, muss folgende Definition durchgeführt werden:&lt;br /&gt;
:&amp;lt;code&amp;gt;define Handy PRESENCE lan-ping 192.168.0.30&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dadurch wird die IP-Addresse 192.168.0.30 alle 30&amp;amp;nbsp;Sekunden geprüft, ob sie erreichbar ist. Wenn sie erreichbar ist, ist der Status &amp;quot;present&amp;quot; (anwesend), ansonsten &amp;quot;absent&amp;quot; (abwesend).&lt;br /&gt;
&lt;br /&gt;
Der Timeout kann verändert werden, indem ein Wert (in Sekunden) an das Define anhängt wird:&lt;br /&gt;
:&amp;lt;code&amp;gt;define Handy PRESENCE lan-ping 192.168.0.30 &#039;&#039;&#039;60&#039;&#039;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nun würde das Handy alle 60 Sekunden geprüft werden.&lt;br /&gt;
&lt;br /&gt;
Nur wenn bei einem iPhone/iPad die Funktion &amp;quot;über WLAN synchronisieren&amp;quot; aktiviert ist, ist es auch im Standby zuverlässig pingbar. Standardmäßig deaktivieren Apple-Geräte ihr WLAN im Standby-Betrieb um die Akkulaufzeit zu verlängern.&lt;br /&gt;
&lt;br /&gt;
Sollte die Fehlermeldung &lt;br /&gt;
:&amp;lt;code&amp;gt; PRESENCE (Handy) - ping command returned with output: ping: icmp open socket: Operation not permitted &amp;lt;/code&amp;gt; &lt;br /&gt;
im Log auftauchen und lan-ping dadurch nicht funktionieren, liegt ein Berechtigungsproblem vor. Kein Grund den User fhem zu root zu machen!&lt;br /&gt;
Prüfe zu erst als User root ob die Capabilities gesetzt sind.&lt;br /&gt;
:&amp;lt;code&amp;gt;getcap /bin/ping&amp;lt;/code&amp;gt;&lt;br /&gt;
Sollte folgendes Ergeben zu Tage fördern.&lt;br /&gt;
:&amp;lt;code&amp;gt;/bin/ping = cap_net_raw+ep&amp;lt;/code&amp;gt;&lt;br /&gt;
Ist dem nicht so, setzen wir die benötigten Capabilities&lt;br /&gt;
:&amp;lt;code&amp;gt;setcap cap_net_raw+ep /bin/ping&amp;lt;/code&amp;gt;&lt;br /&gt;
Mehr Informationen zum Thema Capabilities [https://manpages.debian.org/jessie/manpages-de/capabilities.7.de.html].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= FritzBox: direktes Abfragen der Aktivität via ctlmgr_ctl =&lt;br /&gt;
{{Randnotiz|RNText=Um diese Methode auf einer FritzBox nutzen zu können, muss FHEM mit root-Rechten laufen. Dies ist standardmäßig nicht der Fall. Bitte dazu den Wiki Artikel [[FritzBox: fhem unter root starten]] beachten.}}&lt;br /&gt;
Eine sehr häufige und auch zuverlässige Methode ist auf einer FritzBox die Abfrage mittels ctlmgr_ctl Befehl. Über diesen lassen sich alle Geräte abfragen ob sie aktiv sind. Ist ein Gerät aktiv, so gilt es als anwesend.&lt;br /&gt;
&lt;br /&gt;
Dieser Modus kann allerdings nur in FHEM Installationen direkt auf einer FritzBox verwendet werden. Des weiteren muss FHEM unter dem User root laufen. Um ein Gerät zu überwachen, wird lediglich der Gerätename benötigt, so wie er unter dem Menüpunkt &amp;quot;Heimnetz&amp;quot; auftaucht. &lt;br /&gt;
&lt;br /&gt;
Die erforderliche Definition:&lt;br /&gt;
:&amp;lt;code&amp;gt;define Handy PRESENCE fritzbox iPhone-4S&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Überwachung mittels Perl-Code =&lt;br /&gt;
Es ist möglich zum Überwachen von Geräten eine eigene Perl-Funktion zu verwenden die dann vom PRESENCE Modul im Hintergrund aufgerufen wird.&lt;br /&gt;
&lt;br /&gt;
 define &amp;lt;name&amp;gt; PRESENCE function {...} [ &amp;lt;check-interval&amp;gt; [ &amp;lt;present-check-interval&amp;gt; ] ]&lt;br /&gt;
&lt;br /&gt;
Sobald die Funktion den Rückgabewert 1 hat, ist das Gerät anwesend, bei 0 abwesend.&lt;br /&gt;
&lt;br /&gt;
== Beispiel DHCP Überwachung auf Airport Basestation ==&lt;br /&gt;
Die hier vorgestellte Überwachung der DHCP Lease auf Airport Basestations per SNMP ist absolut robust gegenüber dem Ruhezustand von iOS und setzt keine weitere Konfiguration auf dem iPhone voraus. Das Abmelden beim Verlassen des Empfangsbereiches der Basestation geschieht mit etwa 5-10 Minuten Verzögerung und ist somit auch vor kurzzeitigen Empfangsproblemen sicher. Das nebenstehende Bild (???) verdeutlicht noch mal die Unterschiede zwischen einer IP-Basierten Ping-Überwachung und der Überwachung auf Ebene der Basestation oder FritzBox.&lt;br /&gt;
&lt;br /&gt;
Bevor der folgende Code verwendet werden kann ist das Perl Modul Net:SNMP zu installieren (z.&amp;amp;nbsp;B. mit: &amp;lt;code&amp;gt;cpan install use Net::SNMP&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Zuerst ist folgender Code in 99_myUtils.pm einzufügen, sollte diese noch nicht vorhanden sein muss diese aus dem Template welches unter Edit Files zu finden ist erzeugt werden.&lt;br /&gt;
&#039;&#039;&#039;Achtung, das ist nicht der komplette Inhalt der 99_myUtils!&#039;&#039;&#039; Das ist nur die einzelne Routine&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use Net::SNMP;&lt;br /&gt;
sub&lt;br /&gt;
snmpCheck($$)&lt;br /&gt;
{&lt;br /&gt;
  my ($airport,$client)= @_;&lt;br /&gt;
&lt;br /&gt;
  my $community = &amp;quot;public&amp;quot;;&lt;br /&gt;
  my $host = $airport;&lt;br /&gt;
  my $oid = &amp;quot;.1.3.6.1.2.1.3.1.1.2&amp;quot;;&lt;br /&gt;
  #my $oid = &amp;quot;.1.3.6.1.2.1.3.1.1.2.25.1.10.0.1&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  my ( $session, $error ) = Net::SNMP-&amp;gt;session(&lt;br /&gt;
    -hostname =&amp;gt; $host,&lt;br /&gt;
    -community =&amp;gt; $community,&lt;br /&gt;
    -port =&amp;gt; 161,&lt;br /&gt;
    -version =&amp;gt; 1&lt;br /&gt;
  );&lt;br /&gt;
&lt;br /&gt;
  if( !defined($session) ) {&lt;br /&gt;
    return 0;&lt;br /&gt;
    return &amp;quot;Can&#039;t connect to host $host.&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  my @snmpoids = ();&lt;br /&gt;
&lt;br /&gt;
  my $response = $session-&amp;gt;get_next_request($oid);&lt;br /&gt;
  my @nextid = keys %$response;&lt;br /&gt;
  while ( @nextid &amp;amp;&amp;amp; $nextid[0] &amp;amp;&amp;amp; $nextid[0] =~ m/^$oid/ ) {&lt;br /&gt;
    push( @snmpoids, $nextid[0] );&lt;br /&gt;
&lt;br /&gt;
    $response = $session-&amp;gt;get_next_request( $nextid[0] );&lt;br /&gt;
    @nextid = keys %$response;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if( !defined($response = $session-&amp;gt;get_request( @snmpoids ) ) ) {&lt;br /&gt;
    return 0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  foreach my $value (values %$response) {&lt;br /&gt;
    return 1 if( $value eq $client )&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Danach lässt sich das Mobilgerät so überwachen:&lt;br /&gt;
:&amp;lt;code&amp;gt;define iPhone PRESENCE function {snmpCheck(&amp;quot;10.0.1.1&amp;quot;,&amp;quot;0x44d77429f35c&amp;quot;)} 30 30&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
wobei 10.0.1.1 durch die IP-Adresse der Basestation und 0x44d77429f35c durch die MAC Adresse des Geräts als HEX-Zahl ersetzt werden muss.&lt;br /&gt;
&lt;br /&gt;
== Beispiel Anwesenheitserkennung mittels UniFi Controller ==&lt;br /&gt;
&lt;br /&gt;
Die Anwesenheitserkennung bei Geräten in Verbindung mit UniFi-Produkten funktioniert selbst dann, wenn sich die Geräte im PowerSave-Modus befinden. &lt;br /&gt;
&lt;br /&gt;
Beachte: Die Geräte werden erst ungefähr nach 5 Minuten, nachdem das Gerät das WLAN verlassen hat als disconnected angezeigt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;define &amp;lt;NAME&amp;gt; PRESENCE function {ReadingsVal(&amp;quot;&amp;lt;UniFi&amp;gt;&amp;quot;,&amp;quot;&amp;lt;NamedDevice&amp;gt;&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;connected&amp;quot; ? 1:0}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Überwachen mittels Events =&lt;br /&gt;
Der Vorteil gegenüber der Function-Variante ist, dass diese Variante ohne Blocking.pm-Overhead direkt ausgeführt werden kann und in &amp;quot;Echtzeit&amp;quot; abläuft (siehe {{Link2Forum|Topic=40287|Message=562823}}).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;define &amp;lt;NAME&amp;gt; PRESENCE event UniFi:NamedDevice:.disconnected UniFi:NamedDevice:.connected&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Überwachen mittels Bluetooth =&lt;br /&gt;
== Vorbereitung und Informationen ==&lt;br /&gt;
=== Getestete Hardware/Software ===&lt;br /&gt;
* &#039;&#039;&#039;Raspbian System&#039;&#039;&#039; - wheezy, Jessie (interner BT-Controller)&lt;br /&gt;
* &#039;&#039;&#039;BT-Dongle&#039;&#039;&#039; - CSL NET BT USB2.0 Stick, Bluetooth V4.0, Nano &amp;lt;br /&amp;gt;&#039;&#039;&#039;Achtung&#039;&#039;&#039;: Es muss ein BT V4.0 oder höher verwendet werden. Nur dieser unterstützt &#039;&#039;LowEnergy&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;BT-TAG&#039;&#039;&#039; - Gtag von Gigaset, TrackR, UDOO Neo, PebbleBee, iTag von Unitec, X4-LIFE Multifunkti BL-Anhänger, iTag Wireless Anti, Trackr bravo&lt;br /&gt;
&lt;br /&gt;
=== BT Dongel am PI installieren ===&lt;br /&gt;
Um den BT Dongle &#039;&#039;(hier: CSL NET BT USB2.0)&#039;&#039; am PI verwenden zu können, müssen die notwendigen Pakete über die Paketverwaltung von debain nachinstalliert werden.&lt;br /&gt;
Wer bereits ein BT-Dongle installiert hat, kann diesen Schritt überspringen.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt-get install bluetooth&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Nach erfolgreicher Installation der Pakete sollte der RaspberryPI neu gestartet werden.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nach dem erfolgten Reboot bitte das Log des Raspberry auf folgende Einträge prüfen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Feb 12 19:52:55 fhem kernel: [    4.773600] Bluetooth: Core ver 2.20&lt;br /&gt;
Feb 12 19:52:55 fhem kernel: [    4.773748] NET: Registered protocol family 31&lt;br /&gt;
Feb 12 19:52:55 fhem kernel: [    4.773765] Bluetooth: HCI device and connection manager initialized&lt;br /&gt;
Feb 12 19:52:55 fhem kernel: [    4.773797] Bluetooth: HCI socket layer initialized&lt;br /&gt;
Feb 12 19:52:55 fhem kernel: [    4.773821] Bluetooth: L2CAP socket layer initialized&lt;br /&gt;
Feb 12 19:52:55 fhem kernel: [    4.773890] Bluetooth: SCO socket layer initialized&lt;br /&gt;
Feb 12 19:52:55 fhem kernel: [    4.797531] usbcore: registered new interface driver btusb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sobald der BT-Dongle erkannt wurde &#039;&#039;leuchtet&#039;&#039; (wenn vorhanden) auch die &#039;&#039;blaue/gelbe&#039;&#039; LED am Dongle auf.&lt;br /&gt;
&lt;br /&gt;
=== BT-Tags aktivieren ===&lt;br /&gt;
Jetzt kann der BT-Tag aktiviert werden. Bei einigen Tags muss dafür die &#039;&#039;&#039;Batteriesicherung&#039;&#039;&#039; gezogen werden.&lt;br /&gt;
&lt;br /&gt;
Einen Tag wird mit folgendem Befehl auf der Konsole gesucht:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo hcitool lescan&lt;br /&gt;
&lt;br /&gt;
Ausgabe z.B.:&lt;br /&gt;
LE Scan ...&lt;br /&gt;
7C:2F:80:A1:XA:XD (unknown)&lt;br /&gt;
7C:2F:80:A1:XA:XD Gigaset G-tag&lt;br /&gt;
7C:2F:80:A1:X4:X1 (unknown)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Eine Übersicht über die möglichen Befehle von hcitool gibt es mit der Eingabe von:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo hcitool&lt;br /&gt;
&lt;br /&gt;
Ausgabe z.B.:&lt;br /&gt;
hcitool - HCI Tool ver 5.23&lt;br /&gt;
Usage:&lt;br /&gt;
        hcitool [options] &amp;lt;command&amp;gt; [command parameters]&lt;br /&gt;
Options:&lt;br /&gt;
        --help  Display help&lt;br /&gt;
        -i dev  HCI device&lt;br /&gt;
Commands:&lt;br /&gt;
        dev     Display local devices&lt;br /&gt;
        inq     Inquire remote devices&lt;br /&gt;
        scan    Scan for remote devices&lt;br /&gt;
        name    Get name from remote device&lt;br /&gt;
        info    Get information from remote device&lt;br /&gt;
        spinq   Start periodic inquiry&lt;br /&gt;
        epinq   Exit periodic inquiry&lt;br /&gt;
        cmd     Submit arbitrary HCI commands&lt;br /&gt;
        con     Display active connections&lt;br /&gt;
        cc      Create connection to remote device&lt;br /&gt;
        dc      Disconnect from remote device&lt;br /&gt;
        sr      Switch master/slave role&lt;br /&gt;
        cpt     Change connection packet type&lt;br /&gt;
        rssi    Display connection RSSI&lt;br /&gt;
        lq      Display link quality&lt;br /&gt;
        tpl     Display transmit power level&lt;br /&gt;
        afh     Display AFH channel map&lt;br /&gt;
        lp      Set/display link policy settings&lt;br /&gt;
        lst     Set/display link supervision timeout&lt;br /&gt;
        auth    Request authentication&lt;br /&gt;
        enc     Set connection encryption&lt;br /&gt;
        key     Change connection link key&lt;br /&gt;
        clkoff  Read clock offset&lt;br /&gt;
        clock   Read local or remote clock&lt;br /&gt;
        lescan  Start LE scan&lt;br /&gt;
        lewladd Add device to LE White List&lt;br /&gt;
        lewlrm  Remove device from LE White List&lt;br /&gt;
        lewlsz  Read size of LE White List&lt;br /&gt;
        lewlclr Clear LE White list&lt;br /&gt;
        lecc    Create a LE Connection&lt;br /&gt;
        ledc    Disconnect a LE Connection&lt;br /&gt;
        lecup   LE Connection Update &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Falls beim SCAN kein Tag gefunden wird, sollte das BT Interface neu gestartet werden. Dazu ist kein Reboot des PI notwendig.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo hciconfig hci0 down&lt;br /&gt;
sudo hciconfig hci0 up&lt;br /&gt;
sudo hcitool dev&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Überwachung durch den FHEM Server direkt ==&lt;br /&gt;
[[Datei:Bluetooth-Adresse-iPhone.png|thumb|Bluetooth-Adresse eines iPhones]]&lt;br /&gt;
Jenach Aufstellungsort des FHEM Servers kann es sinnvoll sein, eine Bluetooth-Überwachung direkt durch den FHEM Server durchzuführen. Hierbei gilt allerdings zu beachten, dass Bluetooth nicht für große Reichweiten gedacht ist und in den meisten Fällen keine Wände überwinden kann. Das heisst, dass in den meisten Fällen damit nur ein Raum überwacht werden kann.&lt;br /&gt;
&lt;br /&gt;
Je nach Einsatzzweck kann das auch so gewollt sein. Bluetooth USB Sticks, die bereits Bluetooth 4.0 unterstützen, können höhere Reichweiten über Zimmerwände hinaus erreichen. Vorausgesetzt, das Mobilgerät unterstützt Bluetooth 4.0.&lt;br /&gt;
&lt;br /&gt;
Um eine Überwachung per Bluetooth durchführen zu können, benötigt man die Bluetooth-Adresse eines Gerätes. Diese ähnelt vom Aufbau einer MAC-Adresse. Generell wird die Adresse in den Telefon-Informationen bei Smartphones angezeigt.&lt;br /&gt;
&lt;br /&gt;
Um eine Anwesenheitserkennung via Bluetooth durchzuführen, wird folgende Definition in der [[Konfiguration]] benötigt:&lt;br /&gt;
:&amp;lt;code&amp;gt;define Handy PRESENCE local-bluetooth XX:XX:XX:XX:XX:XX&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Überwachung durch verteilte Agenten in der Wohnung (presenced/lepresenced/collectord) ==&lt;br /&gt;
[[Datei:Raspberry-Pi-mit-WLAN-und-Bluetooth-Stick.jpg|thumb|left|Raspberry Pi mit Bluetooth- und WLAN-USB-Stick]]&lt;br /&gt;
Um eine zuverlässige und flächendeckende Bluetooth-Anwesenheitserkennung durchzuführen, ist es unerlässlich, mehrere Bluetooth-Empfänger zu verwenden, die auf mehrere oder alle Räume verteilt sind.&lt;br /&gt;
&lt;br /&gt;
Hierfür bietet sich zum Beispiel ein [[Raspberry Pi]] mit einem Mini-Bluetooth-USB-Stick und evtl. einem WLAN-USB-Stick an. Jeder Raum wird mit solch einem Raspberry ausgestattet und ist im WLAN Netz verfügbar.&lt;br /&gt;
&lt;br /&gt;
Dieses Netz aus Raspberrys wird mit dem presenced / lepresenced Programm ausgestattet. Beide Programme sind Perl-Skripte, die als Daemon im Hintergrund laufen und auf Anfragen via Netzwerk warten. Es wird lediglich eine vollständige Perl-Grundinstallation mit Standardmodulen benötigt.&lt;br /&gt;
&lt;br /&gt;
=== Unterschied presenced / lepresenced / collectored ===&lt;br /&gt;
presenced und lepresenced sind Programme, welche in regelmäßigen Abständen nach Bluetooth-Geräten suchen. Sobald ein Gerät, welches vorab definiert wurde, gefunden wird, wechselt der Status des Geräts in FHEM auf Anwesend. Der Unterschied zwischen presenced und lepresenced ist, dass lepresenced insbesondere für [https://de.wikipedia.org/wiki/Bluetooth_Low_Energy Bluetooth-LE-Devices] ist und presenced für &amp;quot;normale&amp;quot; Bluetooth-Geräte. &lt;br /&gt;
&lt;br /&gt;
collectored wiederum ist ein Programm, welches mehrere Pis verbindet und auf allen den aktuellen Status von presenced/lepresenced abfragt. Ist das gesuchte Bluetooth-Gerät auf einem der Pi anwesend, so wird es auch in der definierten Hauptinstanz auf anwesend gesetzt. Zusätzlich wird der Pi auf dem das Gerät gefunden wurde als Reading angegeben.&lt;br /&gt;
&lt;br /&gt;
=== Installation von (le)presenced ===&lt;br /&gt;
Diese Anleitung ist sowohl für presenced, als auch für lepresenced gültig. Einfachheitshalber wird nur lepresenced erwähnt, sämtliche Schritte gehen jedoch auch mit presenced, wobei einfach die genannten Daten durch presenced ersetzt werden müssen.&lt;br /&gt;
&lt;br /&gt;
Die Software lepresenced kann aktuell über drei Varianten installiert werden. Dabei ist die bevorzugte Variante (Variante 1) die Installation über das bereitgestellte .deb-Paket.&lt;br /&gt;
Die Variante 2 setzt voraus, dass im FHEM contrib Verzeichnis (/opt/fhem/contrib) die aktuelle Version des .deb-Pakets liegt. Die Variante 3 ist dafür gedacht, wenn man keine .deb-Pakete installieren kann/will oder es aus anderen Gründen nicht funktioniert. Es wird davon abgeraten die Variante 3 zu verwenden. Vollständigkeitshalber wird sie aber aufgeführt.&lt;br /&gt;
&lt;br /&gt;
===== Installation per .deb-Paket =====&lt;br /&gt;
&lt;br /&gt;
Die bevorzugte Variante ist die Installation von lepresenced durch die passenden .deb Pakete.&lt;br /&gt;
{{Randnotiz|RNText=Bei einem Upgrade einer älteren Version reicht es, das neue .deb Paket mit&lt;br /&gt;
:&amp;lt;code&amp;gt;sudo dpkg -i lepresenced-X.XX-X.deb&amp;lt;/code&amp;gt;&lt;br /&gt;
zu aktualisieren}} &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;1.Variante:&#039;&#039;&#039;&lt;br /&gt;
Herunterladen der aktuellen lepresenced-0.83-3.deb (Stand August 2017) Datei über den Webbrowser &lt;br /&gt;
[https://svn.fhem.de/trac/export/HEAD/trunk/fhem/contrib/PRESENCE/deb/ SVN-Repository]. Im SVN die passende Datei auswählen und in der folgende Webseite den Link unter:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Download in other formats:&lt;br /&gt;
    Original Format &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
anklicken und die Datei herunterladen.&lt;br /&gt;
Die Datei kann jetzt auf den RPi kopiert und mit folgenden Befehlen ausgeführt werden (ggf. Berechtigungen anpassen). &lt;br /&gt;
&lt;br /&gt;
Alternativ per wget Befehl direkt auf den RPi (aktuelle Versionsnummer beachten)&lt;br /&gt;
 https://svn.fhem.de/trac/export/HEAD/trunk/fhem/contrib/PRESENCE/deb/lepresenced-0.83-3.deb&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;2.Variante:&#039;&#039;&#039; (zu Verwenden, wenn es Probleme bei Variante 1 gibt)&lt;br /&gt;
Herunterladen aus dem fhem contrib Verzeichnis:&lt;br /&gt;
Hierzu muss das contrib auf dem aktuellen Stand sein. Dazu wird die Installation von subversion (normal bereits vorhanden) benötigt.&lt;br /&gt;
&lt;br /&gt;
 sudo apt-get install subversion&lt;br /&gt;
&lt;br /&gt;
Danach kann per &lt;br /&gt;
 sudo svn checkout https://svn.fhem.de/fhem/trunk/fhem/contrib svnrepo&lt;br /&gt;
&lt;br /&gt;
Das aktuelle Repository auf den Pi heruntergeladen werden. Danach sollte im gewählten Verzeichnis die eingecheckten Dateien verfügbar sein.&lt;br /&gt;
 /opt/fhem/svnrepo/PRESENCE/deb  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039; Installation der Variante 1 oder 2 &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Egal welche Variante gewählt wurde, nun kann mit folgenden Befehlen das Paket installiert werden. Bitte Pfade ggf. anpassen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Wichtig&#039;&#039;&#039;: Das &#039;&#039;&#039;Paket&#039;&#039;&#039; hat eine ca. Größe von &#039;&#039;&#039;6,5Kb&#039;&#039;&#039;. Ab und an gibt es wohl Probleme mit der Installation, wodurch die Datei 11,5kb groß wird.&lt;br /&gt;
Diese Datei lässt sich nicht Installieren. In diesem Fall das Paket bitte mit der Variante 1 und dem Bereich &amp;quot;Download in other formats&amp;quot; herunterladen.&lt;br /&gt;
&lt;br /&gt;
 sudo dpkg -i lepresenced-0.83-3.deb&lt;br /&gt;
&lt;br /&gt;
 sudo apt-get -f install&lt;br /&gt;
&lt;br /&gt;
Die Ausgabe der Installation sollte am Ende ein [ ok ] Starting lepresenced (via systemctl): lepresenced.service. ausgeben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Paketlisten werden gelesen... Fertig&lt;br /&gt;
Abhängigkeitsbaum wird aufgebaut.       &lt;br /&gt;
Statusinformationen werden eingelesen.... Fertig&lt;br /&gt;
Abhängigkeiten werden korrigiert ... Fertig&lt;br /&gt;
Die folgenden zusätzlichen Pakete werden installiert:&lt;br /&gt;
  bluez-hcidump&lt;br /&gt;
Die folgenden NEUEN Pakete werden installiert:&lt;br /&gt;
  bluez-hcidump&lt;br /&gt;
0 aktualisiert, 1 neu installiert, 0 zu entfernen und 0 nicht aktualisiert.&lt;br /&gt;
1 nicht vollständig installiert oder entfernt.&lt;br /&gt;
Es müssen 157 kB an Archiven heruntergeladen werden.&lt;br /&gt;
Nach dieser Operation werden 490 kB Plattenplatz zusätzlich benutzt.&lt;br /&gt;
Möchten Sie fortfahren? [J/n]&lt;br /&gt;
Holen: 1 http://archive.raspberrypi.org/debian/ jessie/main bluez-hcidump armhf 5.23-2+rpi2 [157 kB]&lt;br /&gt;
Es wurden 157 kB in 0 s geholt (921 kB/s).&lt;br /&gt;
Vormals nicht ausgewähltes Paket bluez-hcidump wird gewählt.&lt;br /&gt;
(Lese Datenbank ... 42033 Dateien und Verzeichnisse sind derzeit installiert.)&lt;br /&gt;
Vorbereitung zum Entpacken von .../bluez-hcidump_5.23-2+rpi2_armhf.deb ...&lt;br /&gt;
Entpacken von bluez-hcidump (5.23-2+rpi2) ...&lt;br /&gt;
Trigger für man-db (2.7.0.2-5) werden verarbeitet ...&lt;br /&gt;
bluez-hcidump (5.23-2+rpi2) wird eingerichtet ...&lt;br /&gt;
lepresenced (0.82-1) wird eingerichtet ...&lt;br /&gt;
[ ok ] Starting lepresenced (via systemctl): lepresenced.service.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;3.Variante:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Bei dieser Variante wird das aktuellste lepresenced Skript aus github heruntergeladen. Das bedeutet, dass jegliche Konfiguration wie automatischer Start, Berechtigungen etc. &lt;br /&gt;
manuell konfiguriert werden muss. Diese Variante eignet sich nur für diejenigen, die keine .deb-Pakete installieren wollen/können oder die genau Wissen, was sie tun!&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
https://github.com/mhop/fhem-mirror/blob/master/fhem/contrib/PRESENCE/lepresenced&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zur &amp;quot;Installation&amp;quot; des Skripts folgendermaßen vorgehen:&lt;br /&gt;
Unter /fhem manuell den Ordner „script“ anlegen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir script&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Datei lepresenced reinkopieren und ausführbar machen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo chmod +x /opt/fhem/script/lepresenced&lt;br /&gt;
sudo chgrp -cR dialout lepresenced&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Skript erstmalig starten:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo ./lepresenced --loglevel LOG_EMERG -d&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Kommt beim Starten des Skript eine Fehlermeldung, müssen die Abhängigkeiten aufgelöst werden.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Can&#039;t locate Net/Server/Daemonize.pm in @INC (@INC contains: /etc/perl /usr/local/lib/perl/5.14.2 /usr/local/share/perl/5.14.2 /usr/lib/perl5 /usr/share/perl5 / usr/lib/perl/5.14 /usr/share/perl/5.14 /usr/local/lib/site_perl .) at /opt/fhem/lepresenced line 17.&lt;br /&gt;
BEGIN failed--compilation aborted at /opt/fhem/lepresenced line 17.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Um die Abhängigkeiten aufzulösen muss folgendes nachinstalliert werden und anschließend ein Reboot durchgeführt werden.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt-get install libnet-server-*&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Einrichtung eines Bluetooth-Geräts über FHEM =====&lt;br /&gt;
&lt;br /&gt;
Nach dem letzten Schritt sind alle Bedingungen für eine abschließende Konfiguration eines BT-Geräts in FHEM abgeschlossen worden.&lt;br /&gt;
Jetzt kann der zum Beispiel ein G-Tag dem FHEM-Server bekannt gemacht werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   --   Name       Modul    Modus         MAC vom Gtag  IP vom PI Port    Abfragezeit in Sekunden&lt;br /&gt;
define MeinGtAG PRESENCE lan-bluetooth xx:xx:xx:xx:xx:xx 127.0.0.1:5333    120&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Wichtig ist den angegeben Port zu unterscheiden. Für presenced muss der Port 5111 genommen werden, für lepresenced der Port 5333.&#039;&#039;&#039;&lt;br /&gt;
Den absent und present Mode kann man einfach testen, in dem man den Gtag mit Alufolie einwickelt.&lt;br /&gt;
&lt;br /&gt;
Diese Variante sollte eingesetzt werden, wenn nur ein Pi nach Bluetooth-Geräten sucht. Möchte man mehr als ein Gerät nutzen um zum Beispiel eine größere Fläche abzudecken so muss mit collectored gearbeitet werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Alle Räume gemeinsam ansprechen mittels collectord ===&lt;br /&gt;
Um zwei presenced- oder lepresenced Installationen zu verbinden wird der collectord Daemon von Markus Bloch benötigt. Dieser kennt alle presenced-Installationen im Netzwerk und führt eine koordinierte Suche nach den gewünschten Geräten durch. Sobald ein Gerät in einem Raum erkannt wurde, meldet der collectord den Status einschließlich der Angabe des Raumes, in dem das Gerät erkannt wurde.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:Presence_Collectord_Uebersicht.jpg|200px|thumb|left|Schematische Darstellung Presence und Collectord, Danke an dtavb]]&lt;br /&gt;
Auf Basis folgender Skizze wird die Einrichtung und der Betrieb der Anwesenheitserkennung und Überwachung &amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
mit dem PRESENCE-Modul sowie dem Skript (.deb-Paket) lepresenced beschrieben. Zusätzlich wird für die Verbindung &amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
mehrere lepresenced Instanzen der collectord verwendet.&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Diese Skizze dient als Basis für alle genannten Konfigurationen innerhalb dieses Artikels.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Aufbau ====&lt;br /&gt;
; RPi1 (Hautpinstanz): &lt;br /&gt;
: FHEM Installation&lt;br /&gt;
: presence/lepresenced Installation &lt;br /&gt;
: collectord installation&lt;br /&gt;
: Sämtliche Bluetooth-Geräte in FHEM definiert&lt;br /&gt;
; RPi2 (Zweitsystem): &lt;br /&gt;
: FHEM installation&lt;br /&gt;
: presence/lepresenced Installation&lt;br /&gt;
: Sämtliche Bluetooth-Geräte in FHEM definiert&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Installation per .deb-Paket ====&lt;br /&gt;
collectord wird heruntergeladen und installiert:&lt;br /&gt;
https://svn.fhem.de/trac/export/HEAD/trunk/fhem/contrib/PRESENCE/deb/collectord-1.7.deb (Stand Januar 2017)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo dpkg -i collectord-1.7.deb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nach der Installation befindet sich im Verzeichnis: /etc/collectord.conf die Konfigurationsdatei für das collectord.&lt;br /&gt;
&lt;br /&gt;
==== Konfiguration auf Shellebene ==== &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo vi /etc/collectord.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Datei muss jetzt nach folgender Vorlage angepasst werden.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# room definition&lt;br /&gt;
#[room-name]              # name of the room&lt;br /&gt;
#address=192.168.0.10     # ip-address or hostname&lt;br /&gt;
#port=5111                # tcp port which should be used (5111 is default)&lt;br /&gt;
#presence_timeout=120     # timeout in seconds for each check when devices are present&lt;br /&gt;
#absence_timeout=20       # timeout in secondsfor each check when devices are absent&lt;br /&gt;
&lt;br /&gt;
[RPi1] 			          # Name (wird als Reading room bei den BT-Tags angezeigt) der presence Instanze&lt;br /&gt;
address=127.0.0.1 	          # Lokale Adresse RPi1 , da hier das Collectord später laufen soll!&lt;br /&gt;
port=5333		          # Port der Presence Installation &lt;br /&gt;
presence_timeout=60		  # Selbstgewaelte Pruefintervalle&lt;br /&gt;
absence_timeout=60		  # Selbstgewaelte Pruefintervalle&lt;br /&gt;
&lt;br /&gt;
[RPi2]  		          # Name (wird als Reading room bei den BT-Tags angezeigt) der presence Instanze&lt;br /&gt;
address=192.168.178.127	          # IP-Adresse der Instanz, wo nur das Presence laueft, also RPi2&lt;br /&gt;
port=5333		          # Port der Presence Installation &lt;br /&gt;
presence_timeout=60		  # Selbstgewaelte Pruefintervalle&lt;br /&gt;
absence_timeout=60		  # Selbstgewaelte Pruefintervalle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hinweis: &lt;br /&gt;
* Es dürfen keine [Namen] mit Leerzeichen verwendet werden&lt;br /&gt;
* Der angegebene Port richtet sich danach, ob auf dem Pi presenced (Port 5111) oder lepresenced (Port 5333) nach dem Bluetooth-Gerät sucht&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Konfiguration in FHEM ==== &lt;br /&gt;
;RPi1&lt;br /&gt;
:define Gtag PRESENCE lan-bluetooth XX:XX:XX:XX:XX:XX 127.0.0.1:5222 60 Hinweis: (Der Port ist der, des Collectord!! Standard 5222)&lt;br /&gt;
;RPi2&lt;br /&gt;
:define Gtag PRESENCE lan-bluetooth XX:XX:XX:XX:XX:XX 192.168.178.127:5222 60 Hinweis: (Der Port ist der, des Collectord!! Standard 5222 - die IP-Adresse von die von RPi1)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nach der Konfiguration kann der Daemon gestartet werden.&lt;br /&gt;
Sobald das Bluetoothgerät irgendwo in der Wohnung erkannt wurde, meldet der Collectord dies sofort &lt;br /&gt;
an FHEM und teilt den Raum mit in dem es erkannt worden ist. Diese Information wird im Reading &amp;quot;rooms&amp;quot; des jeweiligen BT-Gerätes dargestellt.&lt;br /&gt;
&lt;br /&gt;
Zum testen sollte collectored einmalig manuell gestartet werden. Dies hat den Vorteil, dass man nochmal den Port des collectored prüfen kann, dieser steht in der Zeile &amp;lt;pre&amp;gt;created socket on 0.0.0.0 with port 5333&amp;lt;/pre&amp;gt; und man sehen kann, ob der collectored richtig startet, oder Fehler auswirft. Gestartet wird mit folgendem Kommando:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo /usr/bin/perl /usr/sbin/collectord -vv -c /etc/collectord.conf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Die Ausgabe sieht wie folgt aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2017-04-02 17:52:55 - =================================================&lt;br /&gt;
2017-04-02 17:52:55 - started with PID 15554&lt;br /&gt;
2017-04-02 17:52:55 - reading configuration file&lt;br /&gt;
2017-04-02 17:52:55 - no config errors found&lt;br /&gt;
2017-04-02 17:52:55 - forked with PID 15556&lt;br /&gt;
2017-04-02 17:52:56 - created socket on 0.0.0.0 with port 5333&lt;br /&gt;
2017-04-02 17:53:20 - new connection from 127.0.0.1:48656&lt;br /&gt;
2017-04-02 17:53:20 - created thread 1 for processing device 7C:2F:80:E1:14:31 in room RPi2 for peer 127.0.0.1 (UUID: d0beb79dd4771532eb5e207c7bf31788)&lt;br /&gt;
2017-04-02 17:53:20 - created thread 2 for processing device 7C:2F:80:E1:14:31 in room RPi1 for peer 127.0.0.1 (UUID: d0beb79dd4771532eb5e207c7bf31788)&lt;br /&gt;
2017-04-02 17:53:20 - new connection from 127.0.0.1:48662&lt;br /&gt;
2017-04-02 17:53:20 - new connection from 127.0.0.1:48664&lt;br /&gt;
2017-04-02 17:53:20 - created thread 3 for processing device 7C:2F:80:ED:BC:F7 in room RPi2 for peer 127.0.0.1 (UUID: 7495a112063d5db45e6335d3fe305e36)&lt;br /&gt;
2017-04-02 17:53:20 - created thread 4 for processing device 7C:2F:80:ED:BC:F7 in room RPi1 for peer 127.0.0.1 (UUID: 7495a112063d5db45e6335d3fe305e36)&lt;br /&gt;
2017-04-02 17:53:20 - created thread 5 for processing device 7C:2F:80:E1:2A:4D in room RPi2 for peer 127.0.0.1 (UUID: c228f8d4d33b06787f995c7903c02760)&lt;br /&gt;
2017-04-02 17:53:20 - created thread 6 for processing device 7C:2F:80:E1:2A:4D in room RPi1 for peer 127.0.0.1 (UUID: c228f8d4d33b06787f995c7903c02760)&lt;br /&gt;
2017-04-02 17:53:22 - new connection from 192.168.xxx.xxx:51638&lt;br /&gt;
2017-04-02 17:53:22 - created thread 7 for processing device 7C:2F:80:E1:14:31 in room RPi2 for peer 192.168.xxx.xxx (UUID: 5db7012e709d6dc2fcd8159fc0344e40)&lt;br /&gt;
2017-04-02 17:53:22 - created thread 8 for processing device 7C:2F:80:E1:14:31 in room RPi1 for peer 192.168.xxx.xxx (UUID: 5db7012e709d6dc2fcd8159fc0344e40)&lt;br /&gt;
2017-04-02 17:53:22 - new connection from 192.168.xxx.xxx:51640&lt;br /&gt;
2017-04-02 17:53:22 - created thread 9 for processing device 7C:2F:80:ED:BC:F7 in room RPi2 for peer 192.168.xxx.xxx (UUID: c4b4d7c654132cf88e8c1fec3a956d3d)&lt;br /&gt;
2017-04-02 17:53:23 - created thread 10 for processing device 7C:2F:80:ED:BC:F7 in room RPi1 for peer 192.168.xxx.xxx (UUID: c4b4d7c654132cf88e8c1fec3a956d3d)&lt;br /&gt;
2017-04-02 17:53:29 - new connection from 192.168.xxx.xxx:51642&lt;br /&gt;
2017-04-02 17:53:29 - created thread 11 for processing device 7C:2F:80:E1:2A:4D in room RPi2 for peer 192.168.xxx.xxx (UUID: ecd7081e5ae3a0d8e735c8750cb116a1)&lt;br /&gt;
2017-04-02 17:53:29 - created thread 12 for processing device 7C:2F:80:E1:2A:4D in room RPi1 for peer 192.168.xxx.xxx (UUID: ecd7081e5ae3a0d8e735c8750cb116a1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn das Log wie oben abgebildet aussieht wurde alles richtig gemacht und unter dem Device in FHEM erscheint ein neues Reading &amp;quot;rooms&amp;quot; mit dem Wert der Erkannten PRESENCE Installation.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Verhalten presence timeout im zusammenhang mit dem Attribut &amp;quot;absenceThreshold&amp;quot; der PRESENCE Konfiguration in FHEM&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
In der collectord.conf sind presence_timeout und absence_timeout für den jeweiligen Raum konfiguriert.&lt;br /&gt;
Das bedeutet, sobald irgendein Gerät in diesem jeweiligen Raum anwesend/abwesend ist, wird das jeweilige Timeout an den verbundenen presenced/lepresenced geschickt um damit das Check-Interval entsprechend zu ändern.&lt;br /&gt;
&lt;br /&gt;
In der PRESENCE-Definition kann man ebenfalls ein absence_timeout/presence_timeout setzen. Sobald sich der Zustand ändert,&lt;br /&gt;
wird auch das jeweilige Timeout an den collectord gesandt. Dies hat aber auf die Checks in den jeweiligen Räumen und damit der collectord.conf keinen Einfluss.&lt;br /&gt;
Der collectord schickt ein Statusupdate an PRESENCE nur, wenn das vorgegebene Timeout (von PRESENCE) erreicht ist und keine Statusänderung stattfand.&lt;br /&gt;
Sobald eine Änderung des Status erfolgt wird natürlich sofort der Status an PRESENCE geschickt.&lt;br /&gt;
&lt;br /&gt;
Das Attribut absenceThreshold/presenceThreshold funktioniert nachwievor. Hier ist nur wichtig wie man die Timeouts sowohl in PRESENCE als auch collectord.conf setzt.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Das Reading &amp;quot;room&amp;quot; bei einer PRESENCE Definition und der Zusammenhang zu collectord&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Wenn ein BT LE Empfänger in mehr als einem Raum detektiert wird, führt der aktuellste collectord (aus dem SVN) eine RSSI-Erkennung durch. Sofern alle Räume den Empfangspegel (RSSI) ermitteln können, wird der Raum mit dem besten Empfangspegel als Raum für das &amp;quot;room&amp;quot;-Reading ausgewählt. Der lepresenced in aktueller Version von PatrickR gibt immer den Empfangspegel aus.&lt;br /&gt;
&lt;br /&gt;
====  Automatischer Start ====&lt;br /&gt;
Wenn das Collectord per .deb Paket installiert wurde, startet es automatisch bei einem Reboot mit.&lt;br /&gt;
Manuell Starten als Daemon mit:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo /usr/bin/perl /usr/sbin/collectord -c /etc/collectord.conf -d -v -l /var/log/collectord.log&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Batterieüberwachung ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Batterieüberwachung mit dem Modul BleTagBattery ===&lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=Anwesenheitserkennung&lt;br /&gt;
|ModType=h&lt;br /&gt;
&amp;lt;!-- |ModCmdRef= --&amp;gt;&lt;br /&gt;
|ModTechName=74_BleTagBattery&lt;br /&gt;
|ModOwner=mumpitzstuff&lt;br /&gt;
}}&lt;br /&gt;
Mit dem Modul BleTagBattery - können die Batteriestati aller BT-LE Devices gelesen werden.&lt;br /&gt;
Es wird das batteryLevel und battery angelegt welches als BT-LE Tags an einer PRESENCE-Installation registriert wurden.&lt;br /&gt;
&lt;br /&gt;
Vorraussetzung und Installation:&lt;br /&gt;
&lt;br /&gt;
Bluez und Gattool&lt;br /&gt;
 sudo apt-get install bluez&lt;br /&gt;
&lt;br /&gt;
Das Gattool ist in den Installationen von Bluez inbegriffen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hinzufügen des githup für das Modul&lt;br /&gt;
 update add http://raw.githubusercontent.com/mumpitzstuff/fhem-BleTagBattery/master/controls_bletagbattery.txt&lt;br /&gt;
 update all&lt;br /&gt;
 restart fhem: shutdown restart&lt;br /&gt;
 BT-LE tags muss an einer PRESENCE-Installation des type &amp;quot;lan-bluetooth&amp;quot; registriert sein.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nach dem Neustart von FHEM kann das Modul definiert werden:&lt;br /&gt;
 define a new device: define &amp;lt;name of device&amp;gt; BleTagBattery&lt;br /&gt;
&lt;br /&gt;
Das Modul versucht in der Standardkonfiguration alle 6 Stunden die BT-LE Devices zu erreichen und das Reading batteryLevel und battery zu aktualisieren.&lt;br /&gt;
Das Update kann auch manuell mit dem folgenden Befehl erzwungen werden&lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;name of device&amp;gt; statusRequest.&lt;br /&gt;
&lt;br /&gt;
Weiter Informationen und Disskussionen können dem eigentlichen [https://forum.fhem.de/index.php?topic=68104.0 Forumsbeitrag] entnommen werden,&lt;br /&gt;
&lt;br /&gt;
=== Batterieüberwachung (aktuell nur G-Tags) ===&lt;br /&gt;
&lt;br /&gt;
Leider überträgt der G-Tag nach der Einrichtung als Device in FHEM kein Reading mit seinem aktuellen Batteriestatus.&lt;br /&gt;
Dem wurde mit Hilfe des Forum Abhilfe geschaffen.&lt;br /&gt;
Im Folgenden wird erläutert wie die Batterieüberwachung eingerichtet werden kann.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Voraussetzung:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
bc - Basiscalculator [https://packages.debian.org/de/sid/bc Bc-Paket]&lt;br /&gt;
&amp;lt;pre&amp;gt; sudo apt-get install bc &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Anlegen eines Shellskript auf dem Raspberry System. &lt;br /&gt;
Die Parameter &amp;lt;&amp;lt;MAC-Adresse&amp;gt;&amp;gt; und &amp;lt;&amp;lt;TagName&amp;gt;&amp;gt; müssen durch die Werte des auszulesenden G-Tags ersetzt werden.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
stringZ=$(sudo gatttool -b 5C:2B:80:C1:14:41 --char-read --handle=0x001b)&lt;br /&gt;
stringZ=${stringZ:33:2}&lt;br /&gt;
stringZ=$(echo &amp;quot;$stringZ&amp;quot; | tr a-f A-F)&lt;br /&gt;
decimal=$(echo &amp;quot;ibase=16; $stringZ&amp;quot; | bc)&lt;br /&gt;
perl /opt/fhem/fhem.pl 7072 &amp;quot;setreading MeinGtag Batterie $decimal&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dem Device in FHEM (hier MeinGtag) ein userReading mit dem Namen &#039;&#039;&#039;Batterie&#039;&#039;&#039; hinzufügen.&lt;br /&gt;
Das Shellskript mit folgendem Befehl starten:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./GtagBatterie.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wichtig ist hierbei,&#039;&#039;&#039; dass Skript mit &amp;quot;./&amp;quot; und nicht mit &amp;quot;sh&amp;quot; aufzurufen. Beim Aufruf mit &amp;quot;sh GtagBatterie.sh&amp;quot; produziert es einen Fehler&lt;br /&gt;
&amp;lt;pre&amp;gt;GtagBatterie.sh: 3: GtagBatterie.sh: Bad substitution &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Reading wird auf den ausgelesenen Wert der Batterie gesetzt. &lt;br /&gt;
&lt;br /&gt;
Hinweis: Es sollte für jeden G-Tag ein eigenes Skript abgelegt werden. Das Skript kann per crontab oder fhem Kommando (system) regelmäßig aufgerufen werden.&lt;br /&gt;
&lt;br /&gt;
=== Batterieüberwachung (alle Devices vom Typ &amp;quot;MODE=lan-bluetooth&amp;quot;) ===&lt;br /&gt;
&lt;br /&gt;
Es gibt eine weitere Möglichkeit um den Batteriestatus von LE Devices abzurufen und in FHEM als Reading darzustellen.&lt;br /&gt;
Dabei wird der Batteriezustand für alle LE Devices, die bereits in FHEM konfiguriert sind und per lepresenced überwacht werden, automatisch in einem shell-Script ermittelt.&lt;br /&gt;
Näheres dazu im Forumartikel {{Link2Forum|Topic=56960|LinkText=Erweiterung: Anwesenheitserkennung/Batterieüberwachung}}.&lt;br /&gt;
&lt;br /&gt;
Vorteile:&lt;br /&gt;
* Automatische Ermittlung aller in FHEM konfigurierten LE Devices&lt;br /&gt;
* Möglichkeit, diese Devices alternativ manuell im Script einzutragen&lt;br /&gt;
* Es werden nur Devices abgefragt, die im Status &amp;quot;present&amp;quot; sind, also mit ziemlicher Sicherheit auch verfügbar sind&lt;br /&gt;
* Ein eventuell auf dem FHEM telnet-Port gesetztes Passwort kann im Script hinterlegt werden&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Voraussetzung:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Funktionierendes lepresenced&#039;&#039;&#039; - siehe [[Anwesenheitserkennung#Anleitung_f.C3.BCr_ein_LE_Device_.28z.B._Gtags.2CPebbles_etc..29|Anleitung für ein LE Device (z.B. Gtags,Pebbles etc.)]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;socat&#039;&#039;&#039; - TCP port forwarder&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt-get update &amp;amp;&amp;amp; sudo apt-get install socat&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;gawk&#039;&#039;&#039; - Zum extrahieren der Daten&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt-get update &amp;amp;&amp;amp; sudo apt-get install gawk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;gatttool&#039;&#039;&#039; - Bestandteil von bluez &lt;br /&gt;
&lt;br /&gt;
gatttool ist auf den meisten Distributionen im bluez-Paket, allerdings nicht bei Opensuse. Dort muss man das Sourcepaket von bluez installieren und selbst kompilieren.&lt;br /&gt;
gatttool sollte dann nach /usr/bin oder /usr/local/bin kopiert werden,&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zusätzlich zu den notwendigen Erweiterungen werden für die Ausführung von gatttool &#039;&#039;&#039;Root-Rechte benötigt&#039;&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
Das Script selbst gibt es hier: [https://raw.githubusercontent.com/micky0867/lebattery/master/lebattery lebattery]&lt;br /&gt;
&lt;br /&gt;
Am Besten unter /opt/fhem/script/lebattery speichern und ausführbar machen:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo su -&lt;br /&gt;
mkdir /opt/fhem/script&lt;br /&gt;
cd /opt/fhem/script&lt;br /&gt;
wget https://raw.githubusercontent.com/micky0867/lebattery/master/lebattery&lt;br /&gt;
chmod 755 lebattery&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Je nach Bedarf können im Script noch die folgenden 3 Parameter angepasst werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# If allowed_telnetPort is protected by a password, add the password here&lt;br /&gt;
TELNETPASSWORD=&amp;quot;&amp;quot;&lt;br /&gt;
# Attribute for batterylevel in FHEM&lt;br /&gt;
ATTRIBUT=&amp;quot;batterylevel&amp;quot;&lt;br /&gt;
# Use this, if you dont want the script to determine the tags on its own&lt;br /&gt;
LETAGS=&amp;quot;&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Skript wird dann unter root folgendermaßen gestartet:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/opt/fhem/script/lebattery -v&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ausgabe des Skripts, wenn es mit dem Verbose Parameter -v gestartet wird.&lt;br /&gt;
&lt;br /&gt;
Beide Devices sind vom Typ NUT mini, das Device mit dem FHEM-Namen &#039;&#039;&#039;nut_Micky&#039;&#039;&#039; ist im Status &#039;&#039;&#039;absent&#039;&#039;&#039;. Das zweite Device ist im Status &#039;&#039;&#039;present&#039;&#039;&#039;.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Determining address for nut_Micky ...&lt;br /&gt;
nut_Micky is in state absent, no further action required&lt;br /&gt;
&lt;br /&gt;
Determining address for nut_Test ...&lt;br /&gt;
Fetching batterylevel for nut_Test (F3:44:04:81:54:89) ...&lt;br /&gt;
Setting batterylevel for nut_Test to 100%&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mein crontab-Eintrag (User root) sieht so aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
3 3  * * * /opt/fhem/script/lebattery -v &amp;gt;/opt/fhem/script/lebattery.log 2&amp;gt;&amp;amp;1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Damit wird jeden Morgen um 3 Minuten nach 3 Uhr der Zustand der Batterien aller Devices ermittelt und in FHEM abgespeichert.&amp;lt;br&amp;gt; &lt;br /&gt;
Bevor man das mit crontab macht, sollte man allerdings zunächst sicher stellen, dass es auch ohne crontab funktioniert....&lt;br /&gt;
&lt;br /&gt;
Bei Problemen kann man auch erstmal schauen, ob das mit dem gattool überhaupt funktioniert:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gatttool -t &amp;lt;Typ&amp;gt; -b &amp;lt;MAC-Adresse&amp;gt; --char-read --uuid 0x2a19&lt;br /&gt;
&lt;br /&gt;
handle: 0x0017 	 value: 64&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In diesem Fall hat die Batterie noch 100% (hex 64).&amp;lt;br&amp;gt;&lt;br /&gt;
Der Typ ist abhängig vom Hersteller und kann public (G-Tags) bzw. random (Nut) sein. Im Zweifelsfall beides ausprobieren.&lt;br /&gt;
&lt;br /&gt;
= Beispiele =&lt;br /&gt;
==  Anwesenheitserkennung / Anwesenheitsbenachrichtigung mit G-Tags ==&lt;br /&gt;
Ein Skript zur Nutzung der Gigaset G-TAGs zur Alarmierung bei öffnen und schließen von Türen und zur Anwesenheitserkennung, um die Alarmierung zu aktivieren bzw. deaktivieren. &lt;br /&gt;
Es kann verwendet werden um die Anwesenheit von mehrern Personen im Haushalt zu erkennen. Dabei wird eingeschränkt, dass nur bestimmte Personen die Alarmierung aktivieren können ( Eltern/Kind -Beziehung ).&lt;br /&gt;
Des Weiteren werden im Beispiel die Eltern benachrichtigt wenn eins der Kinder das Haus verlässt und die Eltern nicht anwesend sind.&lt;br /&gt;
&lt;br /&gt;
{{Randnotiz|RNText=Namen der G-Tags in den Skripten bitte anpassen!}}&lt;br /&gt;
&lt;br /&gt;
Für die &#039;&#039;Notify&#039;&#039; und die &#039;&#039;RESIDENTS-Erweiterung&#039;&#039; wird ein Dummy benötigt.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Alarm dummy&lt;br /&gt;
attr Alarm devStateIcon aktiv:secur_locked@red inaktiv:secur_open@lightgreen&lt;br /&gt;
attr Alarm eventMap on:aktiv off:inaktiv&lt;br /&gt;
attr Alarm setList on off&lt;br /&gt;
attr Alarm webCmd aktiv:inaktiv&lt;br /&gt;
attr Alarm room Alarm&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Mit Notify ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gtag.*.presence:.* {Anwesenheit_check(&amp;quot;$EVTPART1&amp;quot;, &amp;quot;$NAME&amp;quot;)}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Code für die 99_myUtils.pm&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
### GTAG ANWESENHEITS CHECK&lt;br /&gt;
sub Anwesenheit_check($$) {&lt;br /&gt;
my ($EVENT, $NAME) = @_;&lt;br /&gt;
&lt;br /&gt;
# gtag_rot	-	Alias Marco&lt;br /&gt;
# gtag_schwarz	-	Alias Ulli&lt;br /&gt;
# gtag_gruen	-	Alias Frida&lt;br /&gt;
# gtag_orange	-	Alias Hannah&lt;br /&gt;
&lt;br /&gt;
my $RESIDENT = &amp;quot;rr_&amp;quot;; # Alle GTAGs sind Standardmäßig Residents Roommate&lt;br /&gt;
# $RESIDENT = &amp;quot;rg_&amp;quot; if (($NAME eq &amp;quot;gtag_orange&amp;quot;) xor ($NAME eq &amp;quot;gtag_weis&amp;quot;)); # Hier nur Gäste (Roomguest) Auskommentiert, da ich es so nicht brauche&lt;br /&gt;
my $ROOMMATE = (&amp;quot;$RESIDENT&amp;quot; . &amp;quot;$NAME&amp;quot;); # Residentsname zusammenbauen&lt;br /&gt;
my $ALIASNAME = AttrVal($ROOMMATE,&#039;alias&#039;,$ROOMMATE); # ALIAS des Roommates auslesen&lt;br /&gt;
&lt;br /&gt;
my $GTAG1 = Value(&#039;gtag_rot&#039;); # ELTERN&lt;br /&gt;
my $GTAG2 = Value(&#039;gtag_schwarz&#039;); # ELTERN&lt;br /&gt;
&lt;br /&gt;
my $STATUS = &amp;quot;wahrscheinlich gerade los&amp;quot;;&lt;br /&gt;
$STATUS = &amp;quot;anwesend&amp;quot; if ($EVENT eq &amp;quot;present&amp;quot;); # Status: anwesend&lt;br /&gt;
$STATUS = &amp;quot;unterwegs&amp;quot; if ($EVENT eq &amp;quot;absent&amp;quot;); # Status: unterwegs&lt;br /&gt;
&lt;br /&gt;
Log 1, &amp;quot;$ALIASNAME ist $STATUS.&amp;quot;; # LOG Eintrag erzeugen&lt;br /&gt;
&lt;br /&gt;
if (($EVENT eq &amp;quot;present&amp;quot; &amp;amp;&amp;amp; Value(&amp;quot;Alarm&amp;quot;) eq &amp;quot;aktiv&amp;quot;) &amp;amp;&amp;amp; ($NAME eq &amp;quot;gtag_gruen&amp;quot; xor $NAME eq &amp;quot;gtag_orange&amp;quot;)) {&lt;br /&gt;
 fhem(&amp;quot;set teleBot send ALARMIERUNG BLEIBT AKTIV: $ALIASNAME ist da...&amp;quot;); # Telegram&lt;br /&gt;
# fhem(&amp;quot;set Infopush msg &#039;ALARMIERUNG BLEIBT AKTIV&#039; &#039;$ALIASNAME ist da...&#039;&amp;quot;); # Pushover&lt;br /&gt;
 }&lt;br /&gt;
 elsif (($EVENT eq &amp;quot;present&amp;quot; &amp;amp;&amp;amp; Value(&amp;quot;Alarm&amp;quot;) eq &amp;quot;aktiv&amp;quot;) &amp;amp;&amp;amp; ($NAME eq &amp;quot;gtag_rot&amp;quot; xor $NAME eq &amp;quot;gtag_schwarz&amp;quot;)) {&lt;br /&gt;
 fhem(&amp;quot;set teleBot send ALARMIERUNG INAKTIV: $ALIASNAME ist da...; set Alarm inaktiv&amp;quot;); # Telegram&lt;br /&gt;
# fhem(&amp;quot;set Infopush msg &#039;ALARMIERUNG INAKTIV&#039; &#039;$ALIASNAME ist da...&#039;; set Alarm inaktiv&amp;quot;); # Pushover&lt;br /&gt;
 }&lt;br /&gt;
 elsif (($EVENT eq &amp;quot;absent&amp;quot; &amp;amp;&amp;amp; Value(&amp;quot;Alarm&amp;quot;) eq &amp;quot;aktiv&amp;quot;) &amp;amp;&amp;amp; ($NAME eq &amp;quot;gtag_gruen&amp;quot; xor $NAME eq &amp;quot;gtag_orange&amp;quot;)) {&lt;br /&gt;
 fhem(&amp;quot;set teleBot send ALARMIERUNG BLEIBT AKTIV: $ALIASNAME hat das Haus verlassen.&amp;quot;); # Telegram&lt;br /&gt;
# fhem(&amp;quot;set Infopush msg &#039;ALARMIERUNG BLEIBT AKTIV&#039; &#039;$ALIASNAME hat das Haus verlassen.&#039;&amp;quot;); # Pushover&lt;br /&gt;
 } 		&lt;br /&gt;
 elsif (($EVENT eq &amp;quot;absent&amp;quot; &amp;amp;&amp;amp; Value(&amp;quot;Alarm&amp;quot;) eq &amp;quot;inaktiv&amp;quot;) &amp;amp;&amp;amp; ($GTAG1 eq &amp;quot;absent&amp;quot; &amp;amp;&amp;amp; $GTAG2 eq &amp;quot;absent&amp;quot;)) {&lt;br /&gt;
 fhem(&amp;quot;set Alarm aktiv; set teleBot send ALARMIERUNG AKTIV: $ALIASNAME hat das Haus verlassen.&amp;quot;); # Telegram&lt;br /&gt;
# fhem(&amp;quot;set Alarm aktiv; set Infopush msg &#039;ALARMIERUNG AKTIV&#039; &#039;$ALIASNAME hat das Haus verlassen.&#039; &#039;&#039; 0 &#039;&#039;&amp;quot;); # Pushover&lt;br /&gt;
 }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mit Notify und Integration des RESIDENTS-MODUL ===&lt;br /&gt;
&lt;br /&gt;
Der hier beschriebene Code erweitert die Funktionen unter dem Punkt 5.93.&lt;br /&gt;
Das Notify muss daher mit der folgenden Zeile erweitert werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Alarm_AnwesenheitCheck notify gtag.*.presence:.* { Anwesenheit_check(&amp;quot;$EVTPART1&amp;quot;, &amp;quot;$NAME&amp;quot;), Anwesenheit_check_resi(&amp;quot;$NAME&amp;quot;) }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zusätzlicher Code für die 99_myUtils.pm um die RESIDENTS Funktion nutzen zu können:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
### RESIDENTS&lt;br /&gt;
sub Anwesenheit_check_resi($) {&lt;br /&gt;
my ($NAME) = @_;&lt;br /&gt;
my $ALIASNAME = AttrVal($NAME,&#039;alias&#039;,$NAME); # ALIASNAME des GTAGs auslesen&lt;br /&gt;
&lt;br /&gt;
my $RESIDENT = &amp;quot;rr_&amp;quot;; # Als Standard sind alle GTAGs Roommates&lt;br /&gt;
$RESIDENT = &amp;quot;rg_&amp;quot; if (($NAME eq &amp;quot;gtag_orange&amp;quot;) xor ($NAME eq &amp;quot;gtag_weis&amp;quot;)); # Hier nur GTAG Namen der Gäste (Roomguest)&lt;br /&gt;
my $ROOMMATE = (&amp;quot;$RESIDENT&amp;quot; . &amp;quot;$ALIASNAME&amp;quot;); # Residentsname zusammenbauen&lt;br /&gt;
&lt;br /&gt;
if (ReadingsVal($NAME,&#039;presence&#039;,$NAME) eq &amp;quot;absent&amp;quot;) {&lt;br /&gt;
 fhem(&amp;quot;set $ROOMMATE absent&amp;quot;); # Resisents Status von Roommates setzen&lt;br /&gt;
 }&lt;br /&gt;
 elsif(ReadingsVal($NAME,&#039;presence&#039;,$NAME) eq &amp;quot;present&amp;quot;) {&lt;br /&gt;
 fhem(&amp;quot;set $ROOMMATE home&amp;quot;); # Resisents Status von Roommates setzen&lt;br /&gt;
 }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mit Notify und Fenster/Tür. -Kontakt Überwachung ===&lt;br /&gt;
&lt;br /&gt;
Erweiterung für die Überwachung von  Fenster/Tür. -Kontakten. Dazu sind zwei weitere Notifys notwendig die auf die Trigger der Kontakte regagieren&lt;br /&gt;
und so eine weitere Funktion in der 99_myUtils.pm ansprechen. Die Notifys triggern auf Kontakte die mit dem Namen Kontakt* beginnen.&lt;br /&gt;
Sollten die eigenen Fenster/Tür. -Kontakt anderen Namen besitzen, müssen die Skripte dementsprechend angepasst werden.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Alarm_Kontaktmeldung notify Kontakt.*:contact:.* {Kontakt_Meldung(&amp;quot;$EVTPART1&amp;quot;, &amp;quot;$NAME&amp;quot;)}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Alarm_Sabotagealarm notify Kontakt.*.sabotageError:.on {Kontakt_Sabotage(&amp;quot;$EVTPART1&amp;quot;, &amp;quot;$NAME&amp;quot;)}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zusätzlicher Code für die 99_myUtils.pm um die TÜRKONTAKTE-Meldung nutzen zu können:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
### TÜRKONTAKTE-Meldung/Zustand&lt;br /&gt;
sub Kontakt_Meldung($$) {&lt;br /&gt;
my ($EVENT, $NAME) = @_;&lt;br /&gt;
my $ALIASNAME = AttrVal($NAME,&#039;alias&#039;,$NAME);&lt;br /&gt;
Log 1, &amp;quot;$ALIASNAME wurde $EVENT&amp;quot;;&lt;br /&gt;
if (ReadingsVal(&amp;quot;Alarm&amp;quot;, &amp;quot;state&amp;quot;, &amp;quot;on&amp;quot;) eq &amp;quot;on&amp;quot;) {&lt;br /&gt;
fhem(&amp;quot;set teleBot send $ALIASNAME wurde $EVENT&amp;quot;); # Nachricht über Telegram&lt;br /&gt;
# fhem(&amp;quot;set Infopush msg &#039;$ALIASNAME&#039; &#039;$ALIASNAME wurde $EVENT&#039;&amp;quot;); # Nachricht über Pushover&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
### TÜRKONTAKTE-Sabotagealarm&lt;br /&gt;
&lt;br /&gt;
sub Kontakt_Sabotage($$) {&lt;br /&gt;
my ($EVENT, $NAME) = @_;&lt;br /&gt;
my $ALIASNAME = AttrVal($NAME,&#039;alias&#039;,$NAME);&lt;br /&gt;
Log 1, &amp;quot;$ALIASNAME meldet Sabotagealarm&amp;quot;;&lt;br /&gt;
fhem(&amp;quot;set teleBot send Alarm: $ALIASNAME meldet Sabotagealarm&amp;quot;); # Nachricht über Telegram&lt;br /&gt;
# fhem(&amp;quot;set Infopush msg &#039;Alarmanlage&#039; &#039;$ALIASNAME meldet Sabotagealarm&#039; &#039;&#039; 2 &#039; &#039; 60 600 &amp;quot;); # Nachricht über Pushover&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Hinweis zur Benutzung / Fehlerhandling ===&lt;br /&gt;
&lt;br /&gt;
Der Alarm dummy hat den Zustand on:off.  Die Bezeichnungen und Namen müssen 1:1 übernommen werden damit das Script funktioniert.&lt;br /&gt;
Andernfalls müssen die Bezeichnungen für z.B. absent:unterwegs und present:anwesend - angepasst werden.&lt;br /&gt;
Die Benachrichtigung kann aktuell per &#039;&#039;Telegram&#039;&#039; sowie &#039;&#039;Pushover&#039;&#039; (&#039;&#039;&#039;Achtung mit zweiterem sind Abokosten verbunden!&#039;&#039;&#039;) realisiert werden.&lt;br /&gt;
Diskussion zum Thema im Forum unter: {{Link2Forum|Topic=64080}}&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Problemlösungen =&lt;br /&gt;
Falls es &#039;&#039;&#039;Probleme beim Starten des Skripts&#039;&#039;&#039; gibt bzw. man das Skript ohne Reboot des Systems neustarten möchte, kann man dies per kill Befehl erledigen.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ps -ef | grep lepresenced&lt;br /&gt;
sudo kill &amp;lt;pid&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Debuglevel lepresenced setzen:&lt;br /&gt;
{{Randnotiz|RNText=Um Debug-Meldungen zu bekommen (Vorsicht bei SD-Karten-Systemen wie dem RPi) - Hierbei werden die Schreibzyklen auf die SD-Karte erhöht.}}&lt;br /&gt;
&lt;br /&gt;
Der Log Level muss im lepresenced-Skript selbst verändert werden. Um den Log-Level auf INFO/WARNING/DEBUG zu setzen, dass Skript lepresenced mit einem Editor öffnen und die Stellen, wo LOG_WARNING zu finden sind durch den nötigen LOG-Eintrag ersetzen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lepresenced --loglevel LOG_DEBUG&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Nur das wichtigste Loggen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lepresenced --loglevel LOG_WARNING&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Keinerlei LOG-Einträge&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lepresenced --loglevel LOG_EMERG&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Bei &#039;&#039;&#039;Problemen mit der Batterieüberwachung&#039;&#039;&#039; der Tags kann die Pi Firmeware mit folgenden Befehl auf eine ältere Version zurückgesetzt werden.&lt;br /&gt;
Fehlermeldung beim Aufruf des lebattery oder anderen Batterietestskripten:&lt;br /&gt;
&amp;lt;pre&amp;gt;connect: Connection refused (111)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Lösung (vorübergehend) &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo rpi-update 8521fd34c8f66b6d109acce943f6e25ec93ec005&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mehr dazu unter: {{Link2Forum|Topic=56960|Message=589165}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Das BT-Device ist ständig &amp;quot;absent&amp;quot;&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Eine Mögliche Lösung kann sein, dass Paket bluez-hcidump zu installieren. Das Werkzeug hcidump erlaubt die Beobachtung von Bluetooth-Aktivität.&lt;br /&gt;
Dies ist nicht notwendig, wenn bereits bluez installiert ist, da dies Teil des bluez Paketes ist&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt-get install bluez-hcidump&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Fehler in Logdateien /var/log/syslog und /var/log/kernel&#039;&#039;&#039;&lt;br /&gt;
 Jul 29 15:08:11 raspberrypi kernel: [ 4905.634211] bt_err_ratelimited: 1 callbacks suppressed&lt;br /&gt;
 Jul 29 15:08:11 raspberrypi kernel: [ 4905.634231] Bluetooth: hci0 advertising data length corrected&lt;br /&gt;
 Jul 29 15:08:12 raspberrypi kernel: [ 4906.647350] Bluetooth: hci0 advertising data length corrected&lt;br /&gt;
 Jul 29 15:08:13 raspberrypi kernel: [ 4907.532081] Bluetooth: hci0 advertising data length corrected&lt;br /&gt;
 Jul 29 15:08:13 raspberrypi kernel: [ 4907.655564] Bluetooth: hci0 advertising data length corrected&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Ursache des Problems ist noch nicht ergründet, allerdings betrifft dies aktuell nur den RPi3. Die Fehlermeldungen werden in verschiedene log&#039;s geschrieben. Darunter maßgeblich &amp;quot;syslog&amp;quot; und &amp;quot;kern.log&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Lösung (vorübergehend)&lt;br /&gt;
Unterbinden der Einträge durch Anlage eines blocklist Eintrag:&lt;br /&gt;
&lt;br /&gt;
 1. Unter &amp;quot;/etc/rsyslog.d&amp;quot; eine Datei erzeugen mit dem Namen &amp;quot;01-blocklist.conf&amp;quot;&lt;br /&gt;
 2. Inhalt: (Die Ausdrücke in den &amp;quot;&amp;quot; sind diejenigen, die aus dem log verschwinden sollen. - bei mir waren es die unten stehenden&amp;quot;)&lt;br /&gt;
    :msg,contains,&amp;quot;Bluetooth: hci0 advertising data length corrected&amp;quot; stop&lt;br /&gt;
    :msg,contains,&amp;quot;bt_err_ratelimited:&amp;quot; stop&lt;br /&gt;
 3. Dienst neu starten &amp;quot;sudo service rsyslog restart&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Weiter Infos werden im offiziellen Thema {{Link2Forum|Topic=28753|Message=499184|LinkText=hier}} diskutiert.&lt;br /&gt;
&lt;br /&gt;
Seit Version 0.82 kann es beim Start zu folgenden Meldungen im Log kommen. &lt;br /&gt;
 Sep 06 16:13:45 raspberrypi systemd[1]: Started lepresenced.&lt;br /&gt;
 Sep 06 16:13:45 raspberrypi lepresenced[16010]: [tid:1] main::bluetooth_scan_thread: Received &#039;Set scan parameters failed: Input/output error&#039;, ...tting...&lt;br /&gt;
 Sep 06 16:13:46 raspberrypi lepresenced[16010]: [tid:1] main::bluetooth_scan_thread: hcitool exited, retrying...&lt;br /&gt;
&lt;br /&gt;
Diese Meldungen können ignoriert werden. Abhilfe schafft sich lepresenced selbst indem es sich resettet.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Moderne iPhones und Android Geräte wechseln zum &amp;quot;deep standby&amp;quot; Modus&#039;&#039;&#039;, und werden dann als &amp;quot;abwesend&amp;quot; gemeldet.&lt;br /&gt;
Mittels einer Funktion, die via hping3 Packete an den Geräte senden, um die &amp;quot;wach&amp;quot; zu halten, und dann die MacAdresse ausliest, kann man dieses Problem umgehen. Mehr im Forum [https://forum.fhem.de/index.php/topic,76342.0.html]&lt;br /&gt;
&lt;br /&gt;
= Versionsänderungen lepresenced =&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
--Version 0.81 (BasisVersion)&lt;br /&gt;
--Version 0.82 (stable  08/2017)&lt;br /&gt;
  -Neue Kommandozeilenoption &amp;quot;--debug&amp;quot;: Startet lepresenced im Vordergrund und gibt ausführliche Debug-Informationen auf STDOUT aus.&lt;br /&gt;
  -Sanity Check: lepresenced prüft beim Starten die Verfügbarkeit von hciconfig, hcitool und hcidump.&lt;br /&gt;
  -Model: lepresenced übermittelt das Reading model nun als lan-lepresenced. Das erlaubt die Erkennung von lepresenced in der FHEM-Statistik (sofern aktiviert).&lt;br /&gt;
--Version 0.83 (stable  09/2017)&lt;br /&gt;
  - Behebung von Systemstart Fehlern&lt;br /&gt;
  - Weitere Debug-Möglichkeiten. U. a. wird nun mitgezählt, ob hcitool lescan (&amp;quot;legacy&amp;quot;) und hcidump eine identische Zahl an Beacons empfangen&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Ansprechpartner =&lt;br /&gt;
# {{Link2FU|117|markusbloch }} (Markus) für das PRESENCE-Modul und collectord&lt;br /&gt;
# {{Link2FU|5068|PatrikR}} (Patrick) für lepresenced &lt;br /&gt;
# [[Benutzer Diskussion:Devender|Devender]] ({{Link2FU|20043|Dirk}}) für Wiki und Doku&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23077</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23077"/>
		<updated>2017-10-27T14:25:55Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: /* msgDialog und ROOMATE */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=Dialoge für Sofortnachrichten über TelegramBot, Jabber und WhatsApp&lt;br /&gt;
|ModType=d&lt;br /&gt;
|ModForumArea=Frontends&lt;br /&gt;
|ModTechName=76_msgDialog.pm&lt;br /&gt;
|ModOwner={{Link2FU|4106|igami}}&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Zielsetzung ==&lt;br /&gt;
Eine zentrale Anforderung einer modernen Haus-Automation ist die Steuerung von unterwegs. Mittlerweile nutzt fast jeder einen oder mehrere Messenger Dienste. Da liegt es doch nahe, diese Messenger Dienste für die Kommunikation mit FHEM zu nutzen. &lt;br /&gt;
Mit msgDialog ist es jetzt möglich, Dialoge für Sofortnachrichten über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) zu definieren. Dabei können die einzelnen Dialoge für unterschiedliche Nutzer berechtigt werden.&lt;br /&gt;
Die grundlegende Bedienung wird in diesem &#039;&#039;&#039;[https://youtu.be/yiCOTeR1YVQ Video]&#039;&#039;&#039; am Beispiel von TelegramBot gezeigt.&lt;br /&gt;
&lt;br /&gt;
== Einbindung in FHEM ==&lt;br /&gt;
&lt;br /&gt;
=== Voraussetzungen ===&lt;br /&gt;
Für dieses Modul wird das Perl JSON Modul benötigt. Auf einem Debian-basierten System (z.B RaspberryPI o.ä.) kann man das mit dem folgenden Befehl installieren:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt-get install libjson-perl&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Hinweise ===&lt;br /&gt;
&lt;br /&gt;
*Telegram: Es kann notwendig sein, dass im TelegramBot das Attribut &amp;quot;utf8specials&amp;quot; auf &amp;quot;1&amp;quot; gesetzt werden muss. Damit werden Nachrichten mit Umlauten korrekt gesendet. Beim msg-Befehl kann der TelegramBot_MTYPE angegeben werden. Die Vorgabe ist &amp;quot;message&amp;quot;. Durch den Wert &amp;quot;queryInline&amp;quot; lässt sich ein inline Keyboard erzeugen (siehe unten).&lt;br /&gt;
&lt;br /&gt;
*Jabber: Beim msg Befehl kann der Jabber_MTYPE angegeben werden. Die Vorgabe ist leer. Durch den Wert &amp;quot;otr&amp;quot; lässt sich eine OTR-Nachricht versenden.&lt;br /&gt;
&lt;br /&gt;
*WhatsApp (yowsup): Bisher konnten noch keine Erfahrungen gemacht werden.&lt;br /&gt;
&lt;br /&gt;
=== msgDialog und ROOMMATE ===&lt;br /&gt;
&lt;br /&gt;
Für jeden Dialog kann festgelegt werden, welche Person(en) dazu berechtigt ist. Dazu sind Geräte vom Typ ROOMMATE oder GUEST mit definiertem msgContactPush Attribut erforderlich. Es ist darauf zu achten, dass das Reading &amp;quot;fhemMsgRcvPush&amp;quot; ein Event erzeugt.&lt;br /&gt;
&lt;br /&gt;
=== Definition des msgConfig-Device  ===&lt;br /&gt;
&lt;br /&gt;
Als nächstes benötigt man ein definiertes msgConfig device:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defmod myMsgConfig msgConfig&lt;br /&gt;
attr myMsgConfig msgDialog_evalSpecials me=&amp;lt;Aktivierungswort bzw. -Nachricht&amp;gt;&lt;br /&gt;
TelegramBot=&amp;lt;Name des TelegramBot-device&amp;gt;&lt;br /&gt;
attr myMsgConfig msgContactPush TelegramBot&lt;br /&gt;
attr myMsgConfig room msg&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Falls bereits vorhanden müssen, natürlich nur die fehlenden Attribute gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
=== Definition des metaDialogs === &lt;br /&gt;
&lt;br /&gt;
Zur Auflistung aller berechtigten Dialoge dient - was sonst - ein Dialog!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defmod meta_Dialog msgDialog {\&lt;br /&gt;
  &amp;quot;%me%&amp;quot;: {\&lt;br /&gt;
    &amp;quot;match&amp;quot;: &amp;quot;\/?(start|%me%)&amp;quot;,\&lt;br /&gt;
    &amp;quot;commands&amp;quot;: [\&lt;br /&gt;
	  &amp;quot;deletereading TYPE=msgDialog $recipient_history&amp;quot;,\&lt;br /&gt;
	  &amp;quot;deletereading %TelegramBot% $recipient_sentMsgId&amp;quot;\&lt;br /&gt;
    ],\&lt;br /&gt;
    &amp;quot;message&amp;quot;: [\&lt;br /&gt;
      &amp;quot;{return(&#039;(&#039; . join(&#039;) (&#039;, sort(split(&#039;\n&#039;, fhem(&#039;get TYPE=msgDialog:FILTER=NAME!=$SELF:FILTER=allowed=.*($recipient|everyone).* trigger&#039;)))) . &#039;) &#039;)}&amp;quot;,\&lt;br /&gt;
      &amp;quot;(abbrechen) &amp;quot;,\&lt;br /&gt;
      &amp;quot;Ich kann folgendes für dich tun:&amp;quot;\&lt;br /&gt;
    ]\&lt;br /&gt;
  },\&lt;br /&gt;
  &amp;quot;abbrechen&amp;quot;: {\&lt;br /&gt;
    &amp;quot;match&amp;quot;: &amp;quot;\/?abbrechen&amp;quot;,\&lt;br /&gt;
    &amp;quot;commands&amp;quot;: [\&lt;br /&gt;
	  &amp;quot;deletereading TYPE=msgDialog $recipient_history&amp;quot;,\&lt;br /&gt;
	  &amp;quot;deletereading %TelegramBot% $recipient_sentMsgId&amp;quot;\&lt;br /&gt;
    ],\&lt;br /&gt;
    &amp;quot;message&amp;quot;: [\&lt;br /&gt;
      &amp;quot;(%me%) &amp;quot;,\&lt;br /&gt;
      &amp;quot;Dialog abgebrochen.&amp;quot;\&lt;br /&gt;
    ]    \&lt;br /&gt;
  },\&lt;br /&gt;
  &amp;quot;beenden&amp;quot;: {\&lt;br /&gt;
    &amp;quot;match&amp;quot;: &amp;quot;\/?beenden&amp;quot;,\&lt;br /&gt;
    &amp;quot;commands&amp;quot;: [\&lt;br /&gt;
	  &amp;quot;deletereading TYPE=msgDialog $recipient_history&amp;quot;,\&lt;br /&gt;
	  &amp;quot;deletereading %TelegramBot% $recipient_sentMsgId&amp;quot;\&lt;br /&gt;
    ],\&lt;br /&gt;
    &amp;quot;message&amp;quot;: [\&lt;br /&gt;
      &amp;quot;(%me%) &amp;quot;,\&lt;br /&gt;
      &amp;quot;Dialog beendet.&amp;quot;\&lt;br /&gt;
    ]\&lt;br /&gt;
  }\&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
attr meta_Dialog DbLogExclude .*&lt;br /&gt;
attr meta_Dialog allowed everyone&lt;br /&gt;
attr meta_Dialog room msg&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Definition beliebiger Dialoge ===&lt;br /&gt;
&lt;br /&gt;
Aufgrund der Komplexität eines Dialogs mit JSON ist es am praktikabelsten, zunächst einen leeren Dialog zu definieren:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define &amp;lt;name&amp;gt; msgDialog {} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Anschließend kann die DEF in der Detail-Ansicht des Dialog-Device bearbeitet werden. Jeder Dialog basiert auf der folgenden Struktur von einfach bis komplex.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;&amp;lt;TRIGGER&amp;gt;&amp;quot;: {&lt;br /&gt;
    &amp;quot;match&amp;quot;: &amp;quot;&amp;lt;regex&amp;gt;&amp;quot;,&lt;br /&gt;
    &amp;quot;setOnly&amp;quot;: (true|false),&lt;br /&gt;
    &amp;quot;commands&amp;quot;: &amp;quot;(fhem command|{perl code})&amp;quot;,&lt;br /&gt;
    &amp;quot;message&amp;quot;: [&lt;br /&gt;
      &amp;quot;{perl code}&amp;quot;,&lt;br /&gt;
      &amp;quot;text&amp;quot;&lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;&amp;lt;NEXT TRIGGER 1&amp;gt;&amp;quot;: {&lt;br /&gt;
      ...&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;&amp;lt;NEXT TRIGGER 2&amp;gt;&amp;quot;: {&lt;br /&gt;
      ...&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Um den JSON-Teil der Dialoge zu testen, empfiehlt sich ein Besuch auf https://jsonlint.com/&lt;br /&gt;
Hier kann der selbst geschriebene JSON-Code validiert werden.&lt;br /&gt;
&lt;br /&gt;
*TRIGGER: Kann ein beliebiger Text sein. Es wird geprüft ob die eingehende Nachricht damit übereinstimmt. Falls ja, wird der Dialog an dieser Stelle fortgesetzt.&lt;br /&gt;
&lt;br /&gt;
*match: Wenn nicht nur genau eine Nachricht zugelassen werden soll, kann noch eine regex angegeben werden. Die regex muss auf die gesamte eingehnde Nachricht zutreffen. &lt;br /&gt;
&lt;br /&gt;
*setOnly: Kann optional auf true oder false gestellt werden. In beiden fällen wird der TRIGGER dann nicht bei &amp;quot;get &amp;lt;name&amp;gt; trigger&amp;quot; zurück gegeben.&lt;br /&gt;
Wenn setOnly auf &amp;quot;true&amp;quot; gestellt wird, kann der Dialog an dieser Stelle nicht durch eingehende Nachrichten ausgelöst werden, sondern nur über &amp;quot;get &amp;lt;name&amp;gt; say TRIGGER&amp;quot;. Dies kann dazu genutzt werden um einen Dialog aus FHEM heraus zu initiieren.&lt;br /&gt;
&lt;br /&gt;
*commands: Kann einen einzelnen oder mehrere Befehle enthalten: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;commands&amp;quot;: &lt;br /&gt;
&amp;quot;single command&amp;quot;&lt;br /&gt;
&amp;quot;commands&amp;quot;: [&lt;br /&gt;
&amp;quot;command 1&amp;quot;,&lt;br /&gt;
&amp;quot;command 2&amp;quot;,&lt;br /&gt;
&amp;quot;{perl command}&amp;quot;&lt;br /&gt;
]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*message: Kann einen einzelnen oder mehrere Textte enthalten die mit einen Zeilenumbruch verbunden werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: &amp;quot;text&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;text 1&amp;quot;,&lt;br /&gt;
&amp;quot;text 2&amp;quot;,&lt;br /&gt;
&amp;quot;{return from perl command}&amp;quot;&lt;br /&gt;
]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Bei mehrstufigen Dialogen wird diese Struktur ineinander verschachtelt angegeben.&lt;br /&gt;
Es werden Variablen und Platzhalter, welche unter dem Attribut evalSpecials definiert werden, ausgewertet.&lt;br /&gt;
=== Variablen ===&lt;br /&gt;
*$SELF: Eigenname des msgDialog&lt;br /&gt;
*$message: eingegangene Nachricht&lt;br /&gt;
*$recipient: Name des Dialogpartners&lt;br /&gt;
&lt;br /&gt;
=== set ===&lt;br /&gt;
*reset: Setzt den Dialog für alle Benutzer zurück.&lt;br /&gt;
*say [@&amp;lt;recipient1&amp;gt;[,&amp;lt;recipient2&amp;gt;,...]] &amp;lt;TRIGGER&amp;gt;[|&amp;lt;NEXT TRIGGER&amp;gt;|...]: Der Dialog wird für alle angegeben Empänger an der angegeben Stelle fortgeführt. Sind keine Empfänger angegeben wird der Dialog für alle unter dem Attribut allowed angegebenen Empfänger fortgeführt.&lt;br /&gt;
*updateAllowed: Aktualisiert die Auswahl für das Attribut allowed.&lt;br /&gt;
&lt;br /&gt;
=== get ===&lt;br /&gt;
*trigger: Listet alle TRIGGER der ersten Ebene auf bei denen nicht setOnly angegeben ist.&lt;br /&gt;
&lt;br /&gt;
=== ATTRIBUTE ===&lt;br /&gt;
*allowed: Liste mit allen RESIDENTS und ROOMMATE die für diesen Dialog berechtigt sind.&lt;br /&gt;
*disable: [0|1] Dialog ist aktiviert|deaktiviert.&lt;br /&gt;
*disabledForIntervals: HH:MM-HH:MM HH:MM-HH-MM ...&lt;br /&gt;
*evalSpecials: key1=value1 key2=value2 ...Leerzeichen getrennte Liste von Name=Wert Paaren. Wert kann Leerzeichen enthalten, falls es in &amp;quot;&amp;quot; oder {} eingeschlossen ist. Wert wird als perl-Ausdruck ausgewertet, falls es in {} eingeschlossen ist. In der DEF werden %Name% Zeichenketten durch den zugehörigen Wert ersetzt. Dieses Attribut ist als &amp;quot;msgDialog_evalSpecials&amp;quot; im msgConfig Gerät vorhanden. Wenn der selbe Name im msgConfig und msgDialog definiert wurde, wird der Wert aus msgDialog verwendet.&lt;br /&gt;
*msgCommand &amp;lt;command&amp;gt;: Befehl der zum Versenden einer Nachricht verwendet wird. Die Vorgabe ist &amp;quot;msg push \@$recipients $message&amp;quot; Dieses Attribut ist als &amp;quot;msgDialog_msgCommand&amp;quot; im msgConfig Gerät vorhanden.&lt;br /&gt;
&lt;br /&gt;
=== READINGS ===&lt;br /&gt;
*$recipient_history: Durch | getrennte Liste von TRIGGER um den aktuellen Zustand des Dialogs zu sichern. Für jeden Dialogpartner wird ein Reading angelegt. Wenn der Dialog beendet ist wird das Reading zurückgesetzt.&lt;br /&gt;
&lt;br /&gt;
== Beispiele ==&lt;br /&gt;
&lt;br /&gt;
==== Programmierung der Waschmaschine ====&lt;br /&gt;
Das ist ein Beispiel zur Programmierung einer Waschmaschine wie auch oben im Video zu sehen: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defmod Waschmaschine_Dialog msgDialog { &amp;quot;Waschmaschine&amp;quot;: {\&lt;br /&gt;
    &amp;quot;message&amp;quot;: [\&lt;br /&gt;
      &amp;quot;{return(&#039;(Zeitprogramm stoppen) &#039;) if(ReadingsVal(&#039;%controlUnit%&#039;, &#039;controlMode&#039;, &#039;&#039;) eq &#039;auto&#039;)}&amp;quot;,\&lt;br /&gt;
      &amp;quot;{return(&#039;(programmieren) &#039;) if(ReadingsVal(&#039;%actor%&#039;, &#039;state&#039;, &#039;&#039;) ne &#039;on&#039;)}&amp;quot;,\&lt;br /&gt;
      &amp;quot;{return(&#039;(einschalten) &#039;) if(ReadingsVal(&#039;%actor%&#039;, &#039;state&#039;, &#039;&#039;) ne &#039;on&#039;)}&amp;quot;,\&lt;br /&gt;
      &amp;quot;(Verlaufsdiagramm) &amp;quot;,\&lt;br /&gt;
      &amp;quot;(abbrechen) &amp;quot;,\&lt;br /&gt;
      &amp;quot;{return(&#039;Waschmaschine: &#039; . (ReadingsVal(&#039;%actor%&#039;, &#039;state&#039;, &#039;&#039;) eq &#039;on&#039; ? &#039;eingeschaltet&#039; : &#039;ausgeschaltet&#039;))}&amp;quot;,\&lt;br /&gt;
      &amp;quot;{return(&#039;Modus: &#039; . (ReadingsVal(&#039;%controlUnit%&#039;, &#039;controlMode&#039;, &#039;&#039;) eq &#039;auto&#039; ? &#039;Automatik&#039; : &#039;Manuell (&#039; . ReadingsVal(&#039;%controlUnit%&#039;, &#039;time&#039;, &#039;&#039;) . &#039;)&#039;))}&amp;quot;\&lt;br /&gt;
    ],\&lt;br /&gt;
    &amp;quot;Zeitprogramm stoppen&amp;quot;: {\&lt;br /&gt;
      &amp;quot;commands&amp;quot;: &amp;quot;set %controlUnit% controlMode manual&amp;quot;,\&lt;br /&gt;
      &amp;quot;message&amp;quot;: [\&lt;br /&gt;
        &amp;quot;TelegramBot_MTYPE=queryInline (%me%) &amp;quot;,\&lt;br /&gt;
        &amp;quot;Das Zeitprogramm wurde gestoppt.&amp;quot;\&lt;br /&gt;
      ]\&lt;br /&gt;
    },\&lt;br /&gt;
    &amp;quot;programmieren&amp;quot;: {\&lt;br /&gt;
      &amp;quot;message&amp;quot;: [\&lt;br /&gt;
        &amp;quot;(bestätigen|zurück|abbrechen) &amp;quot;,\&lt;br /&gt;
        &amp;quot;( 00:00 | 00:15 | 00:30 | 00:45 ) &amp;quot;,\&lt;br /&gt;
        &amp;quot;( 01:00 | 01:15 | 01:30 | 01:45 ) &amp;quot;,\&lt;br /&gt;
        &amp;quot;( 02:00 | 02:15 | 02:30 | 02:45 ) &amp;quot;,\&lt;br /&gt;
        &amp;quot;( 03:00 | 03:15 | 03:30 | 03:45 ) &amp;quot;,\&lt;br /&gt;
        &amp;quot;( 04:00 | 04:15 | 04:30 | 04:45 ) &amp;quot;,\&lt;br /&gt;
        &amp;quot;( 05:00 | 05:15 | 05:30 | 05:45 ) &amp;quot;,\&lt;br /&gt;
        &amp;quot;( 06:00 | 06:15 | 06:30 | 06:45 ) &amp;quot;,\&lt;br /&gt;
        &amp;quot;( 07:00 | 07:15 | 07:30 | 07:45 ) &amp;quot;,\&lt;br /&gt;
        &amp;quot;( 08:00 | 08:15 | 08:30 | 08:45 ) &amp;quot;,\&lt;br /&gt;
        &amp;quot;( 09:00 | 09:15 | 09:30 | 09:45 ) &amp;quot;,\&lt;br /&gt;
        &amp;quot;( 10:00 | 10:15 | 10:30 | 10:45 ) &amp;quot;,\&lt;br /&gt;
        &amp;quot;( 11:00 | 11:15 | 11:30 | 11:45 ) &amp;quot;,\&lt;br /&gt;
        &amp;quot;( 12:00 | 12:15 | 12:30 | 12:45 ) &amp;quot;,\&lt;br /&gt;
        &amp;quot;( 13:00 | 13:15 | 13:30 | 13:45 ) &amp;quot;,\&lt;br /&gt;
        &amp;quot;( 14:00 | 14:15 | 14:30 | 14:45 ) &amp;quot;,\&lt;br /&gt;
        &amp;quot;( 15:00 | 15:15 | 15:30 | 15:45 ) &amp;quot;,\&lt;br /&gt;
        &amp;quot;( 16:00 | 16:15 | 16:30 | 16:45 ) &amp;quot;,\&lt;br /&gt;
        &amp;quot;( 17:00 | 17:15 | 17:30 | 17:45 ) &amp;quot;,\&lt;br /&gt;
        &amp;quot;( 18:00 | 18:15 | 18:30 | 18:45 ) &amp;quot;,\&lt;br /&gt;
        &amp;quot;( 19:00 | 19:15 | 19:30 | 19:45 ) &amp;quot;,\&lt;br /&gt;
        &amp;quot;( 20:00 | 20:15 | 20:30 | 20:45 ) &amp;quot;,\&lt;br /&gt;
        &amp;quot;( 21:00 | 21:15 | 21:30 | 21:45 ) &amp;quot;,\&lt;br /&gt;
        &amp;quot;( 22:00 | 22:15 | 22:30 | 22:45 ) &amp;quot;,\&lt;br /&gt;
        &amp;quot;( 23:00 | 23:15 | 23:30 | 23:45 ) &amp;quot;,\&lt;br /&gt;
        &amp;quot;Wann soll die Wäsche fertig sein?&amp;quot;,\&lt;br /&gt;
        &amp;quot;Bitte Uhrzeit in HH:MM angeben.&amp;quot;,\&lt;br /&gt;
        &amp;quot;Aktuell ist [%controlUnit%:time] Uhr eingestellt.&amp;quot;\&lt;br /&gt;
      ],\&lt;br /&gt;
      &amp;quot;Uhrzeit&amp;quot;: {\&lt;br /&gt;
        &amp;quot;match&amp;quot;: &amp;quot; ?([0-1][0-9]|2[0-3]):[0-5][0-9] ?&amp;quot;,\&lt;br /&gt;
        &amp;quot;commands&amp;quot;: [\&lt;br /&gt;
          &amp;quot;set %controlUnit% time $message&amp;quot;,\&lt;br /&gt;
          &amp;quot;set $SELF say @$recipient Waschmaschine|programmieren|bestätigen&amp;quot;\&lt;br /&gt;
        ]\&lt;br /&gt;
      },\&lt;br /&gt;
      &amp;quot;bestätigen&amp;quot;: {\&lt;br /&gt;
        &amp;quot;commands&amp;quot;: &amp;quot;set %controlUnit% controlMode auto&amp;quot;,\&lt;br /&gt;
        &amp;quot;message&amp;quot;: [\&lt;br /&gt;
          &amp;quot;TelegramBot_MTYPE=queryInline (%me%) &amp;quot;,\&lt;br /&gt;
          &amp;quot;Das Zeitprogramm wurde eingestellt.&amp;quot;,\&lt;br /&gt;
          &amp;quot;Die Wäsche wird voraussichtlich um [%controlUnit%:time] Uhr fertig sein.&amp;quot;,\&lt;br /&gt;
          &amp;quot;Bitte die Waschmaschine vorbereiten.&amp;quot;\&lt;br /&gt;
        ]\&lt;br /&gt;
      }\&lt;br /&gt;
    },\&lt;br /&gt;
    &amp;quot;einschalten&amp;quot;: {\&lt;br /&gt;
      &amp;quot;commands&amp;quot;: [\&lt;br /&gt;
        &amp;quot;set %controlUnit% controlMode manual&amp;quot;,\&lt;br /&gt;
        &amp;quot;set %actor% on&amp;quot;\&lt;br /&gt;
      ]\&lt;br /&gt;
    },\&lt;br /&gt;
    &amp;quot;Verlaufsdiagramm&amp;quot;: {\&lt;br /&gt;
      &amp;quot;commands&amp;quot;: &amp;quot;set %TelegramBot% cmdSend {plotAsPng(&#039;%plot%&#039;)}&amp;quot;,\&lt;br /&gt;
      &amp;quot;message&amp;quot;: &amp;quot;TelegramBot_MTYPE=queryInline (%me%) $message&amp;quot;\&lt;br /&gt;
    }\&lt;br /&gt;
  },\&lt;br /&gt;
  &amp;quot;auto&amp;quot;: {\&lt;br /&gt;
    &amp;quot;setOnly&amp;quot;: true,\&lt;br /&gt;
    &amp;quot;commands&amp;quot;: [\&lt;br /&gt;
      &amp;quot;set %actor% on&amp;quot;,\&lt;br /&gt;
      &amp;quot;set %controlUnit% controlMode manual&amp;quot;\&lt;br /&gt;
    ],\&lt;br /&gt;
    &amp;quot;message&amp;quot;: [\&lt;br /&gt;
      &amp;quot;TelegramBot_MTYPE=queryInline (%me%) &amp;quot;,\&lt;br /&gt;
      &amp;quot;Die Wachmaschine wurde automatisch eingeschaltet.&amp;quot;\&lt;br /&gt;
    ]\&lt;br /&gt;
  },\&lt;br /&gt;
  &amp;quot;manual&amp;quot;: {\&lt;br /&gt;
    &amp;quot;setOnly&amp;quot;: true,\&lt;br /&gt;
    &amp;quot;message&amp;quot;: [\&lt;br /&gt;
      &amp;quot;TelegramBot_MTYPE=queryInline (%me%) &amp;quot;,\&lt;br /&gt;
      &amp;quot;Die Wachmaschine wurde manuell eingeschaltet.&amp;quot;\&lt;br /&gt;
    ]\&lt;br /&gt;
  },\&lt;br /&gt;
  &amp;quot;done&amp;quot;: {\&lt;br /&gt;
    &amp;quot;setOnly&amp;quot;: true,\&lt;br /&gt;
    &amp;quot;commands&amp;quot;: &amp;quot;set %actor% off&amp;quot;,\&lt;br /&gt;
    &amp;quot;message&amp;quot;: [\&lt;br /&gt;
      &amp;quot;TelegramBot_MTYPE=queryInline (%me%) &amp;quot;,\&lt;br /&gt;
      &amp;quot;Die Wachmaschine ist fertig.&amp;quot;\&lt;br /&gt;
    ]\&lt;br /&gt;
  }\&lt;br /&gt;
}&lt;br /&gt;
attr Waschmaschine_Dialog evalSpecials actor=HM_2C10D8_Sw\&lt;br /&gt;
controlUnit=Waschkeller_washer_controlUnit\&lt;br /&gt;
plot=Waschkeller_washer_SVG&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== TelegramBot: Inline Keyboard verwenden==&lt;br /&gt;
&lt;br /&gt;
In Telegram gibt es die Möglichkeit die Art des Keyboards zu ändern. Links das normale Keyboard, rechts das Inline Keyboard.&lt;br /&gt;
&lt;br /&gt;
[[Datei:76msgDialog menu.png|Normales Keyboard]]  [[Datei:76msgDialog menu inline.PNG|Inline Keyboard]]&lt;br /&gt;
&lt;br /&gt;
In diesem &#039;&#039;&#039;[https://youtu.be/oRDy2918mVI Video]&#039;&#039;&#039; wird Telegram mit einem Inline Keyboard verwendet.&lt;br /&gt;
&lt;br /&gt;
Um eine Nachricht bei Telegram zu verändern, gibt es den Befehl &amp;quot;queryEditInline&amp;quot;.&lt;br /&gt;
Dafür wird die MsgId von der Nachricht benötigt. Das erledigt ein notify, welches die msgId pro Peer abspeichert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defmod sentMsgIdByPeerId notify .+:sentMsgId.+ {\&lt;br /&gt;
  return unless($TYPE eq &amp;quot;TelegramBot&amp;quot;);;\&lt;br /&gt;
  \&lt;br /&gt;
  my $dev_hash = $defs{$NAME};;\&lt;br /&gt;
  my $sentMsgId = ReadingsVal($NAME, &amp;quot;sentMsgId&amp;quot;, &amp;quot;&amp;quot;);;\&lt;br /&gt;
  my $sentMsgPeerId = ReadingsVal($NAME, &amp;quot;sentMsgPeerId&amp;quot;, &amp;quot;&amp;quot;);;\&lt;br /&gt;
  my ($contact) = devspec2array(&amp;quot;TYPE=(ROOMMATE|GUEST):FILTER=msgContactPush=.*$sentMsgPeerId.*&amp;quot;);;\&lt;br /&gt;
  \&lt;br /&gt;
  readingsSingleUpdate($dev_hash, &amp;quot;$contact\_sentMsgId&amp;quot;, $sentMsgId, 1);;\&lt;br /&gt;
}&lt;br /&gt;
attr sentMsgIdByPeerId devStateIcon {ReadingsVal($name, &amp;quot;state&amp;quot;, &amp;quot;inactive&amp;quot;) eq &amp;quot;active&amp;quot; ? &amp;quot;.*:ios-on-blue:inactive&amp;quot; : &amp;quot;.*:ios-off:active&amp;quot;}&lt;br /&gt;
attr sentMsgIdByPeerId icon audio_mic&lt;br /&gt;
attr sentMsgIdByPeerId room msg&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Danach wird der Message-Befehl von  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set &amp;lt;TelegramBot&amp;gt; message&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
auf&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set &amp;lt;TelegramBot&amp;gt; queryEditInline &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
geändert. Dafür wird ein [[cmdalias]] verwendet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defmod message2queryEditInline cmdalias set .+ message (.|\n)+ AS {\&lt;br /&gt;
  my ($NAME, $cmd, $message) = split(/[\s]+/, $EVENT, 3);;\&lt;br /&gt;
  my $TYPE = InternalVal($NAME, &amp;quot;TYPE&amp;quot;, &amp;quot;&amp;quot;);;\&lt;br /&gt;
  (my $recipient, $message) = ($message =~ m/(@\S+)? (.+)/s);;\&lt;br /&gt;
  \&lt;br /&gt;
  if($TYPE eq &amp;quot;TelegramBot&amp;quot; &amp;amp;&amp;amp; $recipient){\&lt;br /&gt;
    my ($contact) = devspec2array(&amp;quot;TYPE=(ROOMMATE|GUEST):FILTER=msgContactPush=.*$recipient.*&amp;quot;);;\&lt;br /&gt;
    my $sentMsgId = ReadingsVal($NAME, &amp;quot;$contact\_sentMsgId&amp;quot;, &amp;quot;&amp;quot;);;\&lt;br /&gt;
\&lt;br /&gt;
    if($sentMsgId ne &amp;quot;&amp;quot;){\&lt;br /&gt;
      fhem(&amp;quot;set $NAME queryEditInline $sentMsgId $recipient $message&amp;quot;);;\&lt;br /&gt;
    }\&lt;br /&gt;
    else{\&lt;br /&gt;
      fhem(&amp;quot;set $NAME queryInline $recipient $message&amp;quot;);;\&lt;br /&gt;
    }\&lt;br /&gt;
  }\&lt;br /&gt;
  else{\&lt;br /&gt;
    fhem(&amp;quot;set $EVENT&amp;quot;);;\&lt;br /&gt;
  }\&lt;br /&gt;
}&lt;br /&gt;
attr message2queryEditInline room msg&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Um wieder zurück zum normalen Keyboard zu gelangen genügt es, das notify und den cmdAlias zu deaktivieren.&lt;br /&gt;
Das kann komfortabel über ein notify und einen dummy erledigt werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defmod inline_normal.NOT notify inline_normal.DUM:.* {\&lt;br /&gt;
if (&amp;quot;$EVENT&amp;quot; =~ &amp;quot;on&amp;quot;) {\&lt;br /&gt;
  fhem &amp;quot;set sentMsgIdByPeerId active;; attr message2queryEditInline disable 0&amp;quot;;;\&lt;br /&gt;
  } \&lt;br /&gt;
elsif (&amp;quot;$EVENT&amp;quot; =~ &amp;quot;off&amp;quot;) {\&lt;br /&gt;
  fhem &amp;quot;set sentMsgIdByPeerId inactive;; attr message2queryEditInline disable 1&amp;quot;;;\&lt;br /&gt;
  }\&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Weitere Infos zum Thema Inline Keyboard sind in der Antwort #10 im Forum zu finden (siehe Link unten).&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Thread über das Modul im {{Link2Forum|Topic=77297|LinkText=FHEM Forum}}&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Gerätemodul]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=AndFHEM&amp;diff=22901</id>
		<title>AndFHEM</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=AndFHEM&amp;diff=22901"/>
		<updated>2017-10-12T19:19:46Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: URL korrigiert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:AndFHEM_logo.png|48px|right]]&lt;br /&gt;
&lt;br /&gt;
andFHEM is a native Android [[:Kategorie:FHEM Frontends|frontend]] for FHEM.&lt;br /&gt;
&lt;br /&gt;
Since May/13, 2012 the free andFHEM version contains advertisements. There is a (billed) premium version available now.&lt;br /&gt;
&lt;br /&gt;
[[File:AndFHEM_screenshot-1324896614334.png|192px]]&lt;br /&gt;
&lt;br /&gt;
[[File:AndroidMarket_logo.png|291px|right]]&lt;br /&gt;
&lt;br /&gt;
For more information see [https://play.google.com/store/apps/details?id=li.klass.fhem Play Store] &amp;quot;andFHEM&amp;quot; or here:&lt;br /&gt;
&lt;br /&gt;
* [http://andfhem.klass.li/index.html Homepage]&lt;br /&gt;
** [http://andfhem.klass.li/changelog/ Changelog]&lt;br /&gt;
** [http://andfhem.klass.li/faq.html FAQ]&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
* Show devices in rooms&lt;br /&gt;
* Create your own favorite devices list&lt;br /&gt;
* Switch and dim FS20 devices&lt;br /&gt;
* Create plots for CUL_WS, HMS, KS300, OREGON devices&lt;br /&gt;
* Delete, move and rename devices&lt;br /&gt;
&lt;br /&gt;
== Supported Devices ==&lt;br /&gt;
* AT&lt;br /&gt;
* CUL_EM&lt;br /&gt;
* CUL_FHTTK&lt;br /&gt;
* CUL_HM&lt;br /&gt;
* CUL_TX&lt;br /&gt;
* CUL_WS&lt;br /&gt;
* DUMMY&lt;br /&gt;
* EIB&lt;br /&gt;
* EN_OCEAN&lt;br /&gt;
* FHT&lt;br /&gt;
* Floorplan&lt;br /&gt;
* FS20&lt;br /&gt;
* HCS&lt;br /&gt;
* HMS&lt;br /&gt;
* HOL&lt;br /&gt;
* Intertechno&lt;br /&gt;
* KS300&lt;br /&gt;
* LGTV&lt;br /&gt;
* MAX&lt;br /&gt;
* Oregon&lt;br /&gt;
* Owcount&lt;br /&gt;
* OWFS&lt;br /&gt;
* Owtemp&lt;br /&gt;
* Owtherm&lt;br /&gt;
* PID&lt;br /&gt;
* RFXCOM&lt;br /&gt;
* RFXX10REC&lt;br /&gt;
* SIS_PMS&lt;br /&gt;
* Structure&lt;br /&gt;
* TRX&lt;br /&gt;
* TRX_LIGHT&lt;br /&gt;
* TRX_WEATHER&lt;br /&gt;
* Twilight&lt;br /&gt;
* USBWX&lt;br /&gt;
* Watchdog&lt;br /&gt;
* Weather&lt;br /&gt;
* WOL&lt;br /&gt;
*  ...&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Glossary]]&lt;br /&gt;
[[Kategorie:FHEM Frontends]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MySensors_Starter_Guide&amp;diff=20980</id>
		<title>MySensors Starter Guide</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MySensors_Starter_Guide&amp;diff=20980"/>
		<updated>2017-03-20T20:39:26Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: Aufrufreihenfolge korrigiert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Dieser Artikel ist im Aufbau und soll Einsteigern und Fortgeschrittenen als Referenzquelle für typische Fragen dienen. Alle sind eingeladen hier weitere Möglichkeiten einzubringen. Die beste Referenz für alle Fragen zu MySensors ist und bleibt aber die offizielle Hompage des Projekts!}}&lt;br /&gt;
&lt;br /&gt;
== Einführung ==&lt;br /&gt;
[http://www.mysensors.org MySensors] ist ein open-Source-Projekt. Der Schwerpunkt liegt auf selbstgemachten Funk-Sensoren für die Hausautomatisierung und das &amp;quot;Internet der Dinge&amp;quot; in einer Art Baukastensystem. Die Bauanleitungen des Projekts für die einzelnen Musterbausteine sind in der Regel einfach nachzubauen, die Hard- und Softwarebauteile lassen sich dabei auch (fast beliebig) kombinieren. &lt;br /&gt;
&lt;br /&gt;
=== Nodes und Children===&lt;br /&gt;
==== Nodes ====&lt;br /&gt;
Die Kombination von einem Microcontroller und einem Funkchip wird jeweils als &amp;quot;Node&amp;quot; bezeichnet. &lt;br /&gt;
Ein MySensors-Netzwerk besteht also (in der Regel) aus mindestens zwei Nodes, nämlich einer Gateway-Node und einer Sensor-Node. Jede Node ist durch eine sog. NodeID innerhalb des Netzwerks eindeutig identifizierbar, wobei die &amp;quot;0&amp;quot; jeweils für das Gateway reserviert ist.&lt;br /&gt;
Als Microcontroller werden in der Regel Arduinos (Nano oder Micro) verwendet, für das GW häufiger auch [[ESP8266]]. Als Funkchips lassen sich derzeit Module mit nRF24L01+ und RFM69 verwenden, die allerdings jeweils eine eigene Funktechnik verwendet und daher innerhalb eines Netzwerks nicht gemischt werden können. Es kann auch ein kabelgebundenes Netzwerk auf Basis von RS485-Modulen aufgebaut werden; hierfür werden 2 Adern als Datenleitung benötigt.&lt;br /&gt;
==== Children ====&lt;br /&gt;
Als Child wird alles bezeichnet, was jeweils innerhalb einer Node unterschieden werden soll. Beispiel: An einer Node wird ein BME280 angeschlossen. Dies ist ein I2C-Sensor, der drei Werte liefert, nämlich Temperatur, Luftfeuchtigkeit und Luftdruck. Jeder dieser Meßgrößen erhält üblicherweise eine eigene ChildID zugewiesen.&lt;br /&gt;
&lt;br /&gt;
=== Softwarestand ===&lt;br /&gt;
{{Randnotiz|RNTyp=g|RNText=Der Verfasser hat in der Vergangenheit festgestellt, dass die bei MySensors beteiligten Entwickler eventuelle Verbesserungen und Fehlerkorrekturen nicht mehr in die &amp;quot;stable&amp;quot;-Version rückportieren. Bei Problemen empfiehlt es sich daher, die jeweilige beta-Version zu testen. Hierzu muß aber in der Regel auch das verwendete Gateway auf diese Version upgedated werden.}}&lt;br /&gt;
Bei Abfassung dieses Artikels war &lt;br /&gt;
*1.8.0 der Stand der verwendeten Arduino-IDE&lt;br /&gt;
*2.1.1 die stable-Version von MySensors. &lt;br /&gt;
*2.2.0-beta der aktuelle Development-Zweig von Mysensors&lt;br /&gt;
&lt;br /&gt;
=== Vor- und Nachteile von MySensors ===&lt;br /&gt;
==== Vorteile  ====&lt;br /&gt;
*Preisgünstig&lt;br /&gt;
*Modular, Elemente können (fast) beliebig kombiniert werden&lt;br /&gt;
*Es kann ein sog. ACK verlangt werden. Damit läßt sich sicherstellen, dass eine Node einen Befehl auch tatsächlich erhalten hat (Bidirektionalität).&lt;br /&gt;
*Auf den Microcontrollern kann eine eigene Funktionalität unabhängig von der zentralen FHEM-Instanz vorgesehen werden (z.B. LED-Licht direkt bei Bewegung schalten). Die Nodes können seit 2.0.1-beta dabei auch ohne Verbindung zum Gateway die loop() ausführen, wenn eine entsprechende Option aktiviert ist.&lt;br /&gt;
*MQTT kann unterstützt werden.&lt;br /&gt;
*Es kann auch eine kabelgebundene Infrastruktur aufgebaut werden (RS485, zwei Adern).&lt;br /&gt;
&lt;br /&gt;
==== Nachteile  ====&lt;br /&gt;
*Standardmäßig wird ein nicht verschüsselter Funkstandard verwendet, so dass von der Verwendung in sicherheitsrelevanten Funktionen (Türschließer usw.) abzuraten ist.&lt;br /&gt;
&lt;br /&gt;
==== Zum Start ====&lt;br /&gt;
Für erste Tests sind sinnvoll:&lt;br /&gt;
{{Randnotiz|RNTyp=g|RNText=1. Für Sensbender-Boards sind spezielle [https://raw.githubusercontent.com/mysensors/ArduinoBoards/master/package_mysensors.org_index.json Board-Definitionen] für die IDE verfügbar. Nach den [https://github.com/mysensors/MySensors/releases Release Notes] sind diese ab der Version 2.0.0 zu empfehlen, die Installation erfolgt über File -&amp;gt; Preferencies -&amp;gt; Additional Boards Manager URLs&lt;br /&gt;
2. Manche neueren Boarddefinitionen aus der IDE führen u.U. zu häufigeren Reboots. Seit 1.6.18 scheint das Problem behoben zu sein, ansonsten ist ein Downgrade der Boarddefinitionen für AVR-Boards bis &amp;lt;=1.6.11 zu empfehlen.}}&lt;br /&gt;
*eine Arduino mit USB-Anschluß (Nano) oder ein ESP8266 &lt;br /&gt;
*ein weiterer Arduino Nano&lt;br /&gt;
*zwei nRF24L01+ (alternativ: zwei RFM69)&lt;br /&gt;
*Die Arduino-IDE &lt;br /&gt;
*die gewünschte Sensorik, also z.B. einen DS18B20+Widerstand, ein Bewegungsmelder-Modul, ... siehe dazu die [https://www.mysensors.org/build Build-Anleitungen bei MySensors.org], wo auch Bezugsquellen zu finden sind.&lt;br /&gt;
&lt;br /&gt;
== MySensors in FHEM ==&lt;br /&gt;
=== Allgemein ===&lt;br /&gt;
Die Nutzung von MySensors in FHEM ist (nicht nur für den Anfänger) mit der standardmäßig eingeschalteten [[autocreate|autocreate-Funktion]] einfach umsetzbar. Die Kenntnis der FHEM-Grundlagen und Durcharbeitung der Anfänger-Lektüren wird im Folgenden vorausgesetzt. Insbesondere sind [[Erste Schritte in FHEM]] und [http://fhem.de/Heimautomatisierung-mit-fhem.pdf Heimautomatisierung mit FHEM] Pflicht! Dort werden wesentliche Punkte für ein Verständnis von FHEM vermittelt, auch wenn manches nicht mehr ganz aktuell ist. So sollte man z.B. ein direktes Editieren der fhem.cfg unterlassen.&lt;br /&gt;
&lt;br /&gt;
Im Folgenden werden immer wieder Auszüge aus der [[Konfiguration]] dargestellt. Diese dienen zur Erläuterung und Veranschaulichung. Die Bearbeitung der [[Konfiguration]] sollte - zur Verhinderung von Fehlern - nach Möglichkeit immer über das &amp;quot;[[Konfiguration#Befehl-Eingabefeld|Befehl-Eingabefeld]]&amp;quot; und die &amp;quot;[[Konfiguration#Objektdetails|Objektdetails]]&amp;quot; erfolgen.&lt;br /&gt;
&lt;br /&gt;
=== Vorbereitung: Gateway ===&lt;br /&gt;
Zunächst ist das I/O-Device zu definieren, also das Gateway. Dies ist in [[MYSENSORS]] beschrieben.&lt;br /&gt;
{{Hinweis|Bei Verwendung eines seriellen Gateways ist zu empfehlen, einen Arduino mit orginalem FTDI-Chip zu verwenden und diesen mit der &amp;quot;by-id&amp;quot;-Methode ([[Trick_der_Woche#CUL_.26_CO_.C3.BCber_Serial_ID-einbinden]]) zuzuweisen. Beim Anschluß mehrer Arduinos mit einem CHG340/CHG341 an denselben Computer/Raspberry sind diese nur mit hohem {{Link2Forum|Topic=44926|Message=446809|LinkText=Aufwand}} eindeutig addressierbar.}}&lt;br /&gt;
{{Hinweis|Die Einbindung eines MySensors-Netzwerks kann auch über [http://fhem.de/commandref.html#MQTT MQTT] erfolgen. Dabei übernimmt ein MySensors-MQTT-Gateway die Kommunikation mit dem Broker. Der Autor hat hier jedoch keine eigene Erfahrung, bitte entsprechend nachtragen!}}&lt;br /&gt;
&lt;br /&gt;
Serielles Gateway am Raspberry PI:&lt;br /&gt;
 define MyGateway_0 MYSENSORS /dev/ttyUSB0@115200&lt;br /&gt;
&lt;br /&gt;
Nach erfolgreicher Definition ist das Gateway im Raum &amp;quot;Everything&amp;quot; in der Gruppe &amp;quot;MYSENSORS&amp;quot; zu finden. Wenn unten &amp;quot;initialized&amp;quot; oder &amp;quot;opened&amp;quot; angezeigt wird, ist FHEM in der Lage, mit dem MySensors-Netz zu kommunizieren. Es sollte dann noch auf [[autocreate]] gestellt werden.&lt;br /&gt;
&lt;br /&gt;
=== Das Gateway ist auch ein MySensors-Device  ===&lt;br /&gt;
{{Hinweis|Sobald die ersten Meßwerte übertragen wurden, werden &#039;&#039;&#039;nach einem Browser-Refresh&#039;&#039;&#039; auch die aktuellen Meßwerte angezeigt, dies kann je nach Einstellung im Sketch aber einige Zeit dauern.}}&lt;br /&gt;
{{Randnotiz|RNTyp=g|RNText=Die Readings werden dem Modul MYSENSOR_DEVICE.pm entnommen. Sind diese dort nicht im Bereich &amp;quot;reads&amp;quot; bzw. &amp;quot;sends&amp;quot; enthalten, kann man fehlende Readings auch manuell anlegen. }}&lt;br /&gt;
Da am Gateway gleichzeitig auch bereits Sensoren angeschlossen sein können, legt FHEM direkt auch ein erstes [[MYSENSORS_DEVICE]] mit der NodeID &amp;quot;0&amp;quot; an. Sollten bereits ChildIDs im presentation()-Abschnitt des Gateway-Sketches enthalten gewesen sein, werden auch die zum Typ des präsentierten Sensor-Child-Typs passenden Readings automatisch angelegt. &lt;br /&gt;
&lt;br /&gt;
=== Das erste Funk-MySensors-Device ===&lt;br /&gt;
In der Regel ist aber das erste &amp;quot;echte&amp;quot; MySensors-Device die 2. Node, die neben dem Gateway in Betrieb genommen wird. Hier gilt das Vorgesagte entsprechend: Nach dem ersten Start sind neu erkannte Devices ebenfalls im Raum &amp;quot;Everything&amp;quot; in der Gruppe &amp;quot;MYSENSORS&amp;quot; zu finden, die readings werden automatisch angelegt. Sobald Meßwerte übermittelt werden, werden die Readings damit gefüllt und entsprechend der per Sketch programmierten Vorgaben aktualisiert.&lt;br /&gt;
&lt;br /&gt;
=== Details der Wechselwirkung zwischen FHEM und MySensors ===&lt;br /&gt;
==== Vergabe der NodeID ====&lt;br /&gt;
Die Vergabe der NodeID kann entweder im einzelnen Sketch erfolgen oder automatisiert. Dabei vergibt FHEM in der Regel fortlaufend Nummern ab 100. Die erste Node mit automatischer Nummernvergabe ist daher in der Regel das Device MYSENSORS_100. &lt;br /&gt;
{{Hinweis|Die NodeID wird - wie einige weitere Informationen - im sog. EEPROM des Arduinos abgespeichert. Ist sie einmal vergeben, ändert sie sich auch bei einem erneuten flashen der Node nicht mehr, es sei denn, man gibt per &amp;quot;define&amp;quot; im Sketch eine andere NodeID vor.}}&lt;br /&gt;
&lt;br /&gt;
==== Fehlende Sensor-Typen und Readings ====&lt;br /&gt;
Für Anfänger ist zu empfehlen, nur Typen und Variablen zu nutzen, die in der 10_MYSENSORS_DEVICE.pm auch hinterlegt sind. Die Angaben dort zu &amp;quot;receives&amp;quot; und &amp;quot;sends&amp;quot; sind aus der Sicht der Node gemeint. Gibt es einzelne Sensor-Typen oder Readings (noch) nicht, gibt es folgende Möglichkeiten:&lt;br /&gt;
*Noch nicht vorhandene Typen kann man umgehen, indem man vergleichbare andere nimmt, also z.B. Wasser- statt Gaszähler (Stand: 11/2015)&lt;br /&gt;
*Fehlende Readings können auch &lt;br /&gt;
**in die 10_MYSENSORS_DEVICE.pm manuell eingepflegt werden, das automatische Anlegen geht dann aber ggf. bei einem Update wieder verloren&lt;br /&gt;
**manuell, z.B. &amp;lt;code&amp;gt;attr MYSENSOR_99 mapReading_ir_send3 3 ir_send&amp;lt;/code&amp;gt;&lt;br /&gt;
Ist das Reading einmal angelegt, wird es auch automatisch befüllt, sobald die Node einen entsprechenden Wert sendet.&lt;br /&gt;
&lt;br /&gt;
==== Austausch von Variablen oder Texten ====&lt;br /&gt;
Es ist möglich, Informationen auch bidirektional zwischen FHEM und den Nodes auszutauschen. Dies ermöglicht z.B. die Ansteuerung von Displays oder die Konfiguration von FHEM aus. Hierzu ist es am einfachsten, ein oder mehrere S_CUSTOM-Child zu präsentieren, die jeweils bis zu 5 Variablen ermöglichen. Die Zuordnung innerhalb der Node zu internen Variablen erfolgt dann über die Auswertung der Messages entsprechend der [https://forum.mysensors.org/topic/1817/weather-and-forecast-display-for-swedish-fhem-users/2 ChildID und der Variablennummer].&lt;br /&gt;
&lt;br /&gt;
==== OTA ====&lt;br /&gt;
MySensors unterstützt für NRF-Chips zwar grundsätzlich OTA-updates, man muß dafür aber vorübergehend einen anderen Controller als FHEM einsetzen (Stand 11/2016). &lt;br /&gt;
Ein Howto ist in diesem {{Link2Forum|Topic=59388.0|LinkText=Forenbeitrag}} zu finden.&lt;br /&gt;
Der dort verwendete Bootloader erwartet OTA-Updates fest auf Channel 76.&lt;br /&gt;
&lt;br /&gt;
== Links, Tricks, Kniffe und Erfahrungen ==&lt;br /&gt;
&lt;br /&gt;
=== Interessante Links ===&lt;br /&gt;
==== Offizielles Debugging-Schema ====&lt;br /&gt;
*[https://forum.mysensors.org/topic/666/debug-faq-and-how-ask-for-help Debug / FAQ bei MySensors.org]&lt;br /&gt;
&lt;br /&gt;
==== Vorgehensweise zur Kombination von mehreren Sketchen/Sensoren an einer Node ====&lt;br /&gt;
Mehrere Sensoren (Children) kann man recht einfach an einen einzigen Arduino anschließen und ist dabei nur durch die Größe des Speichers begrenzt. Die Vorgehensweise erläutert dieses [https://forum.mysensors.org/topic/2597/combining-mysensors-examples/2 Beispiel] .&lt;br /&gt;
==== Verschlüsselung und Signierung ====&lt;br /&gt;
*{{Link2Forum|Topic=67248|LinkText=Forumsbeitrag zu MySensors Verschlüsselung und Signierung}}&lt;br /&gt;
*[https://www.mysensors.org/about/signing Darstellung bei MySensors.org]&lt;br /&gt;
&lt;br /&gt;
=== EEPROM ===&lt;br /&gt;
Die Nodes speichern einen Teil ihrer Einstellungen im sog. EEPROM. Dazu gehören z.B. die NodeID, der letzte bekannte &amp;quot;nächste&amp;quot; Punkt im Netzwert (RepeaterID) oder der Zustand von Relais. In der Regel ist nur die NodeID problematisch und kann beim flashen per Sketch auf einen anderen als den bisherigen Wert gestellt werden. Wer dennoch das EEPROM löschen möchte, muß den &#039;&#039;&#039;MySensor-Lösch-Sketch&#039;&#039;&#039; nehmen, der nicht &amp;quot;0000...&amp;quot; ins EEPROM schreibt wie der Arduino-Standard-Lösch-Sketch, sondern &amp;quot;FFFF...&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Funk-Themen (NRF-Chips) ===&lt;br /&gt;
Viele berichtete Probleme bei der Einrichtung von MySensors-Netzwerken haben ihren Ursprung in einer unzureichenden Funkverbindung. {{Hinweis|Ob dies der Fall ist, läßt sich leicht testen, indem man die fragliche Node wieder in die Nähe des Gateways bringt. Funktioniert es dort wie erwartet, liegt eine schlechte Funkverbindung vor.}}&lt;br /&gt;
&lt;br /&gt;
==== Abhilfemaßnahmen ====&lt;br /&gt;
*Einen bzw. mehrere [https://www.mysensors.org/build/connect_radio#connecting_a_decoupling-capacitor Kondensatoren] einlöten. Es sind auch fertige Module erhältlich, die diese Bauteile und einen Spannungsregler bereits enthalten, auf die der NRF mit einem Stecksockel aufgesteckt wird.&lt;br /&gt;
*Einen anderen Kanal wählen; die verwendeten Frequenzen liegen im b/g-WLAN-Bereich, so dass wechselseitige Störungen möglich sind. In Deutschland sind die Kanäle bis 84 erlaubt.&lt;br /&gt;
*NRF tauschen (Fake NRF-Chips sind zwar verwendbar, haben aber eine deutlich reduzierte Funkreichweite)&lt;br /&gt;
*Ein allgemeiner Guide zur Verwendung der nrf24l01+-Module ist [https://arduino-info.wikispaces.com/Nrf24L01-2.4GHz-HowTo hier] zu finden.&lt;br /&gt;
*Für das Gateway empfielt es sich, ein Modul mit externer Antenne zu verwenden (NRF24L01+PA+LNA Antenna version).&lt;br /&gt;
*Einstellen des richtigen PA_LEVEL_...s: Insbesondere der Standardsketch für das serielle Gateway definiert diesen als LOW, was korrekt ist, wenn der interne Spannungsregler des Arduino verwendet ist. Besser ist es, die benötigten 3,3V mittels eines seperaten Spannungsreglers zu erzeugen und dann den PA_LEVEL_MAX einzustellen. &lt;br /&gt;
*Funkstrecken lassen sich recht unkompliziert mit Repeatern überbrücken. Dieser muß nicht zwingend eine eigene Node sein. Jede (sinnvollerweise nicht Batterie-gespeiste) Node kann per &amp;lt;code&amp;gt; #define MY_REPEATER_FEATURE &amp;lt;/code&amp;gt; zum Repeater gemacht werden.&lt;br /&gt;
*Sonstige Vorschläge ohne Erfolgsgarantie, aber mit Unterhaltungswert:&lt;br /&gt;
**[http://www.instructables.com/id/Enhanced-NRF24L01/ Eigenbau-Antennenverbesserung]&lt;br /&gt;
**[http://blog.blackoise.de/2016/02/fixing-your-cheap-nrf24l01-palna-module/ Schirmung]&lt;br /&gt;
&lt;br /&gt;
==== Buffer-Management ====&lt;br /&gt;
Die NRF-Chips haben nur einen begrenzten Speicher, um Nachrichten zu puffern. Dieser kann überlaufen, wenn in kurzer Folge Informationen versendet werden, z.B. mehr als 5 Temperaturwerte von 1-Wire-Sensoren. Diese Problematik verschärft sich bei der Verwendung von Message-Signing, weil dort die volle payload-Bandbreite für einzelne Nachrichten genutzt wird. Für Abhilfe sorgen kurze Pausen zwischen den einzelnen Sendungen, z.B. &amp;lt;code&amp;gt;wait(30);&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== RS485 ===&lt;br /&gt;
Seit 2.0.1 ist es möglich, statt der Funkmodule auch ein kabelgebundenes Netzwerk auf Basis von RS485-Modulen aufzubauen; hierfür werden 2 Adern als Datenleitung benötigt, die Zahl der Nodes in einem solchen Netzwerk ist bei Verwendung der Standardmodule auf 32 beschränkt, bei Verwendung anderer Transceiver sind auch mehr Nodes möglich. Hierfür ist ein seperates Gateway erforderlich.&lt;br /&gt;
&lt;br /&gt;
==== Bekannte Probleme bei RS485 ====&lt;br /&gt;
(Stand: 2.1.1) &lt;br /&gt;
&lt;br /&gt;
*Die Vergabe der Node-ID&#039;s muß im Sketch selbst erfolgen, die automatische Zuweisung funktioniert nicht.&lt;br /&gt;
*Die für die Anbindung der Module definierten PINs (8+9) sind tief im Code verankert und sollten nicht geändert werden.&lt;br /&gt;
&lt;br /&gt;
=== Ablauf des Starts einer Node ===&lt;br /&gt;
Beim Start durchlaufen alle Nodes nacheinander bestimmte vordefinierte Programmroutinen in folgender Reihenfolge:&lt;br /&gt;
&lt;br /&gt;
==== Vorversionen ====&lt;br /&gt;
*setup()&lt;br /&gt;
*presentation()&lt;br /&gt;
*loop()&lt;br /&gt;
&lt;br /&gt;
==== seit MySensors 2.1.0 ====&lt;br /&gt;
*preHwInit()&lt;br /&gt;
*before()&lt;br /&gt;
*presentation()&lt;br /&gt;
*setup()&lt;br /&gt;
*loop()&lt;br /&gt;
&lt;br /&gt;
==== Im Detail ====&lt;br /&gt;
Dieser Ablauf ermöglicht, die Arduino-Pins vorzukonfigurieren und angeschlossenes Equipment an der für den Programmablauf richtigen Stelle zu initialisieren. Dies ist u.U. wichtig, da &lt;br /&gt;
*eine Node im Normalfall nicht in loop() geht, solange die presentation() nicht erfolgreich war (also solange der Controller nicht verfügbar ist). Eine Failsafe-Initialisierung von Schnittstellen sollte demnach in preHwInit() oder before() erfolgen. Es kann zusätzlich seit 2.1.1 auch die Option MY_TRANSPORT_WAIT_READY_MS min. auf 1 gesetzt werden, dann startet die loop() auch ohne Verbindung zum Gateway.&lt;br /&gt;
*die Initialisierung anderer SPI-Hardware auf einem gemeinsamen Bus mit den NRF-Modulem vor der presentation() erfolgen muß.&lt;br /&gt;
&lt;br /&gt;
=== Beispiel-Sketche ===&lt;br /&gt;
*[https://forum.mysensors.org/topic/938/multisensor-multiactuator-sketch-testboard-tested-with-fhem-controller Mehrfachsensor], allerdings noch für MySensors Vers. 1.5.4&lt;br /&gt;
*Bidirektionale {{Link2Forum|Topic=26807|msg=449776|LinkText=&amp;quot;Infrarot-Fernbedienung&amp;quot;}} aus FHEM raus iVm. remotecontrol&lt;br /&gt;
*mehrere [https://github.com/rejoe2/MySensors-Dallas-Address-ChildID-Consistency Dallas-Temperatursensoren] auf einem Bus eindeutig erkennen&lt;br /&gt;
*[https://forum.mysensors.org/topic/1817/weather-and-forecast-display-for-swedish-fhem-users/2 Display] ansteuern&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Arduino]]&lt;br /&gt;
[[Kategorie:IP Components]]&lt;br /&gt;
[[Kategorie:Other Components]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=DevelopmentModuleIntro&amp;diff=20028</id>
		<title>DevelopmentModuleIntro</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=DevelopmentModuleIntro&amp;diff=20028"/>
		<updated>2017-02-16T20:05:00Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: Änderung 20027 von Kaihs (Diskussion) rückgängig gemacht.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Dieser Text ist in Arbeit und muss noch an einigen Stellen ergänzt werden. }}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Um neue Geräte, Dienste, o.ä. in FHEM verfügbar zu machen, kann man ein eigenes Modul in Perl schreiben. Ein Modul wird in FHEM automatisch geladen, wenn ein entsprechendes Device in FHEM definiert wird. Das Modul ermöglicht eine spezifische Kommunikation mit einem physikalischen Gerät, stellt Ergebnisse (&amp;quot;Readings&amp;quot;) und Events innerhalb von FHEM zur Verfügung und erlaubt es, das Gerät mit &amp;quot;Set&amp;quot;-/&amp;quot;Get&amp;quot;-Befehlen zu beeinflussen. Dieser Artikel soll den Einstieg in die Entwicklung eigener Module erleichtern.&lt;br /&gt;
&lt;br /&gt;
Mit dem FHEM-Befehl &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt; werden Devices in FHEM basierend auf einem Modul definiert. Dieser Befehl sorgt dafür, dass ein neues Modul bei Bedarf geladen und initialisiert wird. Ein gutes Beispiel ist hierbei die zentrale Konfigurationsdatei &amp;quot;fhem.cfg&amp;quot; in der sämtliche Devices in Form von &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt;-Statements gespeichert sind.&lt;br /&gt;
&lt;br /&gt;
Damit das funktioniert müssen der Name des Moduls und der Name der [[#X_Initialize|Initialisierungsfunktion]]  identisch sein. Das folgende Beispiel soll dies verdeutlichen:&lt;br /&gt;
&lt;br /&gt;
Ein Jeelink USB-Stick könnte beispielsweise mit dem Befehl &amp;lt;code&amp;gt;define JeeLink1 &#039;&#039;JeeLink&#039;&#039; /dev/ttyUSB0@57600&amp;lt;/code&amp;gt; definiert werden.&lt;br /&gt;
&lt;br /&gt;
In fhem.pl wird der define-Befehl verarbeitet und geprüft, ob ein Modul mit dem Namen &amp;quot;JeeLink&amp;quot; schon geladen ist und falls nicht ein Modul mit Namen XY_JeeLink.pm im Modulverzeichnis (z.B. /opt/fhem/FHEM) gesucht und dann geladen. &lt;br /&gt;
Danach wird die Funktion &amp;lt;code&amp;gt;&#039;&#039;JeeLink&#039;&#039;_Initialize()&amp;lt;/code&amp;gt; aufgerufen um das Modul in FHEM zu registrieren. Eine Moduldatei muss dazu eine Funktion &amp;lt;code&amp;gt;&#039;&#039;&amp;amp;lt;Modulname&amp;amp;gt;&#039;&#039;_Initialize()&amp;lt;/code&amp;gt; enthalten. Durch den Aufruf dieser Funktion wird FHEM mitgeteilt, welche Funktionalitäten dieses Modul unterstützt.&lt;br /&gt;
&lt;br /&gt;
In der Initialisierungsfunktion des Moduls werden die Namen aller weiteren Perl-Funktionen des Moduls, die von fhem.pl aus aufgerufen werden, bekannt gemacht. Dazu wird für jedes Modul ein eigener Hash (genauer &amp;quot;Modul-Hash&amp;quot;) mit entsprechenden Werten gefüllt, der in fhem.pl für jedes Modul entsprechend abgelegt wird. Dadurch weiß FHEM wie dieses Modul anzusprechen ist.&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau eines Moduls ==&lt;br /&gt;
&lt;br /&gt;
=== Dateiname ===&lt;br /&gt;
&lt;br /&gt;
Ein FHEM-Modul wird als Perl-Modul mit der Dateiendung *.pm abgespeichert. Der Dateiname folgt dabei folgendem Schema:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;&#039;&#039;[&#039;&#039;&#039;Schlüsselnummer&#039;&#039;&#039;]&#039;&#039;&amp;lt;font color=&amp;quot;grey&amp;quot;&amp;gt;_&amp;lt;/font&amp;gt;&#039;&#039;[&#039;&#039;&#039;Modulname&#039;&#039;&#039;]&#039;&#039;&amp;lt;font color=&amp;quot;grey&amp;quot;&amp;gt;.pm&amp;lt;/font&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Schlüsselnummer&#039;&#039;&#039; - Eine zweistellige Zahl zwischen 00 - 99. Die Schlüsselnummer hat aktuell keine technische Relevanz mehr. In früheren FHEM-Versionen ist sie relevant für [[#Zweistufiges_Modell_f.C3.BCr_Module|zweistufige Module]] (Reihenfolge für [[DevelopmentModuleAPI#Dispatch|Dispatch()]] um logische Module zu prüfen). Die allgemeine Empfehlung ist hierbei eine Schlüsselnummer eines Moduls zu verwenden, welches eine ähnliche Funktionalität bietet. Die Schlüsselnummer 99 hat hierbei eine besondere Bedeutung, da alle Module mit dieser Schlüsselnummer beim Start von FHEM automatisch geladen werden, selbst, wenn sie in der Konfiguration nicht verwendet werden. Daher wird für myUtils 99 als Schlüsselnummer verwendet (99_myUtils.pm). Module mit der Schlüsselnummer 99 werden im SVN nicht akzeptiert (siehe [[SVN Nutzungsregeln]])&lt;br /&gt;
* &#039;&#039;&#039;Modulname&#039;&#039;&#039; - Der Name des Moduls wie er in FHEM bei dem Anlegen einer Gerätedefinition zu verwenden ist. Der Modulname sollte nur aus den folgenden möglichen Zeichen bestehen: Groß-/Kleinbuchstaben, Zahlen sowie Unterstrich (_)&lt;br /&gt;
&lt;br /&gt;
=== Inhaltlicher Aufbau ===&lt;br /&gt;
&lt;br /&gt;
Ein Modul ist inhaltlich in folgende Abschnitte unterteilt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
#  72_MYMODULE.pm &lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
package main;&lt;br /&gt;
&lt;br /&gt;
# Laden evtl. abhängiger Perl- bzw. FHEM-Module&lt;br /&gt;
use HttpUtils;&lt;br /&gt;
use [...]&lt;br /&gt;
&lt;br /&gt;
# FHEM Modulfunktionen&lt;br /&gt;
&lt;br /&gt;
sub MYMODULE_Initialize() {&lt;br /&gt;
   ...&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub MYMODULE_Define() {&lt;br /&gt;
   ...&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
# Eval-Rückgabewert für erfolgreiches&lt;br /&gt;
# Laden des Moduls&lt;br /&gt;
1;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Beginn der Commandref&lt;br /&gt;
&lt;br /&gt;
=pod&lt;br /&gt;
=item [helper|device|command]&lt;br /&gt;
=item summary Kurzbeschreibung in Englisch was MYMODULE steuert/unterstützt&lt;br /&gt;
=item summary_DE Kurzbeschreibung in Deutsch was MYMODULE steuert/unterstützt&lt;br /&gt;
&lt;br /&gt;
=begin html&lt;br /&gt;
 Englische Commandref in HTML&lt;br /&gt;
=end html&lt;br /&gt;
&lt;br /&gt;
=begin html_DE&lt;br /&gt;
 Deustche Commandref in HTML&lt;br /&gt;
=end html&lt;br /&gt;
&lt;br /&gt;
# Ende der Commandref&lt;br /&gt;
=cut&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man kann hierbei von folgender Reihenfolge sprechen:&lt;br /&gt;
&lt;br /&gt;
# Perl-Code, welcher das Modul implementiert&lt;br /&gt;
# Die Zeile &amp;lt;code&amp;gt;1;&amp;lt;/code&amp;gt; nachdem der Perl-Code abgeschlossen ist. Dies dient FHEM der Erkennung, dass das Modul erfolgreich und vollständig geladen wurde. Sollte diese Zeile nicht enthalten sein, wird FHEM beim Laden des Moduls die Fehlermeldung &amp;lt;code&amp;gt;Error:Modul 72_MYMODULE deactivated&amp;lt;/code&amp;gt; in das Logfile schreiben.&lt;br /&gt;
# Commandref zur Dokumentation des Moduls. Diese Dokumentation soll dem User die möglichen Befehle/Attribute/Readings/Events vermitteln. Weitere Informationen und Hinweise findet man in den [[Guidelines zur Dokumentation]].&lt;br /&gt;
&lt;br /&gt;
== Der Hash einer Geräteinstanz ==&lt;br /&gt;
Eine Besonderheit in Perl sind [http://de.wikipedia.org/wiki/Assoziatives_Array#Perl assoziative Arrays], (nicht ganz richtig als &amp;quot;Hash&amp;quot; bezeichnet) in denen die Adressierung nicht über eine Zählvariable erfolgt, sondern über einen beliebigen String. Die internen Abläufe bei der Adressierung führen dazu, dass die Speicherung in und der Abruf aus Hashes relativ langsam ist.&lt;br /&gt;
&lt;br /&gt;
Der zentrale Speicherort für Informationen einer Geräteinstanz bei FHEM ist ein solcher Hash, der seinerseits in fhem.pl von einem globalen Hash referenziert wird. &lt;br /&gt;
&lt;br /&gt;
In fhem.pl werden alle Gerätedefinitionen in dem globalen Hash &amp;lt;code&amp;gt;%defs&amp;lt;/code&amp;gt; abgelegt. Der Inhalt von &amp;lt;code&amp;gt;$defs{&#039;&#039;&amp;amp;lt;Name&amp;amp;gt;&#039;&#039;}&amp;lt;/code&amp;gt; in fhem.pl verweist dabei auf den Hash der Geräteinstanz in Form einer Hashreferenz. Diesen Verweis (also nur die Adresse) bekommen die Funktionen eines Moduls übergeben (i.d.R. als &amp;lt;code&amp;gt;$hash&amp;lt;/code&amp;gt; bezeichnet), welche direkt von fhem.pl aufgerufen werden. In dem Hash stehen beispielsweise die internen Werte des Geräts, die im Frontend als &amp;quot;Internals&amp;quot; angezeigt werden, sowie die Readings des Geräts. &lt;br /&gt;
&lt;br /&gt;
Beispiele:&lt;br /&gt;
*&amp;lt;code&amp;gt;$hash-&amp;gt;{NAME}&amp;lt;/code&amp;gt; enthält den Namen der Geräteinstanz, &lt;br /&gt;
*&amp;lt;code&amp;gt;$hash-&amp;gt;{TYPE}&amp;lt;/code&amp;gt; enthält die Typbezeichnung des Geräts (Modulname)&lt;br /&gt;
&lt;br /&gt;
==Ausführung von Modulen==&lt;br /&gt;
FHEM arbeitet intern nicht parallel, sondern arbeitet alle Aufgaben seriell nacheinander kontinuierlich ab. Daher wäre es ungünstig, wenn Module Daten von einem physikalischen Gerät abfragen wollen und dabei innerhalb der selben Funktion auf die Antwort des Geräts warten. In dieser Zeit, in der FHEM auf die Antwort des Gerätes warten muss, wäre der Rest von FHEM blockiert. Da immer nur eine Aufgabe zur selben Zeit bearbeitet wird, müssen alle weiteren Aufgaben solange warten. Eine Datenkommunikation innerhalb eines Moduls sollte daher immer ohne Blockierung erfolgen. Dadurch kann FHEM die Wartezeit effizient für andere Aufgaben nutzen um bspw. anstehende Daten für andere Module zu verarbeiten. Es gibt in FHEM entsprechende Mechanismen, welche eine &amp;quot;Non-Blocking&amp;quot;-Kommunikation über verschiedene Wege (z.B. seriell, HTTP, TCP, ...) ermöglichen.&lt;br /&gt;
&lt;br /&gt;
Dafür werden in FHEM zwei zentrale Listen gepflegt, in der die Filedeskriptoren der geöffneten Kommunikatonsverbindungen gespeichert sind. Auf Linux- bzw. Unix-basierten Plattformen wird der select-Befehl des Betriebssystems verwendet um Filedeskriptoren auf lesbare Daten zu überprüfen. In FHEM gibt es dazu eine Liste (&amp;lt;code&amp;gt;%selectlist&amp;lt;/code&amp;gt;), in der die Filedeskriptoren sämtlicher Geräte (z.B. serielle Verbindung, TCP-Verbindung, etc.) gespeichert sind. &lt;br /&gt;
&lt;br /&gt;
In der zentralen Schleife (Main-Loop) von fhem.pl wird mit &amp;lt;code&amp;gt;select()&amp;lt;/code&amp;gt; überwacht, ob über eine der geöffneten Schnittstellen Daten zum Lesen anstehen. Wenn dies der Fall ist, dann wird die Lesefunktion ([[#X_Read|X_Read]]) des zuständigen Moduls aufgerufen, damit es die Daten entgegennimmt und verarbeitet. Anschließend wird die Schleife weiter ausgeführt.&lt;br /&gt;
&lt;br /&gt;
Auf Windows-Systemen funktioniert dies anders. Hier können USB/Seriell-Geräte nicht per &amp;lt;code&amp;gt;select()&amp;lt;/code&amp;gt; überwacht werden. In FHEM unter Windows werden daher diese Schnittstellen kontinuierlich abgefragt ob Daten bereitstehen. Dafür müssen Module zusätzlich zur Lesefunktion eine Abfragefunktion ([[#X_Ready|X_Ready]]) implementieren, welche prüft, ob Daten zum Lesen anstehen. Auch auf Linux/Unix-Plattformen hat diese Funktion eine Aufgabe. Falls nämlich eine Schnittstelle ausfällt, beziehungsweise ein CUL oder USB-zu-Seriell Adapter ausgesteckt wird, dann wird über diese Funktion regelmäßig geprüft ob die Schnittstelle wieder verfügbar wird.&lt;br /&gt;
&lt;br /&gt;
Innerhalb der eigentlichen Lesefunktion (X_Read) werden dann die Daten vom zugehörigen Gerät gelesen, das nötige Protokoll implementiert um die Daten zu interpretieren und Werte in Readings geschrieben.&lt;br /&gt;
&lt;br /&gt;
Auch wenn von einem Anwender über einen Get-Befehl Daten aktiv von einem Gerät angefordert werden, sollte nicht blockierend gewartet werden. Eine asynchrone Ausgabe, sobald das Ergebnis vorliegt, ist über [[DevelopmentModuleAPI#asyncOutput|asyncOutput()]] möglich. Siehe {{Link2Forum|Topic=43771|Message=357870|LinkText=Beschreibung}} und {{Link2Forum|Topic=43771|Message=360935|LinkText=Beispiel}}. Weitere Anwendungsbeispiele finden sich im  {{Link2Forum|Topic=43052|Message=353477|LinkText=PLEX Modul}} und im überarbeiteten und nicht-blockierenden {{Link2Forum|Topic=42771|Message=348498|LinkText=SYSSTAT Modul}}.&lt;br /&gt;
&lt;br /&gt;
== Wichtige globale Variablen aus fhem.pl ==&lt;br /&gt;
&lt;br /&gt;
FHEM arbeitet mit einer Vielzahl an internen Variablen. Die nun folgenden aufgelisteten Variablen sind die wichtigsten, welche man im Rahmen der Modulprogrammierung kennen sollte:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Variable !! Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$init_done&amp;lt;/code&amp;gt; || Dient der Erkennung für fhem.pl sowie den Modulen, ob FHEM den Initialisierungsvorgang abgeschlossen hat. Beim Starten von FHEM ist &amp;lt;code&amp;gt;$init_done&amp;lt;/code&amp;gt; gleich &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;. Erst, wenn das Einlesen der Konfiguration, sowie des State-Files (Readings) abgeschlossen ist, wird &amp;lt;code&amp;gt;$init_done&amp;lt;/code&amp;gt; auf &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; gesetzt.&lt;br /&gt;
Das gleiche Verfahren wird auch bei dem Befehl &amp;lt;code&amp;gt;rereadcfg&amp;lt;/code&amp;gt; angewandt. Während &amp;lt;code&amp;gt;rereadcfg&amp;lt;/code&amp;gt; ausgeführt wird (Konfiguration löschen, neu einlesen), ist &amp;lt;code&amp;gt;$init_done&amp;lt;/code&amp;gt; gleich &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Dies ist insbesondere in der [[#X_Define|Define]]-Funktion eines Moduls relevant.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;%attr&amp;lt;/code&amp;gt; || In &amp;lt;code&amp;gt;%attr&amp;lt;/code&amp;gt; werden sämtliche gesetzten Attribute aller Geräte gespeichert. Diese Datenstruktur wird generell durch den &amp;lt;code&amp;gt;attr&amp;lt;/code&amp;gt;-Befehl verwaltet. Hierbei wird einem Gerätenamen eine Mehrzahl an Attributnamen mit einem Wert zugeordnet. Attribut-Inhalte können über die Funktion [[DevelopmentModuleAPI#AttrVal|AttrVal()]] ausgelesen werden.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;%cmds&amp;lt;/code&amp;gt; || In &amp;lt;code&amp;gt;%cmds&amp;lt;/code&amp;gt; wird jedem in FHEM existierendem Befehl die entsprechende Funktion zugewiesen, welche diesen Befehl umsetzt. Module können durch das Eintragen eines Befehlsnamen samt Funktion in &amp;lt;code&amp;gt;%cmds&amp;lt;/code&amp;gt; über die [[#X_Initialize|Initialize]]-Funktion eines Moduls einen (oder mehrere) eigene Befehle in FHEM registrieren.&lt;br /&gt;
&lt;br /&gt;
Die Struktur ist dabei wiefolgt:&lt;br /&gt;
&lt;br /&gt;
  $cmds{&#039;&#039;&amp;amp;lt;Befehlsname&amp;amp;gt;&#039;&#039;} = {  Fn  =&amp;gt; &amp;quot;&#039;&#039;&amp;amp;lt;Funktionsname&amp;amp;gt;&#039;&#039;&amp;quot;,&lt;br /&gt;
                            Hlp =&amp;gt; &amp;quot;&#039;&#039;&amp;amp;lt;Aufrufsyntax&amp;amp;gt;&#039;&#039;&amp;quot;};&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;%data&amp;lt;/code&amp;gt;|| Der eigentliche Zweck von &amp;lt;code&amp;gt;%data&amp;lt;/code&amp;gt; ist dem Nutzer eine Möglichkeit zum Speichern von temporären Daten im globalen Kontext zu ermöglichen. Einige Module verwenden &amp;lt;code&amp;gt;%data&amp;lt;/code&amp;gt; jedoch auch um modul- &amp;amp; geräteübergreifend Daten auszutauschen.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;%defs&amp;lt;/code&amp;gt;|| In &amp;lt;code&amp;gt;%defs&amp;lt;/code&amp;gt; werden sämtliche Gerätedefinitionen, bzw. die Hash-Referenzen auf diese, gespeichert. Hier ist jedem Gerätenamen eine Hash-Referenz zugeordnet.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;%modules&amp;lt;/code&amp;gt;|| In &amp;lt;code&amp;gt;%modules&amp;lt;/code&amp;gt; sind alle geladenen Module gelistet mit ihren entsprechenden Initialisierungsdaten (Funktionsnamen, Attribut-Listen, spezielle Einstellungen, ...). Hier wird für jeden Modulname der Modul-Hash aus der [[#X_Initialize|Initialize]]-Funktion gespeichert. &lt;br /&gt;
Desweiteren legen viele Module, welche nach dem [[DevelopmentModuleIntro#Zweistufiges_Modell_f.C3.BCr_Module|zweistufigen Modulkonzept]] hier eine Rückwärtszuordnung von Geräteadressen zu Geräte-Hash an.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;%readyfnlist&amp;lt;/code&amp;gt;|| In &amp;lt;code&amp;gt;%readyfnlist&amp;lt;/code&amp;gt; sind alle zu prüfenden Verbindungen mit ihrer entsprechendem Geräte-Hash gelistet. FHEM prüft alle hier gelisteten Geräte regelmäßig über eine Aufruf der entsprechenden [[#X_Ready|Ready]]-Funktion.&lt;br /&gt;
&lt;br /&gt;
Bei einer Nutzung von dem Hilfsmodul DevIo.pm zum Aufbau einer Kommunikationsverbindung, kümmert sich DevIo selbständig um den entsprechenden Eintrag in &amp;lt;code&amp;gt;%readyfnlist&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;%selectlist&amp;lt;/code&amp;gt;|| In &amp;lt;code&amp;gt;%selectlist&amp;lt;/code&amp;gt; sind alle geöffneten Verbindungen mit ihrer entsprechendem Geräte-Hash gelistet. FHEM prüft alle hier gelisteten Geräte, ob der geöffnete Filedeskriptor unter &amp;lt;code&amp;gt;$hash-&amp;gt;{FD}&amp;lt;/code&amp;gt; Daten zum Lesen bereitgestellt hat. Ist dass der Fall, wird die entsprechende [[#X_Read|Read]]-Funktion aufgerufen, um anstehende Daten durch das Modul zu verarbeiten.&lt;br /&gt;
Bei einer Nutzung von dem Hilfsmodul DevIo.pm zum Aufbau einer Kommunikationsverbindung, kümmert sich DevIo selbständig um den entsprechenden Eintrag in &amp;lt;code&amp;gt;%selectlist&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Es gibt durchaus viele weitere globale Variablen, die jedoch für sehr spezielle Anwendungsfälle und z.T. nur einzelne Module gedacht sind und daher hier nicht aufgeführt werden.&lt;br /&gt;
&lt;br /&gt;
== Internals ==&lt;br /&gt;
Daten, die ein Modul im Geräte-Hash speichert nennt man Internals. Sie werden als Unterstruktur des Hashes der jeweiligen Geräteinstanz gespeichert, beispielswiese &amp;lt;code&amp;gt;$hash-&amp;gt;{NAME}&amp;lt;/code&amp;gt; für den Gerätenamen, welcher beim Define-Befehl übergeben wurde und als Internal gespeichert wird. Diese Daten spielen für FHEM eine sehr wichtige Rolle, da sämtliche gerätespezifischen Daten als Internal im Gerätehash gespeichert werden.&lt;br /&gt;
&lt;br /&gt;
Falls Werte wie z.B. ein Intervall nicht über den Define-Befehl gesetzt werden sollen und im Betrieb einfach änderbar sein sollten, ist eine alternative Möglichkeit die Speicherung in so genannten Attributen. Dann würde man den Define-Befehl so implementieren, dass er kein Intervall übergeben bekommt und statt dessen das Interval als Attribut über den Befehl &amp;lt;code&amp;gt;attr&amp;lt;/code&amp;gt; gesetzt wird.&lt;br /&gt;
&lt;br /&gt;
Generell werden alle Werte, welche direkt in der ersten Ebene von &amp;lt;code&amp;gt;$hash&amp;lt;/code&amp;gt; (Gerätehash) gespeichert werden auf der Detail-Seite einer Definition in der FHEMWEB Oberfläche angezeigt. Es gibt jedoch Ausnahmen:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;$hash-&amp;gt;{helper}{URL]&amp;lt;/code&amp;gt; - Alle Elemente, welche als Unterelement wieder einen Hash besitzen werden nicht in FHEMWEB dargestellt. Typischerweise speichern Module Daten unter &amp;lt;code&amp;gt;$hash-&amp;gt;{helper}&amp;lt;/code&amp;gt; interne Daten zwischen, die für den User nicht relevant sind, sondern nur der internen Verarbeitung dienen.&lt;br /&gt;
* &amp;lt;code&amp;gt;$hash-&amp;gt;{&#039;&#039;&#039;.&#039;&#039;&#039;&amp;lt;font color=&amp;quot;grey&amp;quot;&amp;gt;ELEMENT&amp;lt;/font&amp;gt;}&amp;lt;/code&amp;gt; - Alle Knoten, welche mit einem Punkt beginnen werden in der FHEMWEB Oberfläche nicht angezeigt. Man kann diese Daten jedoch beim Aufruf des [[List|list-Kommandos]] einsehen.&lt;br /&gt;
&lt;br /&gt;
Es gibt bereits vorbelegte Internals welche in FHEM dazu dienen definitionsbezogene Informationen wie bspw. Namen und Readings zu speichern. Dies sind im besonderen:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;min-width: 13em;&amp;quot; | Internal !!  Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash-&amp;gt;{NAME}&amp;lt;/code&amp;gt;  || Der Definitionsname, mit dem das Gerät angelegt wurde.  &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash-&amp;gt;{READINGS}&amp;lt;/code&amp;gt;  || Enthält alle aktuell vorhandenen Readings. Daten unterhalb dieses Knotens sollte man nicht direkt manipulieren. Um Readings zu Erzeugen gibt es entsprechende [[DevelopmentModuleAPI#Readings_.2F_Events|Reading-Funktionen]].&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash-&amp;gt;{NR}&amp;lt;/code&amp;gt;  || Die Positions-Nr. der Definition innerhalb der Konfiguration. Diese dient dazu die Konfiguration in der gleichen Reihenfolge zu speichern, wie die einzelnen Geräte angelegt wurden.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash-&amp;gt;{TYPE}&amp;lt;/code&amp;gt;  || Der Modulname, mit welchem die Definition angelegt wurde.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash-&amp;gt;{DEF}&amp;lt;/code&amp;gt;  || Sämtliche Argumente, welche beim &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt;-Befehl nach dem Modulnamen übergeben wurden.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash-&amp;gt;{CFGFN}&amp;lt;/code&amp;gt;  || Der Dateiname der Konfigurationsdatei in der diese Definition enthalten ist (sofern nicht in fhem.cfg). Dieser Wert ist nur gefüllt, wenn man mit mehreren Konfigurationsdateien arbeitet, welche dann in fhem.cfg via include-Befehl eingebunden werden.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash-&amp;gt;{NTFY_ORDER}&amp;lt;/code&amp;gt;  || Sofern das Modul Events via [[DevelopmentModuleIntro#X_Notify|Notify-Funktion]] verarbeitet enthält jede Definition eine Notify-Order als Zeichenkette bestehend aus dem Notify Order Prefix und dem Definitionsnamen. Details zur Funktionsweise gibt es in der Beschreibung zur [[DevelopmentModuleIntro#X_Notify|Notify-Funktion]] im Abschnitt &amp;quot;Reihenfolge für den Aufruf der Notify-Funktion beeinflussen&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash-&amp;gt;{NOTIFYDEV}&amp;lt;/code&amp;gt;  || Sofern das Modul Events via NotifyFn verarbeitet kann man damit die Definitionen, von denen man Events erhalten will begrenzen. Details zur Funktionsweise gibt es in der Beschreibung zur [[DevelopmentModuleIntro#X_Notify|Notify-Funktion]] im Abschnitt &amp;quot;Begrenzung der Aufrufe auf bestimmte Geräte&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash-&amp;gt;{IODev}&amp;lt;/code&amp;gt;  || Hier wird das zugeordnete IO-Gerät durch [[DevelopmentModuleAPI#AssignIoPort|AssignIoPort()]] gespeichert, welches für den Datentransport und -empfang dieses logischen Gerätes zuständig ist. Dieser Wert existiert nur bei Modulen die nach dem [[DevelopmentModuleIntro#Zweistufiges_Modell_f.C3.BCr_Module|zweistufigen Modulkonzept]] arbeiten. &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash-&amp;gt;{CHANGED}&amp;lt;/code&amp;gt;  || Hier werden alle Events kurzzeitig gesammelt, welche für die Eventverarbeitung anstehen. Insbesondere die [[DevelopmentModuleAPI#Readings_.2F_Events|Reading-Funktionen]] speichern hier alle Events zwischen um sie nach Abschluss via [[DevelopmentModuleAPI#DoTrigger|DoTrigger()]] zu verarbeiten. &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash-&amp;gt;{FD}&amp;lt;/code&amp;gt;  || Wenn die Definition eine Netzwerkverbindung oder serielle Schnittstelle geöffnet hat (z.B. via DevIo), so wird der entsprechende File-Deskriptor in diesem Internal gespeichert. Damit kann FHEM alle geöffneten Filedeskriptoren der entsprechenden Definition zuordnen um bei ankommenden Daten die Definition via [[DevelopmentModuleIntro#X_Read|Read-Funktion]] damit zu versorgen.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash-&amp;gt;{EXCEPT_FD}&amp;lt;/code&amp;gt;  || Ähnlich wie &amp;lt;code&amp;gt;$hash-&amp;gt;{FD}&amp;lt;/code&amp;gt;. Sofern die Definition in &amp;lt;code&amp;gt;[[#Wichtige_globale_Variablen_aus_fhem.pl|%selectlist]]&amp;lt;/code&amp;gt; eingetragen ist und ein Fildeskriptor in diesem Internal gesetzt ist, wird bei einer auftretenden Exception bzw. Interrupt die [[DevelopmentModuleIntro#X_Except|Except]]-Funktion des entsprechenden Moduls aufgerufen um darauf zu reagieren.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Generell sollte man die meisten der hier genannten systemweiten Internals nicht modifizieren, da ansonsten die korrekte Funktionsweise von FHEM nicht mehr garantiert werden kann.&lt;br /&gt;
&lt;br /&gt;
== Readings ==&lt;br /&gt;
Daten, welche von einem Gerät gelesen werden und in FHEM in einer für Menschen verständlichen Form zur Verfügung gestellt werden können, werden Readings genannt. Sie geben den Status des Gerätes wieder und erzeugen Events innerhalb von FHEM auf die andere Geräte reagieren können. Sie werden als Unterstruktur des Hashes der jeweiligen Geräteinstanz gespeichert, beispielsweise &lt;br /&gt;
*&amp;lt;code&amp;gt;$hash-&amp;gt;{READINGS}{temperature}{VAL}&amp;lt;/code&amp;gt; für die Temperatur eines Fühlers&lt;br /&gt;
*&amp;lt;code&amp;gt;$hash-&amp;gt;{READINGS}{temperature}{TIME}&amp;lt;/code&amp;gt; für den Zeitstempel der Messung&lt;br /&gt;
&lt;br /&gt;
Für den lesenden Zugriff auf Readings steht die Funktion &amp;lt;code&amp;gt;[[DevelopmentModuleAPI#ReadingsVal|ReadingsVal()]]&amp;lt;/code&amp;gt; zur Verfügung. Ein direkter Zugriff auf die Datenstruktur sollte nicht vorgenommen werden.&lt;br /&gt;
&lt;br /&gt;
Readings werden im Statefile von FHEM automatisch auf der Festplatte zwischengespeichert, damit sie nach einem Neustart sofort wieder zur Verfügung stehen. Dadurch ist der letzte Status eines Gerätes vor einem Neustart nachvollziehbar.&lt;br /&gt;
&lt;br /&gt;
Readings, die mit einem Punkt im Namen beginnen, haben eine funktionale Besonderheit. Sie werden im FHEMWEB nicht angezeigt und können somit als &amp;quot;Permanentspeicher&amp;quot; für kleinere Daten innerhalb des Moduls genutzt werden. Um größere Datenmengen permanent zu speichern sollte man jedoch die Funktion &amp;lt;code&amp;gt;[[DevelopmentModuleAPI#setKeyValue|setKeyValue()]]&amp;lt;/code&amp;gt; verwenden.&lt;br /&gt;
&lt;br /&gt;
Zum Setzen von Readings sollen &lt;br /&gt;
*bei Gruppen von Readings der Funktionsblock &amp;lt;code&amp;gt;[[DevelopmentModuleAPI#readingsBeginUpdate|readingsBeginUpdate()]]&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;[[DevelopmentModuleAPI#readingsBulkUpdate|readingsBulkUpdate()]]&amp;lt;/code&amp;gt; (mehrfach wiederholt), &amp;lt;code&amp;gt;[[DevelopmentModuleAPI#readingsEndUpdate|readingsEndUpdate()]]&amp;lt;/code&amp;gt;&lt;br /&gt;
*bei einzelnen Updates die Funktion &amp;lt;code&amp;gt;[[DevelopmentModuleAPI#readingsSingleUpdate|readingsSingleUpdate()]]&amp;lt;/code&amp;gt; &lt;br /&gt;
aufgerufen werden. Dabei kann man auch angeben, ob dabei ein Event ausgelöst werden soll oder nicht. Events erzeugen, je nach Hardwareperformance, spürbare Last auf dem System (siehe [[DevelopmentModuleIntro#X_Notify|NotifyFn]]), das Ändern von Readings ohne dass dabei Events erzeugt werden jedoch nicht.&lt;br /&gt;
&lt;br /&gt;
Eine Sequenz zum Setzen von Readings könnte folgendermaßen aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
readingsBeginUpdate($hash);&lt;br /&gt;
readingsBulkUpdate($hash, $readingName1, $wert1 );&lt;br /&gt;
readingsBulkUpdate($hash, $readingName2, $wert2 );&lt;br /&gt;
readingsEndUpdate($hash, 1);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Attribute ==&lt;br /&gt;
Damit der Nutzer das Verhalten einer einzelnen Gerätedefinition zur Laufzeit individuell anpassen kann, gibt es in FHEM für jede Definition sogenannte Attribute, welche mit dem Befehl &amp;lt;code&amp;gt;attr&amp;lt;/code&amp;gt; gesetzt werden können.&lt;br /&gt;
Diese stehen dann dem Modul unmittelbar zur Verfügung um das Verhalten während der Ausführung zu beeinflussen. Attribute werden zusammen mit dem &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt;-Befehl der jeweiligen Definition beim Speichern der aktuellen Konfiguration von FHEM in die Konfigurationsdatei geschrieben. Beim Neustart werden die entsprechenden Befehle ausgeführt um alle Definition inkl. Attribute wieder anzulegen. Zur Laufzeit werden Attribute in dem globalen Hash &amp;lt;code&amp;gt;%attr&amp;lt;/code&amp;gt; mit dem Definitionsnamen als Index (&amp;lt;code&amp;gt;$attr{$name} = $value&amp;lt;/code&amp;gt;) gespeichert. Ein Attribut mit dem Namen &amp;lt;code&amp;gt;header&amp;lt;/code&amp;gt; würde beispielsweise mit &amp;lt;code&amp;gt;$attr{$name}{header}&amp;lt;/code&amp;gt; adressiert. Generell sollte &amp;lt;code&amp;gt;%attr&amp;lt;/code&amp;gt; nicht durch direkten Zugriff manipuliert/benutzt werden.&lt;br /&gt;
&lt;br /&gt;
Zum Auslesen von Attributen sollte die Funktion [[DevelopmentModuleAPI#AttrVal|AttrVal()]] verwendet werden.&lt;br /&gt;
&lt;br /&gt;
Welche Attribute ein Modul unterstützt muss in der Funktion &amp;lt;code&amp;gt;[[#X_Initialize|X_Initialize]]&amp;lt;/code&amp;gt; durch Setzen von &amp;lt;code&amp;gt;$hash-&amp;gt;{AttrList}&amp;lt;/code&amp;gt; bekannt gemacht werden (siehe unten).&lt;br /&gt;
&lt;br /&gt;
Wenn beim Setzen von Attributen in einer Gerätedefinition entsprechende Werte geprüft werden sollen oder zusätzliche Funktionalitäten implementiert werden müssen, dann muss dies in der Funktion &amp;lt;code&amp;gt;[[#X_Attr|X_Attr]]&amp;lt;/code&amp;gt; (siehe unten) implementiert werden. Hier kann man bspw. einen Syntaxcheck für Attribut-Werte implementieren um ungültige Werte zurückzuweisen.&lt;br /&gt;
&lt;br /&gt;
== Modulfunktionen ==&lt;br /&gt;
&lt;br /&gt;
Damit fhem.pl ein Modul nutzen kann, muss dieses entsprechende Funktionen mit einer vorgegebenen Aufrufsyntax implementieren. Durch die Bekanntgabe dieser modulspezifischen Funktionen können Daten zwischen fhem.pl und einem Modul entsprechend ausgetauscht werden. Es gibt verschiedene Arten von Funktionen die ein Modul anbieten muss bzw. kann, je nach Funktionsumfang.&lt;br /&gt;
&lt;br /&gt;
=== Die wichtigsten Funktionen in einem Modul ===&lt;br /&gt;
&lt;br /&gt;
Folgende Funktion muss ein Modul mit dem beispielhaften Namen &amp;quot;X&amp;quot; mindestens bereitstellen:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;text-align:left&amp;quot; | Funktionsname !! style=&amp;quot;text-align:left&amp;quot; | Kurzbeschreibung&lt;br /&gt;
|-&lt;br /&gt;
|  [[#X_Initialize|X_Initialize]] || Initialisiert das Modul und gibt den Namen zusätzlicher Modulfunktionen bekannt, sowie modulspezifische Einstellungen. Wird direkt nach dem erfolgreichen Laden des Moduls durch fhem.pl aufgerufen.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Die folgenden Funktionen sind die wichtigsten Funktionen, welche je nach Anwendungsfall zu implementieren sind. Es handelt sich hierbei um die wichtigsten Vertreter, welche in den meisten Modulen Verwendung finden. Nicht alle Funktionen machen jedoch in jedem Modul Sinn. Generell sollte auch hier bei jeder Funktion der Modulname vorangestellt werden um ein einheitliches Namensschema zu gewährleisten. Hier die wichtigsten Modulfunktionen:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;text-align:left&amp;quot; | Funktionsname !! style=&amp;quot;text-align:left&amp;quot; class=&amp;quot;unsortable&amp;quot;| Kurzbeschreibung&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Define|X_Define]] || Wird im Rahmen des &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt;-Befehls aufgerufen.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Undef|X_Undef]] || Wird im Rahmen des &amp;lt;code&amp;gt;delete&amp;lt;/code&amp;gt;-Befehls, sowie &amp;lt;code&amp;gt;rereadcfg&amp;lt;/code&amp;gt;-Befehl aufgerufen. Dient zum Abbau von offenen Verbindungen, Timern, etc.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Delete|X_Delete]] || Wird im Rahmen des beim &amp;lt;code&amp;gt;delete&amp;lt;/code&amp;gt;-Befehls aufgerufen wenn das Gerät endgültig gelöscht wird um weiterführende Aktionen vor dem Löschen durchzuführen.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Get|X_Get]] || Wird im Rahmen des &amp;lt;code&amp;gt;get&amp;lt;/code&amp;gt;-Befehls aufgerufen um Daten vom Gerät abzufragen&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Set|X_Set]]  || Wird im Rahmen des &amp;lt;code&amp;gt;set&amp;lt;/code&amp;gt;-Befehls aufgerufen um Daten an das Gerät zu senden.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Attr|X_Attr]]  || Wird im Rahmen des &amp;lt;code&amp;gt;attr&amp;lt;/code&amp;gt;-Befehls aufgerufen um Attributwerte zu prüfen)&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Read|X_Read]]  || Wird durch FHEM aufgerufen, wenn ein gelisteter Filedeskriptor in &amp;lt;code&amp;gt;[[#Wichtige_globale_Variablen_aus_fhem.pl|%selectlist]]&amp;lt;/code&amp;gt; Daten zum Lesen bereitstellt.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Ready|X_Ready]]  || Wird unter Windows durch FHEM aufgerufen um zyklisch einen seriellen Filedeskriptor auf lesbare Daten zu prüfen. Unter Linux dient diese Funktion dem Wiederaufbau verlorener Verbindungen.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Notify|X_Notify]]  || Verarbeitet Events von anderen Geräten innerhalb von FHEM&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Rename|X_Rename]] || Wird aufgerufen, wenn ein Gerät umbenannt wird.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Shutdown|X_Shutdown]] || Wird beim Herunterfahren von FHEM ausgeführt.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Diese Funktionen werden in diesem Abschnitt genauer beschrieben.&lt;br /&gt;
&lt;br /&gt;
==== X_Initialize ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Initialize($)&lt;br /&gt;
{&lt;br /&gt;
	my ($hash) = @_;&lt;br /&gt;
	...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das &amp;lt;code&amp;gt;X&amp;lt;/code&amp;gt; im Namen muss dabei auf den Namen des Moduls bzw. des definierten Gerätetyps geändert werden. Im Modul mit der Datei &amp;lt;code&amp;gt;36_JeeLink.pm&amp;lt;/code&amp;gt; beispielsweise ist der Name der Funktion &amp;lt;code&amp;gt;JeeLink_Initialize&amp;lt;/code&amp;gt;. Die Funktion wird von fhem.pl nach dem Laden des Moduls aufgerufen und bekommt eine leere Hashreferenz für den Initialisierungsvorgang übergeben. &lt;br /&gt;
&lt;br /&gt;
Dieser Hash muss nun von X_Initialize mit allen modulrelevanten Funktionsnamen gefüllt werden. Anschließend wird dieser Hash durch fhem.pl im globalen Hash &amp;lt;code&amp;gt;%modules&amp;lt;/code&amp;gt; gespeichert. &amp;lt;code&amp;gt;$modules{ModulName}&amp;lt;/code&amp;gt; wäre dabei der Hash für das Modul mit dem Namen &amp;lt;code&amp;gt;ModulName&amp;lt;/code&amp;gt;. Es handelt sich also nicht um den oben beschriebenen Hash der Geräteinstanzen sondern einen Hash, der für jedes Modul existiert und modulspezifische Daten wie bspw. die implementierten Modulfunktionen enthält. Die Initialize-Funktion setzt diese Funktionsnamen, in den Hash des Moduls wie folgt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
$hash-&amp;gt;{DefFn}         = &amp;quot;X_Define&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{UndefFn}       = &amp;quot;X_Undef&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{DeleteFn}      = &amp;quot;X_Delete&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{SetFn}         = &amp;quot;X_Set&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{GetFn}         = &amp;quot;X_Get&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{AttrFn}        = &amp;quot;X_Attr&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{ReadFn}        = &amp;quot;X_Read&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{ReadyFn}       = &amp;quot;X_Ready&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{NotifyFn}      = &amp;quot;X_Notify&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{RenameFn}      = &amp;quot;X_Rename&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{ShutdownFn}    = &amp;quot;X_Shutdown&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Um eine entsprechende Funktion in FHEM bekannt zu machen muss dazu der Funktionsname, wie er im Modul als &amp;lt;code&amp;gt;sub &amp;amp;lt;&#039;&#039;Funktionsname&#039;&#039;&amp;amp;gt;() { ... }&amp;lt;/code&amp;gt; definiert ist, als Zeichenkette in &amp;lt;code&amp;gt;$hash&amp;lt;/code&amp;gt; gesetzt werden. Dabei sollten die entsprechenden Funktionsnamen immer den Modulnamen (in diesem Beispiel &amp;lt;code&amp;gt;X&amp;lt;/code&amp;gt;) als Präfix verwenden.&lt;br /&gt;
Auf diese Weise können sämtliche modulspezifisch implementierten Funktionen wie &amp;lt;code&amp;gt;X_Read&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;X_Parse&amp;lt;/code&amp;gt; etc. durch Zuweisung an &amp;lt;code&amp;gt;$hash-&amp;gt;{ReadFn}&amp;lt;/code&amp;gt; bzw. &amp;lt;code&amp;gt;$hash-&amp;gt;{ParseFn}&amp;lt;/code&amp;gt; usw. bekannt gemacht werden.&lt;br /&gt;
&lt;br /&gt;
Darüber hinaus sollten die vom Modul unterstützten Attribute definiert werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
$hash-&amp;gt;{AttrList} =&lt;br /&gt;
  &amp;quot;do_not_notify:1,0 &amp;quot; . &lt;br /&gt;
  &amp;quot;header &amp;quot; .&lt;br /&gt;
  $readingFnAttributes;  &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Auflistung aller unterstützten modulspezifischen Attribute erfolgt in Form einer durch Leerzeichen getrennten Liste in &amp;lt;code&amp;gt;$hash-&amp;gt;{AttrList}}&amp;lt;/code&amp;gt;. Es gibt in FHEM globale Attribute, die in allen Gerätedefinitionen verfügbar sind und nur modulspezifische Attribute die jedes Modul via &amp;lt;code&amp;gt;$hash-&amp;gt;{AttrList}&amp;lt;/code&amp;gt; über die eigene Initialize-Funktion setzt.  In fhem.pl werden dann die entsprechenden Attributwerte beim Aufruf eines &amp;lt;code&amp;gt;attr&amp;lt;/code&amp;gt;-Befehls in die globale Datenstruktur &amp;lt;code&amp;gt;$attr{$name}&amp;lt;/code&amp;gt;, z.B. &amp;lt;code&amp;gt;$attr{$name}{header}&amp;lt;/code&amp;gt; für das Attribut &amp;lt;code&amp;gt;header&amp;lt;/code&amp;gt; gespeichert. Falls im Modul weitere Aktionen oder Prüfungen beim Setzen eines Attributs nötig sind, dann kann wie im Beispiel oben die [[#X_Attr|Attr]]-Funktion implementiert und in der Initialize-Funktion bekannt gemacht werden.&lt;br /&gt;
&lt;br /&gt;
Die Variable &amp;lt;code&amp;gt;$readingFnAttributes&amp;lt;/code&amp;gt;, die im obigen Beispiel an die Liste der unterstützten Attribute angefügt wird, definiert Attributnamen, die dann zusätzlich gemacht werden, wenn das Modul zum Setzen von Readings die Funktionen &amp;lt;code&amp;gt;[[DevelopmentModuleAPI#readingsBeginUpdate|readingsBeginUpdate()]]&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;[[DevelopmentModuleAPI#readingsBulkUpdate|readingsBulkUpdate()]]&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;[[DevelopmentModuleAPI#readingsEndUpdate|readingsEndUpdate()]]&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;[[DevelopmentModuleAPI#readingsSingleUpdate|readingsSingleUpdate()]]&amp;lt;/code&amp;gt; verwendet. In diesen Funktionen werden Attribute wie &amp;lt;code&amp;gt;event-min-interval&amp;lt;/code&amp;gt; oder auch &amp;lt;code&amp;gt;event-on-change-reading&amp;lt;/code&amp;gt; ausgewertet. Für Details hierzu siehe commandref zu [http://fhem.de/commandref.html#readingFnAttributes readingFnAttributes].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Nutzung von parseParams()&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Funktion &amp;lt;code&amp;gt; [[DevelopmentModuleAPI#parseParams|parseParams()]]&amp;lt;/code&amp;gt; unterstützt Modulautoren beim Parsen von Übergabeparametern, welche bei &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;get&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;set&amp;lt;/code&amp;gt; Kommandos an die entsprechenden Modulfunktionen übergeben werden. Dadurch lassen sich auf einfache Weise insbesondere komplexe Parameter (wie bspw. Perl-Ausdrücke) sehr einfach parsen.&lt;br /&gt;
&lt;br /&gt;
Diese Zusatzfunktion kann man in der Initialize-Funktion einfach über folgenden Parameter für [[#X_Define|Define]]-, [[#X_Get|Get]]- und [[#X_Set|Set]]-Funktion modulweit aktivieren:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;$hash-&amp;gt;{parseParams} = 1;&amp;lt;/source&amp;gt;&lt;br /&gt;
Sobald es gesetzt ist wird automatisch durch fhem.pl &amp;lt;code&amp;gt;[[DevelopmentModuleAPI#parseParams|parseParams()]]&amp;lt;/code&amp;gt; aufgerufen und die an die [[#X_Define|Define]]-, [[#X_Get|Get]]- und [[#X_Set|Set]]-Funktion übergebenen Parameter ändern sich wie weiter unten in den jeweiligen Funktionen beschrieben.&lt;br /&gt;
&lt;br /&gt;
==== X_Define ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Define($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $def ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
 &lt;br /&gt;
	return $error;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Define-Funktion eines Moduls wird von FHEM aufgerufen wenn der Define-Befehl für ein Geräte ausgeführt wird und das Modul bereits geladen und mit der Initialize-Funktion initialisiert ist. Sie ist typischerweise dazu da, die übergebenen Parameter zu prüfen und an geeigneter Stelle zu speichern sowie einen Kommunikationsweg zum Gerät zu öffnen (z.B. TCP-Verbindung, USB-Schnittstelle o.ä.) oder einen [[#Pollen_von_Geräten|Status-Timer]] zu starten.&lt;br /&gt;
Sie beginnt typischerweise mit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Define($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $def ) = @_;&lt;br /&gt;
	my @a = split( &amp;quot;[ \t][ \t]*&amp;quot;, $def );&lt;br /&gt;
	...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Als Übergabeparameter bekommt die Define-Funktion den Hash der Geräteinstanz sowie den die im &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt;-Befehl übergebenen Parameter. Welche bzw. wie viele Parameter &lt;br /&gt;
akzeptiert werden und welcher Syntax diese entsprechen müssen ist Sache dieser Funktion. Im obigen Beispiel wird die Argumentzeile &amp;lt;code&amp;gt;$def&amp;lt;/code&amp;gt; in ein Array aufgeteilt (durch Leerzeichen/Tabulator getrennt) und so können die vom Modul bzw. der Define-Funktion erwarteten Werte über das Array der Reihe nach verarbeitet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
my $name   = $a[0];&lt;br /&gt;
my $module = $a[1];&lt;br /&gt;
my $url    = $a[2];&lt;br /&gt;
my $inter  = 300;&lt;br /&gt;
&lt;br /&gt;
if(int(@a) == 4) { &lt;br /&gt;
	$inter = $a[3]; &lt;br /&gt;
	if ($inter &amp;lt; 5) {&lt;br /&gt;
		return &amp;quot;interval too small, please use something &amp;gt; 5s, default is 300 seconds&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Damit die übergebenen Werte auch anderen Funktionen zur Verfügung stehen und an die jeweilige Geräteinstanz gebunden sind, werden die Werte typischerweise als Internals im Hash der Geräteinstanz gespeichert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
$hash-&amp;gt;{url} 		= $url;&lt;br /&gt;
$hash-&amp;gt;{Interval}	= $inter;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sobald alle Parameter korrekt verarbeitet wurden, wird in der Regel die erste Verbindung zum Gerät aufgebaut. Je nach Art des Geräts kann das eine permanente Datenverbindung sein (z.B. serielle Schnittstelle oder TCP-Verbindung) oder das Starten eines regelmäßigen Timers, der zyklisch den Status z.B. via [[HttpUtils|HTTP]] ausliest.&lt;br /&gt;
&lt;br /&gt;
Sollten im Rahmen der Define-Funktion Syntax-Probleme der Übergabeparameter festgestellt werden oder es kann bspw. keine Verbindung aufgebaut werden, so ist als Funktionsrückgabewert eine entsprechende Fehlermeldung zurückzugeben. Nur wenn alle Übergabeparameter akzeptiert werden, darf &amp;lt;code&amp;gt;undef&amp;lt;/code&amp;gt; zurückgegeben werden. Sobald eine Define-Funktion eine Fehlermeldung zurückmeldet, wird der define-Befehl durch FHEM zurückgewiesen und der User erhält die Fehlermeldung, welche die Define-Funktion produziert hat, als Ausgabe zurück.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Verfügbarkeit von Attributen&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Während die Define-Funktion ausgeführt wird, sollte man nicht davon ausgehen, dass alle vom Nutzer konfigurierten Attribute via [[DevelopmentModuleAPI#AttrVal|AttrVal()]] verfügbar sind. Attribute stehen in der Define-Funktion nur dann zur Verfügung, wenn FHEM sich nicht in der Initialisierungsphase befindet (globale Variable &amp;lt;code&amp;gt;$init_done&amp;lt;/code&amp;gt; ist wahr; der Nutzer hat die Gerätedefinition modifiziert). Daher sollte man weiterführende Funktion, welche auf gesetzte Attribute angewiesen sind, nur dann in der Define-Funktion starten, wenn &amp;lt;code&amp;gt;$init_done&amp;lt;/code&amp;gt; zutrifft.&lt;br /&gt;
&lt;br /&gt;
Andernfalls sollte man den Aufruf in der Notify-Funktion durchführen sobald &amp;lt;code&amp;gt;global:INITIALIZED&amp;lt;/code&amp;gt; bzw. &amp;lt;code&amp;gt;global:REREADCFG&amp;lt;/code&amp;gt; getriggert wurde:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Define($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $def ) = @_;&lt;br /&gt;
 &lt;br /&gt;
	...&lt;br /&gt;
&lt;br /&gt;
	$hash-&amp;gt;{NOTIFYDEV} = &amp;quot;global&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	X_FunctionWhoNeedsAttr($hash) if($init_done);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub X_Notify($$)&lt;br /&gt;
{&lt;br /&gt;
	my ($own_hash, $dev_hash) = @_;&lt;br /&gt;
	my $ownName = $own_hash-&amp;gt;{NAME}; # own name / hash&lt;br /&gt;
 &lt;br /&gt;
	return &amp;quot;&amp;quot; if(IsDisabled($ownName)); # Return without any further action if the module is disabled&lt;br /&gt;
 &lt;br /&gt;
	my $devName = $dev_hash-&amp;gt;{NAME}; # Device that created the events&lt;br /&gt;
	my $events = deviceEvents($dev_hash, 1);&lt;br /&gt;
&lt;br /&gt;
	if($devName eq &amp;quot;global&amp;quot; &amp;amp;&amp;amp; grep(m/^INITIALIZED|REREADCFG$/, @{$events}))&lt;br /&gt;
	{&lt;br /&gt;
		 X_FunctionWhoNeedsAttr($hash);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dadurch wird die Modulfunktion X_FunctionWhoNeedsAttr() nach dem Start erst aufgerufen, wenn alle Attribute aus der Konfiguration geladen wurden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Nutzung von parseParams()&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zum Aufteilen und Parsen von &amp;lt;code&amp;gt;$def&amp;lt;/code&amp;gt; lässt sich die Funktion [[DevelopmentModuleAPI#parseParams|parseParams]] verwenden um die einzelnen Argumente einfach zu parsen. Wenn in X_Initialize &amp;lt;code&amp;gt;$hash-&amp;gt;{parseParams} = 1;&amp;lt;/code&amp;gt; gesetzt wurde dann wird parseParams automatisch aufgerufen und X_Define ändert sich wie folgt:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Define($$$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $a, $h ) = @_;&lt;br /&gt;
	...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die genauen Möglichkeiten von parseParams sind in dem entsprechenden [[DevelopmentModuleAPI#parseParams|Artikel]] dokumentiert.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Nutzung von DevIo&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn eine physische Schnittstelle geöffnet werden soll und dann bei verfügbaren Eingabedaten eine Lese-Funktion von FHEM aufgerufen werden soll, dann kann man in der Define-Funktion die Funktion DevIo_OpenDev aufrufen, die sich um alles weitere kümmert. Sie öffnet die Schnittstelle und fügt den Filedeskriptor an die globale Liste offener Verbindungen (selectlist / readyfnlist) an. Damit kann FHEM in seiner Hauptschleife erkennen, von welchem Gerät Daten bereit stehen und die zuständigen Funktionen aufrufen.&lt;br /&gt;
&lt;br /&gt;
Um DevIo mitzuteilen welche Verbindung genau zu öffnen ist, muss das Internal &amp;lt;code&amp;gt;$hash-&amp;gt;{DeviceName} mit einer entsprechenden Syntax gefüllt sein (z.B. &amp;lt;code&amp;gt;&amp;quot;/dev/ttyUSB0@9600&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;192.168.2.105:3000&amp;quot;&amp;lt;/code&amp;gt;, ...). Üblicherweise wird diese Information als Argument im &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt;-Befehl vom Nutzer angegeben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
my $ret = DevIo_OpenDev( $hash, 0, &amp;quot;X_DeviceInit&amp;quot; );&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die optionale Funktion &amp;lt;code&amp;gt;X_DevInit&amp;lt;/code&amp;gt; wird zur weiteren Initialisierung der Verbindung von &amp;lt;code&amp;gt;DevIo_OpenDev&amp;lt;/code&amp;gt; aufgerufen. Der zweite Übergabeparameter an &amp;lt;code&amp;gt;DevIo_OpenDev&amp;lt;/code&amp;gt; (hier &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;) steht für reopen und wird benötigt, da die Funktion auch aufgerufen wird, wenn ein USB-Geräte beispielsweise im Betrieb aus- und wieder eingesteckt wird. In diesem Fall wird die Funktion mit &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; aufgerufen. Dies ist jedoch nur in der [[#X_Ready|X_Ready]]-Funktion notwendig. In der Define-Funktion wird immer &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; (erster Verbindungsversuch) angegen&lt;br /&gt;
&lt;br /&gt;
==== X_Undef ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Undef ($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $name ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
 &lt;br /&gt;
	return $error;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Die Undef-Funktion wird aufgerufen wenn ein Gerät mit &amp;lt;code&amp;gt;delete&amp;lt;/code&amp;gt; gelöscht wird oder bei der Abarbeitung des Befehls &amp;lt;code&amp;gt;rereadcfg&amp;lt;/code&amp;gt;, der ebenfalls alle Geräte löscht und danach das Konfigurationsfile neu einliest. Entsprechend müssen in der Funktion typische Aufräumarbeiten durchgeführt werden wie das saubere Schließen von Verbindungen oder das Entfernen von internen Timern, sofern diese im Modul zum Pollen verwendet wurden (siehe Abschnitt [[#Pollen_von_Geräten|Pollen von Geräten]]). &lt;br /&gt;
&lt;br /&gt;
Zugewiesene Variablen im Hash der Geräteinstanz, Internals oder Readings müssen hier nicht gelöscht werden. In fhem.pl werden die entsprechenden Strukturen beim Löschen der Geräteinstanz ohnehin vollständig gelöscht.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Undef($$)    &lt;br /&gt;
{                     &lt;br /&gt;
	my ( $hash, $name) = @_;       &lt;br /&gt;
	DevIo_CloseDev($hash);         &lt;br /&gt;
	RemoveInternalTimer($hash);    &lt;br /&gt;
	return undef;                  &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sollten im Rahmen der Undef-Funktion Probleme festgestellt werden, die ein Löschen nicht zulassen, so ist als Funktionsrückgabewert eine entsprechende Fehlermeldung zurückzugeben. Nur wenn die Undef-Funktion erfolgreich durchgeführt wurde, darf &amp;lt;code&amp;gt;undef&amp;lt;/code&amp;gt; zurückgegeben werden. Nur dann wird eine Gerätedefinition von FHEM auch tatsächlich gelöscht bzw. neu angelegt. Sollte die Undef-Funktion jedoch eine Fehlermeldung zurückgeben, wird der entsprechende Vorgang (&amp;lt;code&amp;gt;delete&amp;lt;/code&amp;gt; bzw. &amp;lt;code&amp;gt;rereadcfg&amp;lt;/code&amp;gt;) für dieses Gerät abgebrochen. Es bleibt dann unverändert in FHEM bestehen.&lt;br /&gt;
&lt;br /&gt;
==== X_Delete ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Delete ($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $name ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
 &lt;br /&gt;
	return $error;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Delete-Funktion ist das Gegenstück zur Funktion [[#X_Define|X_Define]] und wird aufgerufen wenn ein Gerät mit dem Befehl &amp;lt;code&amp;gt;delete&amp;lt;/code&amp;gt; gelöscht wird. &lt;br /&gt;
&lt;br /&gt;
Wenn ein Gerät in FHEM gelöscht wird, wird zuerst die Funktion [[#X_Undef|X_Undef]] aufgerufen um offene Verbindungen zu schließen, anschließend wird die Funktion X_Delete aufgerufen. Diese dient eher zum Aufräumen von dauerhaften Daten, welche durch das Modul evtl. für dieses Gerät spezifisch erstellt worden sind. Es geht hier also eher darum, alle Spuren sowohl im laufenden FHEM-Prozess, als auch dauerhafte Daten bspw. im physikalischen Gerät zu löschen die mit dieser Gerätedefinition zu tun haben.&lt;br /&gt;
&lt;br /&gt;
Dies kann z.B. folgendes sein:&lt;br /&gt;
&lt;br /&gt;
* Löschen von Dateien im Dateisystem die während der Nutzung dieses Geräts angelegt worden sind.&lt;br /&gt;
* Lösen von evtl. Pairings mit dem physikalischen Gerät &lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Delete($$)    &lt;br /&gt;
{                     &lt;br /&gt;
	my ( $hash, $name ) = @_;       &lt;br /&gt;
&lt;br /&gt;
	# Löschen von Geräte-assoziiertem Temp-File&lt;br /&gt;
	unlink($attr{global}{modpath}.&amp;quot;/FHEM/FhemUtils/$name.tmp&amp;quot;;)&lt;br /&gt;
&lt;br /&gt;
	return undef;&lt;br /&gt;
}    &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sollten im Rahmen der Delete-Funktion Probleme festgestellt werden, die ein Löschen nicht zulassen, so ist als Funktionsrückgabewert eine entsprechende Fehlermeldung zurückzugeben. Nur die Delete-Funktion erfolgreich durchgeführt wurde, darf &amp;lt;code&amp;gt;undef&amp;lt;/code&amp;gt; zurückgegeben werden. Nur dann wird eine Gerätedefinition von FHEM auch tatsächlich gelöscht. Sollte die Delete-Funktion eine Fehlermeldung zurückgeben, wird der Löschvorgang abgebrochen und das Gerät bleibt weiter in FHEM bestehen.&lt;br /&gt;
&lt;br /&gt;
==== X_Get ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Get ($$@)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $name, $opt, @args ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
 &lt;br /&gt;
	return $result;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Die Get-Funktion wird aufgerufen wenn der FHEM-Befehl &amp;lt;code&amp;gt;get&amp;lt;/code&amp;gt; mit einem Gerät dieses Moduls ausgeführt wird. Mit &amp;lt;code&amp;gt;get&amp;lt;/code&amp;gt; werden typischerweise Werte von einem Gerät abgefragt. In vielen Modulen wird auf diese Weise auch der Zugriff auf generierte Readings ermöglicht. Der Get-Funktion wird dabei der Geräte-Hash, der Gerätename, sowie die Aufrufparameter des get-Befehls übergeben. Als Rückgabewert wird das Ergebnis des entsprechenden Befehls in Form einer Zeichenkette zurückgegeben. Der Rückgabewert &amp;lt;code&amp;gt;undef&amp;lt;/code&amp;gt; hat hierbei keine besondere Bedeutung und wird behandelt wie eine leere Zeichenkette &amp;lt;code&amp;gt;&amp;quot;&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Get($$@)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $name, $opt, @args ) = @_;&lt;br /&gt;
&lt;br /&gt;
	return &amp;quot;\&amp;quot;get $name\&amp;quot; needs at least one argument&amp;quot; unless(defined($opt)));&lt;br /&gt;
&lt;br /&gt;
	if($opt eq &amp;quot;status&amp;quot;) &lt;br /&gt;
	{&lt;br /&gt;
	   ...&lt;br /&gt;
	}&lt;br /&gt;
	elsif($opt eq &amp;quot;powser&amp;quot;)&lt;br /&gt;
	{&lt;br /&gt;
	   ...&lt;br /&gt;
	}&lt;br /&gt;
	...&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		return &amp;quot;Unknown argument $opt, choose one of status power [...]&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn eine unbekannte Option an die Get-Funktion übergeben wird, so muss als Rückgabewert der Funktion eine bestimmte Syntax einhalten um FHEM mitzuteilen, welche Optionen für einen Get-Befehl aktuell unterstützt werden. Die Rückgabe muss dabei folgender Syntax entsprechen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&#039;&#039;&#039;unknown&#039;&#039;&#039; argument &#039;&#039;&amp;lt;font color=&amp;quot;grey&amp;quot;&amp;gt;[Parameter]&amp;lt;/font&amp;gt;&#039;&#039; &#039;&#039;&#039;choose one of&#039;&#039;&#039; &#039;&#039;&amp;lt;font color=&amp;quot;grey&amp;quot;&amp;gt;[Liste möglicher Optionen]&amp;lt;/font&amp;gt;&#039;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hierbei sind die fett gedruckten Teile der Rückmeldung besonders wichtig. Sind diese nicht vorhanden, kann FHEM nicht die möglichen Get-Kommandos für das entsprechende Gerät ermitteln. Es muss am Anfang der Meldung das Stichwort &amp;quot;unknown&amp;quot; vorkommen gefolgt von einer frei definierbaren Fehlermeldung (i.d.R der übergebene Parameter, welcher ungültig ist). Anschließend folgt &amp;quot;choose one of&amp;quot; mit einer anschließenden Liste möglicher Optionen getrennt durch ein Leerzeichen. &lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;return &amp;quot;unknown argument $opt choose one of state temperature humidity&amp;quot;;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hier werden als mögliche Optionen für einen Get-Befehl folgende Parameter angegeben:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;temperature&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;humidity&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dies würde in folgenden, mögliche Get-Befehle für einen User resultieren:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;get &#039;&#039;&amp;amp;lt;NAME&amp;amp;gt;&#039;&#039; state&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;get &#039;&#039;&amp;amp;lt;NAME&amp;amp;gt;&#039;&#039; temperature&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;get &#039;&#039;&amp;amp;lt;NAME&amp;amp;gt;&#039;&#039; humidity&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Ausgabe einer solchen Meldung ist sehr wichtig, da sie im GUI-Modul verwendet wird um die möglichen &amp;lt;code&amp;gt;get&amp;lt;/code&amp;gt;-Optionen zu ermitteln und als Auswahl anzubieten. Im weiteren Verlauf der Get-Funktion könnte man dann mit dem physischen Gerät kommunizieren und den gefragten Wert direkt abfragen und diesen als Return-Wert der Get-Funktion zurückgeben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Nutzung von parseParams()&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn in [[#X_Initialize|X_Initialize]] &amp;lt;code&amp;gt;$hash-&amp;gt;{parseParams} = 1;&amp;lt;/code&amp;gt; gesetzt wurde dann wird [[DevelopmentModuleAPI#parseParams|parseParams]] automatisch aufgerufen und X_Get ändert sich wie folgt:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Get($$$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $a, $h ) = @_;&lt;br /&gt;
	...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die genauen Möglichkeiten von parseParams sind in dem entsprechenden [[DevelopmentModuleAPI#parseParams|Artikel]] dokumentiert.&lt;br /&gt;
&lt;br /&gt;
==== X_Set ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Set ($$@)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $name, $cmd, @args ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
 &lt;br /&gt;
	return $error;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Set-Funktion ist das Gegenteil zur [[#X_Get|Get]]-Funktion. Sie ist dafür gedacht, Daten zum physischen Gerät zu schicken, bzw. entsprechende Aktionen im Gerät selber auszulösen. Ein Set-Befehl dient daher der direkten Steuerung des physikalischen Gerätes in dem es bspw. Zustände verändert (wie &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;off&amp;lt;/code&amp;gt;). Der Set-Funktion wird dabei der Geräte-Hash, der Gerätename, sowie die Aufrufparameter des set-Befehls übergeben. Als Rückgabewert kann eine Fehlermeldung in Form Zeichenkette zurückgegeben werden. Der Rückgabewert &amp;lt;code&amp;gt;undef&amp;lt;/code&amp;gt; bedeutet hierbei, dass der Set-Befehl erfolgreich durchgeführt wurde. Eine Set-Funktion gibt daher nur im Fehlerfall eine Rückmeldung mit einer entsprechenden Fehlermeldung. Der Wert &amp;lt;code&amp;gt;undef&amp;lt;/code&amp;gt; wird als &amp;quot;erfolgreich&amp;quot; interpretiert. Rückmeldungen von set-Befehlen sämtlicher Module, die im Rahmen eines ausgeführten [[Notify]] auftreten werden im FHEM Logfile festgehalten.&lt;br /&gt;
&lt;br /&gt;
Falls nur interne Daten, die ausschließlich für das Modul relevant sind, gesetzt werden müssen, so sollte statt Set die [[#X_Attr|Attr]]-Funktion verwendet werden. Attribute werden bei Save-Config auch in der Fhem.cfg gesichert. Set-Befehle nicht, da sie nur zur Steuerungszwecken im laufenden Betrieb von FHEM dienen.&lt;br /&gt;
 &lt;br /&gt;
Eine Set-Funktion ist ähnlich aufgebaut wie die Get-Funktion, sie bekommt jedoch in der Regel weitere zusätzliche Parameter übergeben um Zustände zu setzen. &lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Set($@)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $name, $cmd, @args ) = @_;&lt;br /&gt;
&lt;br /&gt;
	return &amp;quot;\&amp;quot;set $name\&amp;quot; needs at least one argument&amp;quot; unless(defined($cmd)));&lt;br /&gt;
&lt;br /&gt;
	if($cmd eq &amp;quot;status&amp;quot;)&lt;br /&gt;
	{&lt;br /&gt;
	   if($args[0] eq &amp;quot;up&amp;quot;)&lt;br /&gt;
	   {&lt;br /&gt;
	      ...&lt;br /&gt;
	   }&lt;br /&gt;
	   elsif($args[0] eq &amp;quot;down&amp;quot;)&lt;br /&gt;
	   {&lt;br /&gt;
	      ...&lt;br /&gt;
	   }&lt;br /&gt;
	   else&lt;br /&gt;
	   {&lt;br /&gt;
	      return &amp;quot;Unknown value $args[0] for $cmd, choose one of status power&amp;quot;;&lt;br /&gt;
	   }   &lt;br /&gt;
	}&lt;br /&gt;
	elsif($cmd eq &amp;quot;power&amp;quot;)&lt;br /&gt;
	{&lt;br /&gt;
	   if($args[0] eq &amp;quot;on&amp;quot;)&lt;br /&gt;
	   {&lt;br /&gt;
	      ...&lt;br /&gt;
	   }&lt;br /&gt;
	   elsif($args[0] eq &amp;quot;off&amp;quot;)&lt;br /&gt;
	   {&lt;br /&gt;
	      ...&lt;br /&gt;
	   }  &lt;br /&gt;
	   else&lt;br /&gt;
	   {&lt;br /&gt;
	      return &amp;quot;Unknown value $args[0] for $cmd, choose one of status power&amp;quot;;&lt;br /&gt;
	   }       &lt;br /&gt;
	}&lt;br /&gt;
	...&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		return &amp;quot;Unknown argument $cmd, choose one of status power&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn eine unbekannte Option an die Set-Funktion übergeben wird, so muss als Rückgabewert der Funktion eine bestimmte Syntax eingehalten werden um FHEM mitzuteilen, welche Optionen für einen Set-Befehl aktuell unterstützt werden. Die Rückgabe muss dabei folgender Syntax entsprechen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&#039;&#039;&#039;unknown&#039;&#039;&#039; argument &#039;&#039;&amp;lt;font color=&amp;quot;grey&amp;quot;&amp;gt;[Parameter]&amp;lt;/font&amp;gt;&#039;&#039; &#039;&#039;&#039;choose one of&#039;&#039;&#039; &#039;&#039;&amp;lt;font color=&amp;quot;grey&amp;quot;&amp;gt;[Liste möglicher Optionen]&amp;lt;/font&amp;gt;&#039;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hierbei sind die fett gedruckten Teile der Rückmeldung besonders wichtig. Sind diese nicht vorhanden, kann FHEM nicht die möglichen Set-Kommandos für das entsprechende Gerät ermitteln. Es muss am Anfang der Meldung das Stichwort &amp;quot;unknown&amp;quot; vorkommen gefolgt von einer frei definierbaren Fehlermeldung (i.d.R der übergebene Parameter, welcher ungültig ist). Anschließend folgt &amp;quot;choose one of&amp;quot; mit einer anschließenden Liste möglicher Optionen getrennt durch ein Leerzeichen. &lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;return &amp;quot;unknown argument $cmd choose one of state power&amp;quot;;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hier werden als mögliche Optionen für einen Get-Befehl folgende Parameter angegeben:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;power&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dies würde in folgenden, mögliche Get-Befehle für einen User resultieren:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;get &#039;&#039;&amp;amp;lt;NAME&amp;amp;gt;&#039;&#039; state&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;get &#039;&#039;&amp;amp;lt;NAME&amp;amp;gt;&#039;&#039; power&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Ausgabe einer solchen Meldung ist sehr wichtig, da sie im GUI-Modul verwendet wird um die möglichen &amp;lt;code&amp;gt;set&amp;lt;/code&amp;gt;-Optionen zu ermitteln und als Auswahl anzubieten&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Nutzung von SetExtensions.pm&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn man dem Nutzer zusätzlich zu den Set-Befehlen &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;off&amp;lt;/code&amp;gt; auch weiterführende Befehle wie &amp;lt;code&amp;gt;on-for-timer&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;on-till&amp;lt;/code&amp;gt;, usw. anbieten möchte, obwohl die zu steuernde Hardware solche Kommandos nicht unterstützt, kann man dies über das Hilfsmodul SetExtensions.pm realisieren.&lt;br /&gt;
&lt;br /&gt;
Das Hilfsmodul SetExtensions.pm bietet weiterführende Set-Kommandos basierend auf den Befehlen &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;off&amp;lt;/code&amp;gt; an. Dabei werden durch interne Timer bzw. eigens angelegten [[at]]-Definitionen diese Befehle durch FHEM selber umgesetzt. Je nach ausgeführtem Befehl wird der &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt;- bzw. &amp;lt;code&amp;gt;off&amp;lt;/code&amp;gt;-Befehl dann durch FHEM zum richtigen Zeitpunkt ausgeführt. Vorausgesetzt das Modul unterstützt in der Set-Funktion die Befehle &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;off&amp;lt;/code&amp;gt;, so werden durch den Einsatz von SetExtensions.pm folgende Befehle zusätzlich unterstützt:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Set-Kommando !! Beispiel !! Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;on-for-timer &#039;&#039;&amp;amp;lt;Dauer&amp;amp;gt;&#039;&#039;&amp;lt;/code&amp;gt;  || style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;on-for-timer 120&amp;lt;/code&amp;gt; || Schaltet das Gerät sofort mit dem &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt;-Befehl ein und nach der angegebenen Dauer in Sekunden via &amp;lt;code&amp;gt;off&amp;lt;/code&amp;gt; wieder aus.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;off-for-timer &#039;&#039;&amp;amp;lt;Dauer&amp;amp;gt;&#039;&#039;&amp;lt;/code&amp;gt;  || style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;off-for-timer 120&amp;lt;/code&amp;gt; || Schaltet das Gerät sofort mit dem &amp;lt;code&amp;gt;off&amp;lt;/code&amp;gt;-Befehl aus und nach der angegebenen Dauer in Sekunden via &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt; wieder ein.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;on-till &#039;&#039;&amp;amp;lt;Zeitpunkt&amp;amp;gt;&#039;&#039;&amp;lt;/code&amp;gt;  || style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;on-till 16:30&amp;lt;/code&amp;gt; || Schaltet das Gerät sofort mit dem &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt;-Befehl ein und zum angegebenen Zeitpunkt via &amp;lt;code&amp;gt;off&amp;lt;/code&amp;gt; wieder aus.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;off-till &#039;&#039;&amp;amp;lt;Zeitpunkt&amp;amp;gt;&#039;&#039;&amp;lt;/code&amp;gt;  || style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;off-till 16:30&amp;lt;/code&amp;gt; || Schaltet das Gerät sofort mit dem &amp;lt;code&amp;gt;off&amp;lt;/code&amp;gt;-Befehl aus und zum angegebenen Zeitpunkt via &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt; wieder ein.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;on-till-overnight &#039;&#039;&amp;amp;lt;Zeitpunkt&amp;amp;gt;&#039;&#039;&amp;lt;/code&amp;gt;  || style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;on-till-overnight 01:00&amp;lt;/code&amp;gt; || Ähnlich wie &amp;lt;code&amp;gt;on-till&amp;lt;/code&amp;gt;. Der übergebene Zeitpunkt wird aber nicht geprüft, ob er für den heutigen Tag bereits überschritten wurde. Dadurch kann man Abends einen Zeitpunkt setzen, der erst am nächsten Tag zutrifft.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;off-till-overnight &#039;&#039;&amp;amp;lt;Zeitpunkt&amp;amp;gt;&#039;&#039;&amp;lt;/code&amp;gt;  || style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;off-till-overnight 01:00&amp;lt;/code&amp;gt; || Ähnlich wie &amp;lt;code&amp;gt;off-till&amp;lt;/code&amp;gt;. Der übergebene Zeitpunkt wird aber nicht geprüft, ob er für den heutigen Tag bereits überschritten wurde. Dadurch kann man Abends einen Zeitpunkt setzen, der erst am nächsten Tag zutrifft.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;blink &#039;&#039;&amp;amp;lt;Anzahl&amp;amp;gt; &amp;amp;lt;Interval&amp;amp;gt;&#039;&#039;&amp;lt;/code&amp;gt;  || style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;blink 3 1&amp;lt;/code&amp;gt; || Schaltet das Gerät via &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt; für &amp;lt;code&amp;gt;&#039;&#039;&amp;amp;lt;Interval&amp;amp;gt;&#039;&#039;&amp;lt;/code&amp;gt; Sekunden ein und anschließend via &amp;lt;code&amp;gt;off&amp;lt;/code&amp;gt; wieder aus. Nach &amp;lt;code&amp;gt;&#039;&#039;&amp;amp;lt;Interval&amp;amp;gt;&#039;&#039;&amp;lt;/code&amp;gt; Sekunden wird das ganze wiederholt, solange bis die angegebene Anzahl erreicht ist.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;intervals &#039;&#039;&amp;amp;lt;Start&amp;amp;gt;-&amp;amp;lt;Ende&amp;amp;gt;&#039;&#039; &#039;&#039;&amp;amp;lt;Start&amp;amp;gt;-&amp;amp;lt;Ende&amp;amp;gt;&#039;&#039; ...&amp;lt;/code&amp;gt; || style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;intervals 07:00-08:00 16:30-18:00&amp;lt;/code&amp;gt; || Schaltet das Gerät innerhalb der übergebenen Zeiträumen via &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt; ein. Sobald die aktuelle Zeit ausserhalb dieser Zeiträume liegt, wird das Gerät via &amp;lt;code&amp;gt;off&amp;lt;/code&amp;gt; wieder ausgeschaltet. Es können dabei beliebig viele Zeiträume angegeben werden.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;toggle&amp;lt;/code&amp;gt; || style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;toggle&amp;lt;/code&amp;gt;  || Sofern der aktuelle Status &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt; ist, wird das Gerät via &amp;lt;code&amp;gt;off&amp;lt;/code&amp;gt; ausgeschaltet. Andernfalls wird es via &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt; eingeschaltet.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Eine kurze Beschreibung zu den möglichen Befehlen durch SetExtensions.pm gibt es auch in der Commandref zum [http://fhem.de/commandref.html#set Set-Befehl].&lt;br /&gt;
&lt;br /&gt;
Um SetExtensions.pm in der Set-Funktion nutzen zu können müssen folgende Aktionen durchgeführt werden:&lt;br /&gt;
&lt;br /&gt;
# Laden von SetExtensions.pm via &amp;lt;code&amp;gt;use SetExtensions;&amp;lt;/code&amp;gt; am Anfang des Moduls&lt;br /&gt;
# Aufruf und Rückgabe der Funktion [[DevelopmentModuleAPI#SetExtensions|SetExtensions()]] sofern die Set-Funktion mit dem übergebenen Befehl nichts anfangen kann.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
use SetExtensions;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
sub X_Set($@)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $name, $cmd, @args ) = @_;&lt;br /&gt;
	my $cmdList = &amp;quot;on off&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	return &amp;quot;\&amp;quot;set $name\&amp;quot; needs at least one argument&amp;quot; unless(defined($cmd)));&lt;br /&gt;
&lt;br /&gt;
	if($cmd eq &amp;quot;on&amp;quot;)&lt;br /&gt;
	{&lt;br /&gt;
		# Gerät einschalten...&lt;br /&gt;
	}&lt;br /&gt;
	elsif($cmd eq &amp;quot;off&amp;quot;)&lt;br /&gt;
	{&lt;br /&gt;
		# Gerät ausschalten...&lt;br /&gt;
	}&lt;br /&gt;
	...&lt;br /&gt;
	else # wenn der übergebene Befehl nicht durch X_Set() verarbeitet werden kann, Weitergabe an SetExtensions()&lt;br /&gt;
	{&lt;br /&gt;
		return SetExtensions($hash, $cmdList, $name, $cmd, @args);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sollte der übergebene Set-Befehl auch für SetExtensions unbekannt sein (bspw. &amp;lt;code&amp;gt;set &#039;&#039;&amp;amp;lt;Name&amp;amp;gt;&#039;&#039; ?&amp;lt;/code&amp;gt;), so generiert SetExtensions() eine entsprechende Usage-Meldung, welche innerhalb der Set-Funktion an FHEM zurückgegeben werden muss.&lt;br /&gt;
&lt;br /&gt;
Eine ausführliche Beschreibung zu der Funktion SetExtensions() gibt es in der  [[DevelopmentModuleAPI#SetExtensions|API-Referenz]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Nutzung von parseParams()&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn in [[#X_Initialize|X_Initialize]] &amp;lt;code&amp;gt;$hash-&amp;gt;{parseParams} = 1;&amp;lt;/code&amp;gt; gesetzt wurde dann wird [[DevelopmentModuleAPI#parseParams|parseParams]] automatisch aufgerufen und X_Set ändert sich wie folgt:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Set($$$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $a, $h ) = @_;&lt;br /&gt;
	...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die genauen Möglichkeiten von parseParams sind in dem entsprechenden [[DevelopmentModuleAPI#parseParams|Artikel]] dokumentiert.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Nutzung von FHEMWEB-Widgets&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das GUI-Modul [[FHEMWEB]] kann für die einzelnen Set-Optionen, die das Modul versteht, automatisch Eingabehilfen wie Drop-Down Boxen oder Slider erzeugen. In der Detailansicht der GUI kann der Anwender dann die jeweiligen Werte komfortabel auswählen. Dafür muss die Set-Funktion, wenn sie mit der Option &amp;lt;code&amp;gt;?&amp;lt;/code&amp;gt; aufgerufen wird, nicht nur einen Text mit  &amp;lt;code&amp;gt;&amp;quot;Unknown ... choose one of ...&amp;quot;&amp;lt;/code&amp;gt; zurückgeben sondern den einzelnen Set-Optionen in diesem Rückgabetext nach einem Doppelpunkt entsprechende Zusatzinformationen anhängen.&lt;br /&gt;
Meist prüft man in den Modulen gar nicht auf die Option &amp;lt;code&amp;gt;?&amp;lt;/code&amp;gt; sondern gibt generell bei unbekannten Optionen diesen Text zurück. Das Modul FHEMWEB ermittelt die Syntax eines Gerätes jedoch immer mit dem Befehl:&lt;br /&gt;
 set &#039;&#039;&amp;amp;lt;NAME&amp;amp;gt;&#039;&#039; ?&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
	return &amp;quot;Unknown argument $cmd, choose one of state:up,down power:on,off on:noArg off:noArg&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit Kommata getrennte Werte ergeben eine Drop-Down Liste, mit der der User die Werte auswählen kann&lt;br /&gt;
&amp;lt;pre&amp;gt;timer:30,120,300&lt;br /&gt;
mode:verbose,ultra,relaxed&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wird kein Doppelpunkt zum Kommando angegeben, so wird eine Eingabezeile angezeigt, die die freie Eingabe eines Wertes erlaubt.&lt;br /&gt;
&lt;br /&gt;
Man kann jedoch die Eingabe-/Auswahlmöglichkeiten durch Widgets vereinfachen. Dazu gibt man hinter dem Doppelpunkt einen Widgetnamen und widgetspezifische Parameter an. Es existieren mehrere solcher Widgets in FHEMWEB. Die gebräuchlichsten sind:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Zusatz !! Beispiel !! Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;noArg&#039;&#039;&#039; || &amp;lt;code&amp;gt;reset:noArg&amp;lt;/code&amp;gt;|| Es werden keine weiteren Argumente mehr benötigt. In so einem Fall wird bei der Auswahl keine Textbox oder ähnliches angezeigt, da keine weiteren Argumente für diesen Befehl notwendig sind.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;slider&#039;&#039;&#039;:&amp;lt;min&amp;gt;,&amp;lt;step&amp;gt;,&amp;lt;max&amp;gt; || &amp;lt;code&amp;gt;dim:slider,0,1,100&amp;lt;/code&amp;gt;|| Es wird ein Schieberegler angezeigt um den Parameter auszuwählen. Dabei werden als Zusatzparameter Minimum, Schrittweite und Maximum angegeben.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;colorpicker&#039;&#039;&#039; || &amp;lt;code&amp;gt;rgb:colorpicker,RGB&amp;lt;/code&amp;gt;|| Es wird ein Colorpicker angezeigt, der dem Anwender die Auswahl einer Farbe ermöglicht. Die genaue Parametersyntax kann man dem Artikel zum  [[Color#Colorpicker|Colorpicker]] entnehmen.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;multiple&#039;&#039;&#039; || &amp;lt;code&amp;gt;group:multiple,Telefon,Multimedia,Licht,Heizung&amp;lt;/code&amp;gt; || Es erscheint ein Auswahldialog, wo man verschiedene Werte durch klicken auswählen kann. Optional kann man in einem Freitext eigene Werte ergänzen. dieser Dialog wird bspw. bei der Raum-Auswahl (Attribut &amp;quot;room&amp;quot;) oder der Gruppen-Auswahl (Attribut &amp;quot;group&amp;quot;) in FHEMWEB genutzt. &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;sortable&#039;&#039;&#039; || &amp;lt;code&amp;gt;command:sortable,monday,tuesday,...&amp;lt;/code&amp;gt; || Es erscheint ein Auswahldialog, wo man verschiedene Werte auswählen und sortieren kann. Man kann dabei Werte durch Klicken auswählen und durch Drag&#039;n&#039;Drop sortieren.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Es gibt noch weitere solcher Widgets. Eine genaue Auflistung dazu findet sich in der [http://fhem.de/commandref.html#widgetOverride commandref] unter widgetOverride zu FHEMWEB.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweise&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Damit in einer Eingabe bereits der aktuelle Wert vorbelegt bzw. in einer Auswahlliste der aktuelle Wert vorselektiert ist, muss es im Modul bzw. Gerät ein Reading mit dem gleichen Namen wie die Set-Option geben. Der Wert des gleichnamigen Readings wird dann als Vorbelegung / Vorselektion verwendet. &lt;br /&gt;
* Der User kann sich in der Raumübersicht nach wie vor via [[WebCmd|webCmd]] eine entsprechende Steuerung anlegen.&lt;br /&gt;
&lt;br /&gt;
==== X_Attr ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Attr ($$$$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $cmd, $name, $attrName, $attrValue  ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
 &lt;br /&gt;
	return $error;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Attr-Funktion dient der Prüfung von Attributen, welche über den &amp;lt;code&amp;gt;attr&amp;lt;/code&amp;gt;-Befehl gesetzt werden können. Sobald versucht wird, ein Attribut für ein Gerät zu setzen, wird vorher die Attr-Funktion des entsprechenden Moduls aufgerufen um zu prüfen, ob das Attribut aus Sicht des Moduls korrekt ist.&lt;br /&gt;
Liegt ein Problem mit dem Attribut bzw. dem Wert vor, so muss die Funktion eine aussagekräftige Fehlermeldung zurückgeben, welche dem User angezeigt wird.&lt;br /&gt;
Sofern das übergebene Attribut samt Inhalt korrekt ist, gibt die Attr-Funktion den Wert &amp;lt;code&amp;gt;undef&amp;lt;/code&amp;gt; zurück. Erst dann wird das Attribut in der globalen Datenstruktur &amp;lt;code&amp;gt;%attr&amp;lt;/code&amp;gt; gespeichert und ist somit erst aktiv.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
X_Attr(@)&lt;br /&gt;
{&lt;br /&gt;
	my ( $cmd, $name, $attrName, $attrValue ) = @_;&lt;br /&gt;
    &lt;br /&gt;
  	# $cmd  - Vorgangsart - kann die Werte &amp;quot;del&amp;quot; (löschen) oder &amp;quot;set&amp;quot; (setzen) annehmen&lt;br /&gt;
	# $name - Gerätename&lt;br /&gt;
	# $attrName/$attrValue sind Attribut-Name und Attribut-Wert&lt;br /&gt;
    &lt;br /&gt;
	if ($cmd eq &amp;quot;set&amp;quot;) {&lt;br /&gt;
		if ($aName eq &amp;quot;Regex&amp;quot;) {&lt;br /&gt;
			eval { qr/$aVal/ };&lt;br /&gt;
			if ($@) {&lt;br /&gt;
				Log3 $name, 3, &amp;quot;X ($name) - Invalid regex in attr $name $aName $aVal: $@&amp;quot;;&lt;br /&gt;
				return &amp;quot;Invalid Regex $aVal: $@&amp;quot;;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	return undef;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zusätzlich ist es möglich auch übergebene Attributwerte zu verändern bzw. zu korrigieren, indem man im Parameterarray &amp;lt;code&amp;gt;@_&amp;lt;/code&amp;gt; den ursprünglichen Wert anpasst. Dies erfolgt im Beispiel über die Modifikation des Wertes mit Index 3 (entspricht dem 4. Element) im Parameterarray, also &amp;lt;code&amp;gt;$_[3]&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Da das Attribut zum Zeitpunkt des Aufrufs der Attr-Funktion noch nicht gespeichert ist, wird der neue Wert zu diesem Zeitpunkt noch nicht via [[DevelopmentModuleAPI#AttrVal|AttrVal()]] zurückgegeben. Erst, wenn die Attr-Funktion mit &amp;lt;code&amp;gt;undef&amp;lt;/code&amp;gt; beendet ist, wird der neue Wert in FHEM gespeichert und steht dann via AttrVal() zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
Die Attr-Funktion bekommt nicht den Hash der Geräteinstanz übergeben, da sie normalerweise keine Werte dort speichern muss, sondern lediglich das Attribut auf Korrektheit prüfen muss.&lt;br /&gt;
Im obigen Beispiel wird für ein Attribut mit Namen &amp;quot;Regex&amp;quot; geprüft ob der reguläre Ausdruck fehlerhaft ist. Sofern dieser OK ist, wird &amp;lt;code&amp;gt;undef&amp;lt;/code&amp;gt; zurückgegeben und fhem.pl speichert den Wert des Attributs in &amp;lt;code&amp;gt;%attr&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Attributnamen mit Platzhaltern&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Falls man Attribute in der [[#X_Initialize|Initialize]]-Funktion mit Platzhaltern definiert (Wildcard-Attribute) wie z.B.:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
    $hash-&amp;gt;{AttrList} =&lt;br /&gt;
      &amp;quot;reading[0-9]*Name &amp;quot; .&lt;br /&gt;
    # usw.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
dann können Anwender Attribute wie reading01Name, reading02Name etc. setzen. Leider funktioniert das bisher nicht durch Klicken in der Web-Oberfläche, da FHEMWEB nicht alle denkbaren Ausprägungen in einem Dropdown anbieten kann. Der Benutzer muss solche Attribute manuell über den &amp;lt;code&amp;gt;attr&amp;lt;/code&amp;gt;-Befehl eingeben.&lt;br /&gt;
&lt;br /&gt;
Man kann jedoch in der Attr-Funktion neu gesetzte Ausprägungen von Wildcard-Attributen an die gerätespezifische userattr-Variable anfügen. Dann können bereits gesetzte Attribute in FHEMWEB durch Klicken ausgewählt und geändert werden.&lt;br /&gt;
Dazu reicht ein Aufruf der Funktion [[DevelopmentModuleAPI#addToDevAttrList|addToDevAttrList()]]: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
    addToDevAttrList($name, $aName);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== X_Read ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Read ($)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Die X_Read-Funktion wird aufgerufen, wenn ein dem Gerät zugeordneter Filedeskriptor (serielle Schnittstelle, TCP-Verbindung, ...) Daten zum Lesen bereitgestellt hat. Die Daten müssen nun eingelesen und interpretiert werden.&lt;br /&gt;
&lt;br /&gt;
Im folgenden Beispiel wird über eine serielle Schnittstelle (beziehungsweise über einen USB-To-Seriell-Konverter) von einem angeschlossenen Gerät gelesen. Dazu werden die bisher verfügbaren Daten mit der Funktion &amp;lt;code&amp;gt;DevIo_SimpleRead&amp;lt;/code&amp;gt; gelesen. Da die Übertragung möglicherweise noch nicht vollständig ist, kann es sein, dass kurz darauf die X_Read-Funktion wieder aufgerufen wird und ein weiterer Teil oder der Rest der Daten gelesen werden kann.&lt;br /&gt;
Die Funktion muss daher prüfen ob schon alle erwarteten Daten angekommen sind und gegebenenfalls die bisher gelesenen Daten in einem eigenen Puffer (idealerweise in &amp;lt;code&amp;gt;$hash&amp;lt;/code&amp;gt;) zwischenspeichern. Im Beispiel ist dies &amp;lt;code&amp;gt;$hash-&amp;gt;{helper}{BUFFER}&amp;lt;/code&amp;gt; an den die aktuell gelesenen Daten angehängt werden, bis die folgende Prüfung ein für das jeweilige Protokoll vollständige Frame erkennt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Read($)&lt;br /&gt;
{&lt;br /&gt;
	my ($hash) = @_;&lt;br /&gt;
	my $name = $hash-&amp;gt;{NAME};&lt;br /&gt;
	&lt;br /&gt;
	# einlesen der bereitstehenden Daten&lt;br /&gt;
	my $buf = DevIo_SimpleRead($hash);		&lt;br /&gt;
	return &amp;quot;&amp;quot; if ( !defined($buf) );&lt;br /&gt;
	Log3 $name, 5, &amp;quot;X ($name) - received data: &amp;quot;.$buf;    &lt;br /&gt;
&lt;br /&gt;
	# Daten in Hex konvertieren und an den Puffer anhängen&lt;br /&gt;
	$hash-&amp;gt;{helper}{BUFFER} .= unpack (&#039;H*&#039;, $buf);	&lt;br /&gt;
	Log3 $name, 5, &amp;quot;X ($name) - current buffer content: &amp;quot;.$hash-&amp;gt;{helper}{BUFFER};&lt;br /&gt;
&lt;br /&gt;
	# prüfen, ob im Buffer ein vollständiger Frame zur Verarbeitung vorhanden ist.&lt;br /&gt;
	if ($hash-&amp;gt;{helper}{BUFFER} =~ &amp;quot;ff1002(.{4})(.*)1003(.{4})ff(.*)&amp;quot;) {&lt;br /&gt;
	...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die zu lesenden Nutzdaten können dann je nach Protokoll des Geräts beispielsweise an einer festgelegten Stelle im Frame (dann in &amp;lt;code&amp;gt;$hash-&amp;gt;{helper}{BUFFER}&amp;lt;/code&amp;gt;) stehen oder aus dem Kontext mit einem Regex-Match extrahiert werden und via [[DevelopmentModuleAPI#Readings_.2F_Events|Reading-Funktionen]] in Readings gespeichert werden (siehe unten).&lt;br /&gt;
&lt;br /&gt;
Der Rückgabewert der Read-Funktion wird nicht geprüft und hat daher keinerlei Bedeutung.&lt;br /&gt;
&lt;br /&gt;
==== X_Ready ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Ready ($)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
    &lt;br /&gt;
	return $success;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wird im Main-Loop aufgerufen falls das Modul in der globalen Liste &amp;lt;code&amp;gt;%readyfnlist&amp;lt;/code&amp;gt; existiert. Diese Funktion hat je nachdem auf welchem OS FHEM ausgeführt wird unterschiedliche Aufgaben:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;UNIX-artiges Betriebssystem:&#039;&#039;&#039; prüfen, ob eine Verbindung nach einem Verbindungsabbruch wieder aufgebaut werden kann. Sobald der Verbindungsaufbau erfolgreich war, muss die Funktion einen erfolgreichen Wahrheitswert zurückliefern (z.B. &amp;quot;1&amp;quot;) und den eigenen Eintrag entsprechend aus &amp;lt;code&amp;gt;%readyfnlist&amp;lt;/code&amp;gt; löschen.&lt;br /&gt;
* &#039;&#039;&#039;Windows-Betriebssystem:&#039;&#039;&#039; prüfen, ob lesbare Daten für ein serielles Device (via COM1, COM2, ...) vorliegen. Sofern lesbare Daten vorliegen, muss Funktion einen erfolgreichen Wahrheitswert zurückliefern (z.B. &amp;quot;1&amp;quot;). Zusätzlich dazu muss die Funktion, wie bei UNIX-artigen Betriebssystem, ebenfalls bei einem Verbindungsabbruch einen neuen Verbindungsversuch initiieren. Der Eintrag in &amp;lt;code&amp;gt;%readyfnlist&amp;lt;/code&amp;gt; bleibt solange erhalten, bis die Verbindung seitens FHEM beendet wird.&lt;br /&gt;
&lt;br /&gt;
Der Windows-spezifische Teil zur Datenprüfung ist dabei nur zu implementieren, wenn das Modul über eine serielle Verbindung kommuniziert.&lt;br /&gt;
&lt;br /&gt;
Bei der Nutzung des Moduls DevIo wird dem Modulentwickler der Umgang mit &amp;lt;code&amp;gt;%readyfnlist&amp;lt;/code&amp;gt; abgenommen, da DevIo sich selbst um die entsprechenden Einträge kümmert und diese selbstständig wieder entfernt.&lt;br /&gt;
&lt;br /&gt;
In der Regel sieht eine Ready-Funktion immer gleich aus.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Ready($)&lt;br /&gt;
{&lt;br /&gt;
	my ($hash) = @_;&lt;br /&gt;
      &lt;br /&gt;
	# Versuch eines Verbindungsaufbaus, sofern die Verbindung beendet ist.&lt;br /&gt;
	return DevIo_OpenDev($hash, 1, undef ) if ( $hash-&amp;gt;{STATE} eq &amp;quot;disconnected&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
	# This is relevant for Windows/USB only&lt;br /&gt;
	if(defined($hash-&amp;gt;{USBDev})) {&lt;br /&gt;
		my $po = $hash-&amp;gt;{USBDev};&lt;br /&gt;
		my ( $BlockingFlags, $InBytes, $OutBytes, $ErrorFlags ) = $po-&amp;gt;status;&lt;br /&gt;
		return ( $InBytes &amp;gt; 0 );&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== X_Notify ====&lt;br /&gt;
&lt;br /&gt;
Die X_Notify-Funktion wird aus der Funktion [[DevelopmentModuleAPI#DoTrigger|DoTrigger()]] in fhem.pl heraus aufgerufen sobald ein Modul Events erzeugt hat. Damit kann ein Modul auf Events anderer Module reagieren. Typische Beispiele sind dabei das [[FileLog]]-Modul oder das [[notify]]-Modul.&lt;br /&gt;
&lt;br /&gt;
Die Notify-Funktion bekommt dafür zwei Hash-Referenzen übergeben: den Hash des eigenen Geräts und den Hash des Geräts, dass die Events erzeugt hat. &lt;br /&gt;
Über den Hash des eigenen Geräts kann die Notify-Funktion beispielsweise auf die Internals oder Attribute des eigenen Geräts zugreifen.&lt;br /&gt;
Über den Hash des Gerätes und der [[DevelopmentModuleAPI#deviceEvents|deviceEvents()]]-Funktion kann man auf die generierten Events zugreifen. Über den zweiten Parameter dieser Routine lässt sich bestimmen ob für das Reading &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt; ein &#039;normales&#039; Event (d.h. in der form &amp;lt;code&amp;gt;state: &amp;lt;wert&amp;gt;&amp;lt;/code&amp;gt;) erzeugen soll (Wert: 1) oder ob z.b. aus Gründen der Rückwärtskompatibilität ein Event ohne &amp;lt;code&amp;gt;state: &amp;lt;/code&amp;gt; erzeugt werden soll. Falls dem Anwender die Wahl des verwendeten Formats überlassen werden soll ist hierzu das [http://fhem.de/commandref_DE.html#addStateEvent addStateEvent-Attribut] vorzusehen.&lt;br /&gt;
&lt;br /&gt;
Der direkte Zugriff auf &amp;lt;code&amp;gt;$hash-&amp;gt;{CHANGED}&amp;lt;/code&amp;gt; ist nicht mehr zu empfehlen.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Notify($$)&lt;br /&gt;
{&lt;br /&gt;
  my ($own_hash, $dev_hash) = @_;&lt;br /&gt;
  my $ownName = $own_hash-&amp;gt;{NAME}; # own name / hash&lt;br /&gt;
&lt;br /&gt;
  return &amp;quot;&amp;quot; if(IsDisabled($ownName)); # Return without any further action if the module is disabled&lt;br /&gt;
&lt;br /&gt;
  my $devName = $dev_hash-&amp;gt;{NAME}; # Device that created the events&lt;br /&gt;
&lt;br /&gt;
  my $events = deviceEvents($dev_hash,1);&lt;br /&gt;
  return if( !$events );&lt;br /&gt;
&lt;br /&gt;
  foreach my $event (@{$events}) {&lt;br /&gt;
    $event = &amp;quot;&amp;quot; if(!defined($event));&lt;br /&gt;
&lt;br /&gt;
    # Examples:&lt;br /&gt;
    # $event = &amp;quot;readingname: value&amp;quot; &lt;br /&gt;
    # or&lt;br /&gt;
    # $event = &amp;quot;INITIALIZED&amp;quot; (for $devName equal &amp;quot;global&amp;quot;)&lt;br /&gt;
    #&lt;br /&gt;
    # processing $event with further code&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Begrenzung der Aufrufe auf bestimmte Geräte&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Da die Notify-Funktion für jedes definierte Gerät mit all seinen Events aufgerufen wird, muss sie in einer Schleife jedesmal prüfen und entscheiden, ob es mit dem jeweiligen Event etwas anfangen kann. Ein Gerät, dass die Notify-Funktion implementiert, sieht dafür typischerweise einen regulären Ausdruck vor, welcher für die Filterung verwendet wird.&lt;br /&gt;
&lt;br /&gt;
Wenn man nur gezielt von bestimmten Definitionen Events erhalten will, kann man diese auch in Form einer [http://fhem.de/commandref_DE.html#devspec devspec] in &amp;lt;code&amp;gt;$hash-&amp;gt;{NOTIFYDEV}&amp;lt;/code&amp;gt; angeben. Bspw. kann man in der Define-Funktion diesen Wert setzen. Dadurch wird die Notify-Funktion nur aufgerufen wenn eine der Definitionen, auf welche die devspec passt, ein Event erzeugt hat. Ein typischer Fall ist die Begrenzung von Events auf &amp;quot;global&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
in der Define-Funktion:&lt;br /&gt;
&lt;br /&gt;
$hash-&amp;gt;{NOTIFYDEV} = &amp;quot;global&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{NOTIFYDEV} = &amp;quot;global,Definition_A,Definition_B&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{NOTIFYDEV} = &amp;quot;global,TYPE=CUL_HM&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dies schont insbesondere bei grossen Installationen Ressourcen, da die Notify-Funktion nicht sämtliche Events, sondern nur noch Events der gewünschten Definitionen erhält. Dadurch erfolgen deutlich weniger Aufrufe der Notify-Funktion, was Systemressourcen schont.&lt;br /&gt;
&lt;br /&gt;
Sofern in der [[#X_Define|Define-Funktion]] eine Regexp als Argument übergeben wird, die ähnlich wie beim Modul [[notify]] auf Events wie &amp;lt;code&amp;gt;&amp;amp;lt;Definitionsname&amp;amp;gt;&amp;lt;/code&amp;gt; bzw. &amp;lt;code&amp;gt;&amp;amp;lt;Definitionsname&amp;amp;gt;:&amp;amp;lt;Event&amp;amp;gt;&amp;lt;/code&amp;gt; reagiert, so sollte man in der Define-Funktion die Funktion [[DevelopmentModuleAPI#notifyRegexpChanged|notifyRegexpChanged()]] verwenden. Diese versucht einen passenden Eintrag für &amp;lt;code&amp;gt;$hash-&amp;gt;{NOTIFYDEV}&amp;lt;/code&amp;gt; basierend auf der übergebenen Regexp zu setzen, sofern dies möglich ist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Reihenfolge für den Aufruf der Notify-Funktion beeinflussen&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sobald ein Event ausgelöst wurde, stellt sich FHEM eine Liste aller relevanten Geräte-Hashes zusammen, welche via Notify-Funktion prüfen müssen, ob das Event relevant ist. Dabei wird die Liste nach &amp;lt;code&amp;gt;$hash-&amp;gt;{NTFY_ORDER}&amp;lt;/code&amp;gt; sortiert. Diese enthält ein Order-Präfix in Form einer Ganzzahl, sowie den Namen der Definition (Bsp: &amp;lt;code&amp;gt;&#039;&#039;&#039;50&#039;&#039;&#039;-Lampe_Wohnzimmer&amp;lt;/code&amp;gt;). Dadurch kann man jedoch nicht sicherstellen, dass Events von bestimmten Modulen zuerst verarbeitet werden.&lt;br /&gt;
&lt;br /&gt;
Wenn das eigene Modul bei der Eventverarbeitung gegenüber den anderen Modulen eine bestimmte Reihenfolge einhalten muss, kann man in der [[#X_Initialize|Initialize]]-Funktion durch Setzen von &amp;lt;code&amp;gt;$hash-&amp;gt;{NotifyOrderPrefix}&amp;lt;/code&amp;gt; diese Reihenfolge beeinflussen. Standardmäßig werden Module immer mit einem Order-Präfix von &amp;quot;50-&amp;quot; in FHEM registriert. Durch die Veränderung dieses Präfixes kann man das eigene Modul in der Reihenfolge gegenüber anderen Modulen bei der Eventverarbeitung beeinflussen. &lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Initialize($)&lt;br /&gt;
{&lt;br /&gt;
	my ($hash) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
	&lt;br /&gt;
	$hash-&amp;gt;{NotifyOrderPrefix} = &amp;quot;45-&amp;quot;  # Alle Definitionen des Moduls X werden bei der Eventverarbeitung zuerst geprüft&lt;br /&gt;
	&lt;br /&gt;
	# oder...&lt;br /&gt;
	&lt;br /&gt;
	$hash-&amp;gt;{NotifyOrderPrefix} = &amp;quot;55-&amp;quot;  # Alle Definitionen des Moduls X werden bei der Eventverarbeitung als letztes geprüft&lt;br /&gt;
	&lt;br /&gt;
&amp;lt;/source&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
Da dieses Präfix bei eventverarbeitenden Definitionen in &amp;lt;code&amp;gt;$hash-&amp;gt;{NTFY_ORDER}&amp;lt;/code&amp;gt; dem Definitionsnamen vorangestellt wird bewirkt es bei einer normalen aufsteigenden Sortierung nach &amp;lt;code&amp;gt;$hash-&amp;gt;{NTFY_ORDER}&amp;lt;/code&amp;gt; eine veränderte Reihenfolge. Alle Module die in der Initialize-Funktion nicht &amp;lt;code&amp;gt;$hash-&amp;gt;{NotifyOrderPrefix}&amp;lt;/code&amp;gt; explizit setzen, werden mit &amp;quot;50-&amp;quot; als Standardwert vorbelegt.&lt;br /&gt;
&lt;br /&gt;
==== X_Rename ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Rename ($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $new_name, $old_name) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Rename-Funktion wird ausgeführt, nachdem ein Gerät umbenannt wurde. Auf diese Weise kann ein Modul auf eine Namensänderung reagieren, wenn das Gerät &amp;lt;code&amp;gt;$old_name&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;$new_name&amp;lt;/code&amp;gt; umbenannt wurde. Ein typischer Fall ist das Umsetzen der Namensänderungen bei Daten die mittels [[DevelopmentModuleAPI#setKeyValue|setKeyValue()]] gespeichert wurden. Hierbei müssen die Daten, welche unter dem alten Namen gespeichert sind, auf den neuen Namen geändert werden.&lt;br /&gt;
&lt;br /&gt;
Der Rename-Funktion wird lediglich der alte, sowie der neue Gerätename übergeben. Der Rückgabewert wird nicht ausgewertet.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Rename ($)&lt;br /&gt;
{&lt;br /&gt;
	my ( $new_name, $old_name ) = @_;&lt;br /&gt;
&lt;br /&gt;
	my $old_index = &amp;quot;Module_X_&amp;quot;.$old_name.&amp;quot;_data&amp;quot;;&lt;br /&gt;
	my $new_index = &amp;quot;Module_X_&amp;quot;.$new_name.&amp;quot;_data&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	my ($err, $data) = getKeyValue($old_index);&lt;br /&gt;
	return undef unless(defined($old_pwd));&lt;br /&gt;
&lt;br /&gt;
	setKeyValue($new_index, $data);&lt;br /&gt;
	setKeyValue($old_index, undef);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== X_Shutdown ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Shutdown ($)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Mit der X_Shutdown Funktion kann ein Modul Aktionen durchführen bevor FHEM gestoppt wird. Dies kann z.B. der ordnungsgemäße Verbindungsabbau mit dem physikalischen Gerät sein (z.B. Session beenden, Logout, etc.). Als Übergabeparameter wird der Geräte-Hash bereitgestellt. Der Rückgabewert einer Shutdown-Funktion wird nicht ausgewertet und ist daher irrelevant.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Shutdown($)&lt;br /&gt;
{&lt;br /&gt;
	my ($hash) = @_;&lt;br /&gt;
&lt;br /&gt;
	# Verbindung schließen&lt;br /&gt;
	DevIo_CloseDev($hash);&lt;br /&gt;
        return undef;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Funktionen für zweistufiges Modulkonzept ===&lt;br /&gt;
&lt;br /&gt;
Für das [[#Zweistufiges_Modell_für_Module|zweistufige Modulkonzept]] gibt es weiterhin:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;text-align:left&amp;quot; | Funktionsname !! style=&amp;quot;text-align:left&amp;quot; class=&amp;quot;unsortable&amp;quot; | Kurzbeschreibung&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Parse|X_Parse]] || Zustellen von Daten via [[DevelopmentModuleAPI#Dispatch|Dispatch()]] vom physischen Modul zum logischen Modul zwecks der Verarbeitung.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Write|X_Write]]|| Zustellen von Daten via [[DevelopmentModuleAPI#Dispatch|IOWrite()]] vom logischen zum physischen Modul um diese an die Hardware weiterzureichen.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Fingerprint|X_Fingerprint]] || Rückgabe eines &amp;quot;Fingerabdrucks&amp;quot; einer Nachricht. Dient der Erkennung von Duplikaten im Rahmen von [[DevelopmentModuleAPI#Dispatch|Dispatch()]]. Kann im physischen, als auch logischen Modul benutzt werden.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Für das zweistufige Modulkonzept muss in einem logischen Modul eine [[#X_Parse|Parse]]-Funktion im Modul-Hash registriert werden. In einem physikalischen Modul muss eine [[#X_Write|Write]]-Funktion definiert sein. Diese dienem dem Datenaustausch in beide Richtungen und werden von dem jeweils anderen Modul indirekt aufgerufen.&lt;br /&gt;
&lt;br /&gt;
In der [[#X_Initialize|Initialize]]-Funktion werden diese wie folgt definiert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
$hash-&amp;gt;{ParseFn}       = &amp;quot;X_Parse&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{WriteFn}       = &amp;quot;X_Write&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{FingerprintFn} = &amp;quot;X_Fingerprint&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Funktionen werden in diesem Abschnitt genauer beschrieben.&lt;br /&gt;
&lt;br /&gt;
==== X_Parse ====&lt;br /&gt;
{{Randnotiz|RNTyp=Info|RNText=&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&amp;lt;u&amp;gt;&#039;&#039;&#039;ACHTUNG&#039;&#039;&#039;:&amp;lt;/u&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
Dieser Abschnitt geht davon aus, dass das Modul mit dem Namen &amp;quot;X&amp;quot; ein &#039;&#039;&#039;logisches Modul&#039;&#039;&#039; im Sinne des zweistufigen Modulkonzepts ist, also Daten mit einem übergeordneten, physikalischen Modul austauscht.}}&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Parse ($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $io_hash, $message) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
	&lt;br /&gt;
	return $found;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Funktion X_Parse wird aufgerufen, sobald von dem IO-Gerät &amp;lt;code&amp;gt;$io_hash&amp;lt;/code&amp;gt; eine Nachricht &amp;lt;code&amp;gt;$message&amp;lt;/code&amp;gt; via [[DevelopmentModuleAPI#Dispatch|Dispatch()]] zur Verarbeitung angefragt wird. Die Parse-Funktion muss dann prüfen, zu welcher Gerätedefinition diese Nachricht gehört und diese entsprechend verarbeiten.&lt;br /&gt;
&lt;br /&gt;
Üblicherweise enthält eine Nachricht immer eine Komponente durch welche sich die Nachricht einem Gerät zuordnen lässt (z.B. Adresse, ID-Nummer, ...). Eine solche Identifikation sollte man im Rahmen der [[#X_Define|Define]]-Funktion im logischen Modul an geeigneter Stelle speichern, um in der Parse-Funktion eine einfache Zuordnung von Adresse/ID einer Nachricht zur entsprechenden Gerätedefinition zu haben. Dazu wird in der Regel im Modul-Hash im modulspezifischen Berreich eine Liste &amp;lt;code&amp;gt;defptr&amp;lt;/code&amp;gt; (Definition Pointer) geführt, welche jede eindeutige Adresse/ID dem entsprechenden Geräte-Hash zuordnet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sub X_Define ($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $def) = @_;&lt;br /&gt;
	my @a = split(&amp;quot;[ \t][ \t]*&amp;quot;, $def);&lt;br /&gt;
	my $name = $a[0];&lt;br /&gt;
&lt;br /&gt;
	...&lt;br /&gt;
	&lt;br /&gt;
	# erstes Argument ist die eindeutige Geräteadresse&lt;br /&gt;
	my $address = $a[1];&lt;br /&gt;
&lt;br /&gt;
	# Adresse rückwärts dem Hash zuordnen (für ParseFn)&lt;br /&gt;
	$modules{X}{defptr}{$address} = $hash;&lt;br /&gt;
&lt;br /&gt;
	...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Auf Basis dieses Definition Pointers kann die Parse-Funktion nun sehr einfach prüfen, ob für die empfangene Nachricht bereits eine entsprechende Gerätedefinition existiert. Sofern diese existiert, kann die Nachricht entsprechend verarbeitet werden. Sollte jedoch keine passende Gerätedefinition zu der empfangenen Nachricht existieren, so muss die Parse-Funktion den Gerätenamen &amp;quot;UNDEFINED&amp;quot; zusammen mit den Argumenten für einen &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt;-Befehl zurückgeben, welcher ein passendes Gerät in FHEM anlegen würde (durch [[autocreate]]).&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sub X_Parse ($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $io_hash, $message) = @_;&lt;br /&gt;
	&lt;br /&gt;
	# Die Stellen 10-15 enthalten die eindeutige Identifikation des Geräts&lt;br /&gt;
	my $address = substr($message, 10, 5); &lt;br /&gt;
&lt;br /&gt;
	# wenn bereits eine Gerätedefinition existiert (via Definition Pointer aus Define-Funktion)&lt;br /&gt;
	if(my $hash = $modules{X}{defptr}{$address}) &lt;br /&gt;
	{&lt;br /&gt;
		...  # Nachricht für $hash verarbeiten&lt;br /&gt;
		&lt;br /&gt;
		# Rückgabe des Gerätenamens, für welches die Nachricht bestimmt ist.&lt;br /&gt;
		return $hash-&amp;gt;{NAME}; &lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		# Keine Gerätedefinition verfügbar&lt;br /&gt;
		# Daher Vorschlag define-Befehl: &amp;lt;NAME&amp;gt; &amp;lt;MODULNAME&amp;gt; &amp;lt;ADDRESSE&amp;gt;&lt;br /&gt;
		return &amp;quot;UNDEFINED X_&amp;quot;.$address.&amp;quot; X $address&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== X_Write ====&lt;br /&gt;
{{Randnotiz|RNTyp=Info|RNText=&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&amp;lt;u&amp;gt;&#039;&#039;&#039;ACHTUNG&#039;&#039;&#039;:&amp;lt;/u&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
Dieser Abschnitt geht davon aus, dass das Modul mit dem Namen &amp;quot;X&amp;quot; ein &#039;&#039;&#039;physisches Modul&#039;&#039;&#039; im Sinne des zweistufigen Modulkonzepts ist, also Daten mit untergeordneten logischen Modulen austauscht. }}&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Write ($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, @arguments) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
	&lt;br /&gt;
	return $return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Write-Funktion wird durch die Funktion [[DevelopmentModuleAPI#IOWrite|IOWrite()]] aufgerufen, sobald eine logische Gerätedefinition Daten per IO-Gerät an die Hardware übertragen möchte. Dazu kümmert sich die Write-Funktion um die Übertragung der Nachricht in geeigneter Form an die verbundene Hardware. Als Argumente wird der Hash des physischen Gerätes übertragen, sowie alle weiteren Argumente, die das logische Modul beim Aufruf von IOWrite() mitgegeben hat. Im Normalfall ist das ein Skalar mit der zu sendenden Nachricht in Textform. Es kann aber auch sein, dass weitere Daten zum Versand notwendig sind (evtl. Schlüssel, Session-Key, ...). Daher ist die Parametersyntax einer zu schreibenden Nachricht via IOWrite-/Write-Funktion zwischen logischem und physikalischen Modul abzustimmen.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Write ($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $message, $address) = @_;&lt;br /&gt;
	&lt;br /&gt;
	DevIo_SimpleWrite($hash, $address.$message, 2);&lt;br /&gt;
&lt;br /&gt;
	return undef;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== X_Fingerprint ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Fingerprint($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $io_name, $msg ) = @_;&lt;br /&gt;
 &lt;br /&gt;
	...&lt;br /&gt;
 &lt;br /&gt;
	return ( $io_name, $fingerprint );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Fingerprint-Funktion dient der Erkennung von Duplikaten empfangener Nachrichten. Diese Funktion kann dabei sowohl im physischen, als auch im logischen Modul implementiert sein. Je nachdem auf welcher Ebene man für eine Nachricht einen Fingerprint bilden kann. &lt;br /&gt;
&lt;br /&gt;
Als Parameter wird der Name des IO-Geräts &amp;lt;code&amp;gt;$io_name&amp;lt;/code&amp;gt; übergeben, sowie die Nachricht &amp;lt;code&amp;gt;$msg&amp;lt;/code&amp;gt;, welche empfangen wurde. Nun muss aus dieser Nachricht ein eindeutiger Fingerprint gebildet werden. Dies bedeutet, dass alle variablen Inhalte, die aufgrund des Empfangs dieser Nachricht über unterschiedliche IO-Geräte enthalten sein können, entfernt werden müssen. Dies können bspw. Empfangsadressen von IO-Geräten sein oder Session-ID&#039;s die in der Nachricht enthalten sind. Alle Fingerprints sämtlicher Nachrichten, die innerhalb der letzten 500 Millisekunden (konfigurierbar via &amp;lt;code&amp;gt;global&amp;lt;/code&amp;gt; Attribut &amp;lt;code&amp;gt;dupTimeout&amp;lt;/code&amp;gt;) empfangen wurden, werden gegen diesen generierten Fingerprint getestet. Sollte innerhalb dieser Zeit bereits eine Nachricht mit diesem Fingerprint verarbeitet worden sein, so wird sie als Duplikat erkannt und nicht weiter verarbeitet. In diesem Fall gibt [[DevelopmentModuleAPI#Dispatch|Dispatch()]] den Namen der Gerätedefinition zurück, welche eine Nachricht mit dem selben Fingerprint bereits verarbeitet hat. Es erfolgt dann kein Aufruf der [[#X_Parse|Parse]]-Funktion.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Fingerprint($$)&lt;br /&gt;
{&lt;br /&gt;
  my ( $io_name, $msg ) = @_;&lt;br /&gt;
&lt;br /&gt;
  substr( $msg, 2, 2, &amp;quot;--&amp;quot; ); # entferne Empfangsadresse&lt;br /&gt;
  substr( $msg, 4, 1, &amp;quot;-&amp;quot; );  # entferne Hop-Count&lt;br /&gt;
&lt;br /&gt;
  return ( $io_name, $msg );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es wird zuerst, sofern implementiert, die Fingerprint-Funktion des physischen Moduls aufgerufen. Sollte sich hierdurch kein Duplikat erkennen lassen, wird die Fingerprint-Funktion jedes möglichen geladenen logischen Moduls aufgerufen, sofern implementiert. &lt;br /&gt;
&lt;br /&gt;
Sollte sowohl im physischen, als auch im logischen Modul keine Fingerprint-Funktion implementiert sein, so wird keinerlei Duplikatserkennung durchgeführt.&lt;br /&gt;
&lt;br /&gt;
=== FHEMWEB-spezifische Funktionen ===&lt;br /&gt;
&lt;br /&gt;
FHEMWEB bietet Modulautoren die Möglichkeit an durch spezielle Funktionsaufrufe in Modulen, eigene HTML-Inhalte zu verwenden. Dadurch können in Verbindung mit zusätzlichem JavaScript komplexe Dialoge/Inhalte/Steuermöglichkeiten dargestellt werden. &lt;br /&gt;
&lt;br /&gt;
Eine genaue Auflistung aller FHEMWEB-spezifischen Funktionsaufrufe gibt es in dem separaten Artikel [[DevelopmentFHEMWEB]]&lt;br /&gt;
&lt;br /&gt;
=== sonstige Funktionen ===&lt;br /&gt;
&lt;br /&gt;
In diesem Abschnitt werden weitere Funktionen behandelt die zum Teil aus FHEM, aber auch aus anderen Modulen aufgerufen werden. Sie sind dabei nur in speziellen Anwendungsfällen relevant. Hier eine Auflistung aller sonstigen Modulfunktionen:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Funktionsname !! class=&amp;quot;unsortable&amp;quot; | Kurzbeschreibung&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_DbLog_split|X_DbLog_split]] || Wird durch das Modul 93_DbLog.pm aufgerufen. Dient dem korrekten Split eines moduleigenen Events in Name/Wert/Einheit für die Nutzung einer Datenbank.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Except|X_Except]]|| Wird aufgerufen, sobald ein ein geöffneter Filedescriptor in [[#Wichtige_globale_Variablen_aus_fhem.pl|&amp;lt;code&amp;gt;%selectlist&amp;lt;/code&amp;gt;]], der unter &amp;lt;code&amp;gt;$hash-&amp;gt;{EXCEPT_FD}&amp;lt;/code&amp;gt; im Geräte-Hash gesetzt ist, einen Interrupt bzw. Exception auslöst.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Copy|X_Copy]]|| Wird durch das Modul 98_copy.pm aufgerufen im Rahmen des &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt;-Befehls sobald ein Gerät kopiert wurde.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_State|X_State]]|| Wird aufgerufen im Rahmen des &amp;lt;code&amp;gt;setstate&amp;lt;/code&amp;gt;-Befehls bevor der Status einer Gerätedefinition bzw. eines zugehörigen Readings gesetzt wird.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_AsyncOutput|X_AsyncOutput]]|| Nur Relevant für Module die via [[TcpServerUtils]] eine Client-Verbindung zu FHEM ermöglichen (z.B. FHEMWEB und telnet). Ermöglicht die asynchrone Ausgabe von Daten via [[DevelopmentModuleAPI#asyncOutput|asyncOutput()]] an einen einzelnen verbundenen Client.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_ActivateInform|X_ActivateInform]]|| Nur Relevant für Module die via [[TcpServerUtils]] eine Client-Verbindung zu FHEM ermöglichen (z.B. FHEMWEB und telnet). Ermöglicht das aktivieren des inform-Mechanismus zum senden von Events für einen einzelnen verbundenen Client.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Authorize|X_Authorize]]|| Wird aufgerufen im Rahmen von [[DevelopmentModuleAPI#Authorize|Authorize()]] um eine gewünschte Vorgangs-Art zu autorisieren.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Authenticate|X_Authenticate]]||  Wird aufgerufen im Rahmen von [[DevelopmentModuleAPI#Authenticate|Authenticate()]] um eine Authentifizierung zu prüfen und ggf. zu genehmigen.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In der [[#X_Initialize|Initialize]]-Funktion werden diese wie folgt definiert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
$hash-&amp;gt;{DbLog_splitFn} = &amp;quot;X_DbLog_split&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{ExceptFn} = &amp;quot;X_Except&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{CopyFn} = &amp;quot;X_Copy&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{AsyncOutputFn} = &amp;quot;X_AsyncOutput&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{ActivateInformFn} = &amp;quot;X_ActivateInform&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{StateFn} = &amp;quot;X_State&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{AuthorizeFn} = &amp;quot;X_Authorize&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{AuthenticateFn} = &amp;quot;X_Authenticate&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Diese Funktionen werden in diesem Abschnitt genauer beschrieben.&lt;br /&gt;
==== X_DbLog_split ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_DbLog_split ($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $event, $device_name ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
    &lt;br /&gt;
	return  ( $reading, $value, $unit );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die DbLog_split-Funktion wird durch das Modul [[DbLog]] aufgerufen, sofern der Nutzer DbLog benutzt. Sofern diese Funktion implementiert ist, kann der Modulautor das Auftrennen von Events in den Reading-Namen, -Wert und der Einheit selbst steuern. Andernfalls nimmt DbLog diese Auftrennung selber mittels Trennung durch Leerzeichen sowie vordefinierten Regeln zu verschiedenen Modulen vor. Je nachdem, welche Readings man in seinem Modul implementiert, passt diese standardmäßige Trennung jedoch nicht immer.&lt;br /&gt;
&lt;br /&gt;
Der Funktion werden folgende Eingangsparameter übergeben:&lt;br /&gt;
# Das generierte Event (Bsp: &amp;lt;code&amp;gt;temperature: 20.5 °C&amp;lt;/code&amp;gt;)&lt;br /&gt;
# Der Name des Geräts, welche das Event erzeugt hat (Bsp: &amp;lt;code&amp;gt;Temperatursensor_Wohnzimmer&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Es ist nicht möglich in der DbLog_split-Funktion auf die verarbeitende DbLog-Definition zu referenzieren.&lt;br /&gt;
&lt;br /&gt;
Als Rückgabewerte muss die Funktion folgende Werte bereitstellen:&lt;br /&gt;
# Name des Readings (Bsp: &amp;lt;code&amp;gt;temperature&amp;lt;/code&amp;gt;)&lt;br /&gt;
# Wert des Readings (Bsp: &amp;lt;code&amp;gt;20.5&amp;lt;/code&amp;gt;)&lt;br /&gt;
# Einheit des Readings (Bsp: &amp;lt;code&amp;gt;°C&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_DbLog_splitFn($$)&lt;br /&gt;
{&lt;br /&gt;
	my ($event, $device) = @_;&lt;br /&gt;
	my ($reading, $value, $unit);&lt;br /&gt;
        my $devhash = $defs{$device}&lt;br /&gt;
&lt;br /&gt;
	if($event =~ m/temperature/) {&lt;br /&gt;
	   $reading = &#039;temperature&#039;;&lt;br /&gt;
	   $value = substr($event,12,4);&lt;br /&gt;
	   $unit = &#039;°C&#039;;&lt;br /&gt;
	}   &lt;br /&gt;
        &lt;br /&gt;
        return ($reading, $value, $unit);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== X_Except ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Except ($)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die X_Except-Funktion wird durch fhem.pl aufgerufen, wenn die Gerätedefinition &amp;lt;code&amp;gt;$hash&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;[[#Wichtige_globale_Variablen_aus_fhem.pl|%selectlist]]&amp;lt;/code&amp;gt; aufgeführt ist und der Filedeskriptor in &amp;lt;code&amp;gt;$hash-&amp;gt;{EXCEPT_FD}&amp;lt;/code&amp;gt; eine Exception bzw. Interrupt auslöst. &lt;br /&gt;
&lt;br /&gt;
Der Rückgabewert wird nicht ausgewertet und ist daher irrelevant.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
use IO::File;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
sub X_Except ($)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	# Filehandle aus Filedescriptor erstellen&lt;br /&gt;
	my $filehandle = IO::File-&amp;gt;new_from_fd($hash-&amp;gt;{EXCEPT_FD}, &#039;r&#039;);&lt;br /&gt;
	seek($filehandle,0,0);	&lt;br /&gt;
&lt;br /&gt;
	# aktuellen Inhalt auslesen&lt;br /&gt;
	my $current_value = $filehandle-&amp;gt;getline;&lt;br /&gt;
&lt;br /&gt;
	if($current_value eq &amp;quot;1&amp;quot;)&lt;br /&gt;
	{&lt;br /&gt;
		...&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		...&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== X_Copy ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Copy ($)&lt;br /&gt;
{&lt;br /&gt;
	my ( $old_name, $new_name ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die X_Copy-Funktion wird durch das Modul [[copy]] aufgerufen nachdem ein Nutzer eine Gerätedefinition über den Befehl &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt; kopiert hat. Dazu werden als Funktionsparameter die Definitionsnamen der alten und neuen Gerätedefinition übergeben. Es dient dazu zusätzliche Daten aus der zu kopierenden Gerätedefinition in die neue Definition zu übernehmen. Der Befehl &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt; überträgt lediglich &amp;lt;code&amp;gt;$hash-&amp;gt;{DEF}&amp;lt;/code&amp;gt; in die neue Definition sowie sämtliche gesetzte Attribute. Weitere Daten müssen dann durch die X_Copy-Funktion übertragen werden. &lt;br /&gt;
&lt;br /&gt;
Die X_Copy-Funktion wird erst nach dem erfolgtem Kopiervorgang aufgerufen.&lt;br /&gt;
&lt;br /&gt;
Der Rückgabewert wird nicht ausgewertet und ist daher irrelevant.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sub X_Copy ($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $old_name, $new_name ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	my $old_hash = $defs{$old_name};&lt;br /&gt;
	my $new_hash = $defs{$new_name};&lt;br /&gt;
&lt;br /&gt;
	# copy also temporary session key&lt;br /&gt;
	$new_hash-&amp;gt;{helper}{SESSION_KEY} = $old_hash-&amp;gt;{helper}{SESSION_KEY};&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== X_AsyncOutput ====&lt;br /&gt;
TBD&lt;br /&gt;
&lt;br /&gt;
==== X_ActivateInform ====&lt;br /&gt;
TBD&lt;br /&gt;
==== X_State ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_State($)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $time, $readingName, $value ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
&lt;br /&gt;
	return $error;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die X_State-Funktion wird durch fhem.pl aufgerufen, sobald über den Befehl &amp;lt;code&amp;gt;setstate&amp;lt;/code&amp;gt; versucht wird ein Wert für ein Reading oder den Status (&amp;lt;code&amp;gt;$hash-&amp;gt;{STATE}&amp;lt;/code&amp;gt;) einer Gerätedefinition zu setzen. Dieser Befehl wird primär beim Starten von FHEM aufgerufen sobald das State-File eingelesen wird. Je nachdem, ob im gegebenen Fall ein Reading oder der Definitionsstatus gesetzt wird, haben die Übergabeparameter verschiedene Werte:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Funktionsparameter!! Wert beim Setzen eines Readings !! Wert beim Setzen eines Definitionsstatus&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash&amp;lt;/code&amp;gt; || colspan=2 align=center | Die Hashreferenz der betreffenden Gerätedefinition&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$time&amp;lt;/code&amp;gt;|| Der Zeitstempel auf welchen das Reading &amp;lt;code&amp;gt;$readingName&amp;lt;/code&amp;gt; gesetzt werden soll. Das Ergebnis entspricht dem Rückgabewert der Funktion || Der aktuelle Zeitstempel zum jetzigen diesem Zeitpunkt.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$readingName&amp;lt;/code&amp;gt;|| Der Name des Readings, welches auf einen neuen Wert gesetzt werden soll. || Statischer Wert &amp;quot;STATE&amp;quot; um anzuzeigen, dass es sich um den Definitionsstatus handelt, welcher gesetzt werden soll (&amp;lt;code&amp;gt;$hash-&amp;gt;{STATE}&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$value&amp;lt;/code&amp;gt; || Der Wert, welchen das Reading &amp;lt;code&amp;gt;$readingName&amp;lt;/code&amp;gt; annehmen soll. || Der Wert, welchen die Gerätedefinition als Status annehmen soll.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Wenn via &amp;lt;code&amp;gt;setstate&amp;lt;/code&amp;gt; ein Reading gesetzt wird, kann die X_State-Funktion das Setzen dieses Readings durch die Rückgabe einer aussagekräftigen Fehlermeldung unterbinden. Sofern &amp;lt;code&amp;gt;undef&amp;lt;/code&amp;gt; zurückgegeben wird, wird das entsprechende Reading auf den übergebenen Status gesetzt.&lt;br /&gt;
&lt;br /&gt;
Wenn via &amp;lt;code&amp;gt;setstate&amp;lt;/code&amp;gt; der Definitionsstatus gesetzt wird, wird die X_State-Funktion erst nach dem Setzen des Status aufgerufen. Man kann dabei zwar eine Fehlermeldung zurückgeben. Der Status wird aber dennoch übernommen. Die Fehlermeldung wird lediglich dem Nutzer angezeigt.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_State($)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $time, $readingName, $value ) = @_;&lt;br /&gt;
&lt;br /&gt;
	return undef if($readingName &amp;quot;STATE&amp;quot; || $value ne &amp;quot;inactive&amp;quot;);&lt;br /&gt;
	readingsSingleUpdate($hash, &amp;quot;state&amp;quot;, &amp;quot;inactive&amp;quot;, 1);&lt;br /&gt;
	return undef;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== X_Authorize ====&lt;br /&gt;
TBD&lt;br /&gt;
&lt;br /&gt;
==== X_Authenticate ====&lt;br /&gt;
TBD&lt;br /&gt;
&lt;br /&gt;
== Bereitstellen eines eigenen Befehls (Befehlsmodul) ==&lt;br /&gt;
&lt;br /&gt;
Ein Modul kann primär einen neuen FHEM-Befehl bereitstellen. Man spricht in so einem Fall nicht von einem Gerätemodul, sondern einem Befehlsmodul. Ein solches Befehlsmodul stellt nur einen einzelnen Befehl bereit, der dem Modulnamen entsprechen muss. Nur, wenn der Modulname dem Befehlsname entspricht, kann FHEM das Modul beim ersten Ausführen dieses unbekannten Befehls finden und nachladen.&lt;br /&gt;
&lt;br /&gt;
Der entsprechende Befehl wird dazu in der [[#X_Initialize|Initialize]]-Funktion im globalen Hash &amp;lt;code&amp;gt;[[DevelopmentModuleIntro#Wichtige_globale_Variablen_aus_fhem.pl|%cmds]]&amp;lt;/code&amp;gt; registriert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Initialize($$) {&lt;br /&gt;
&lt;br /&gt;
	$cmds{X} = { Fn           =&amp;gt; &amp;quot;CommandX&amp;quot;,&lt;br /&gt;
	             Hlp          =&amp;gt; &amp;quot;&amp;lt;argument1&amp;gt; [optional_argument2], print something very useful&amp;quot;,&lt;br /&gt;
 &lt;br /&gt;
                     # optional&lt;br /&gt;
		     ClientFilter =&amp;gt; &amp;quot;FHEMWEB&amp;quot;&lt;br /&gt;
	           };&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Damit wird der neue Befehl &amp;lt;code&amp;gt;X&amp;lt;/code&amp;gt; in FHEM registriert. Die Funktion mit dem Namen &amp;lt;code&amp;gt;CommandX&amp;lt;/code&amp;gt; setzt diesen Befehl innerhalb des Moduls um. Desweiteren wird eine kurze Aufrufsyntax mitgegeben, welche beim Aufruf des &amp;lt;code&amp;gt;help&amp;lt;/code&amp;gt;-Befehls dem Nutzer angezeigt wird um als Gedankenstütze zu dienen. Optional kann man mittels &amp;lt;code&amp;gt;ClientFilter&amp;lt;/code&amp;gt; die Ausführbarkeit nur auf bestimmte Client-Module (wie FHEMWEB oder telnet) beschränken. &lt;br /&gt;
&lt;br /&gt;
Nun muss noch die Funktion &amp;lt;code&amp;gt;CommandX&amp;lt;/code&amp;gt; im Rahmen des Moduls implementiert werden, welche den Befehl &amp;lt;code&amp;gt;X&amp;lt;/code&amp;gt; umsetzt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
sub CommandX($$)&lt;br /&gt;
{&lt;br /&gt;
 	my ($client_hash, $arguments) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
	&lt;br /&gt;
	return $output;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dabei werden der Befehlsfunktion zwei Parameter übergeben. Zuerst die Hash-Referenz des aufrufenden Clients (sofern manuell ausgeführt, ansonsten &amp;lt;code&amp;gt;undef&amp;lt;/code&amp;gt;) zwecks Rechteprüfung via [[allowed|allowed-Definitionen]]. Anschließend folgen die Aufrufparameter als zusammenhängende Zeichenkette. Die Trennung der einzelnen Argumente obligt der Funktion (bspw. via [[DevelopmentModuleAPI#parseParams|parseParams()]]). Als Funktionsrückgabewert wird eine Ausgabemeldung erwartet, die dem Nutzer angezeigt werden soll.&lt;br /&gt;
&lt;br /&gt;
== Pollen von Geräten ==&lt;br /&gt;
Wenn Geräte von sich aus keine Informationen senden sondern abgefragt werden müssen, kann man im Modul die Funktion [[DevelopmentModuleAPI#InternalTimer|InternalTimer()]] verwenden um einen Funktionsaufruf zu einem späteren Zeitpunkt durchführen zu können. Man übergibt dabei den Zeitpunkt für den nächsten Aufruf, den Namen der Funktion, die aufgerufen werden soll, sowie den zu übergebenden Parameter. Als zu übergebender Parameter wird üblicherweise der Hash der betroffenen Geräteinstanz verwendet. Damit hat die aufgerufene Funktion Zugriff auf alle wichtigen Daten der Geräteinstanz. Eventuell zusätzlich benötigte Werte können einfach als weitere Internals über den Hash zugänglich gemacht werden.&lt;br /&gt;
&lt;br /&gt;
Beispielsweise könnte man für das Abfragen eines Geräts in der [[#X_Define|Define]]-Funktion den Timer folgendermaßen setzen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
InternalTimer(gettimeofday()+2, &amp;quot;X_GetUpdate&amp;quot;, $hash);	&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternativ kann man auch in der [[#X_Notify|Notify]]-Funktion auf das Event &amp;lt;code&amp;gt;global:INITIALIZED&amp;lt;/code&amp;gt; bzw. &amp;lt;code&amp;gt;global:REREADCFG&amp;lt;/code&amp;gt; reagieren und erst dort, den Timer anstoßen, sobald die Konfiguration komplett eingelesen wurde. Dies ist insbesondere notwendig, wenn man sicherstellen will, dass alle Attribute aus der Konfiguration gesetzt sind, sobald man einen Status-Update initiiert.&lt;br /&gt;
&lt;br /&gt;
In der Funktion &amp;lt;code&amp;gt;X_GetUpdate&amp;lt;/code&amp;gt; selbst wird dann der Timer neu gesetzt, so dass nach einem Intervall die Funktion erneut aufgerufen wird:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_GetUpdate($)&lt;br /&gt;
{&lt;br /&gt;
	my ($hash) = @_;&lt;br /&gt;
	my $name = $hash-&amp;gt;{NAME};&lt;br /&gt;
	Log3 $name, 4, &amp;quot;X: GetUpdate called ...&amp;quot;;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
	&lt;br /&gt;
	# neuen Timer starten in einem konfigurierten Interval.&lt;br /&gt;
	InternalTimer(gettimeofday()+$hash-&amp;gt;{Interval}, &amp;quot;X_GetUpdate&amp;quot;, $hash);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Innerhalb der Funktion kann man nun das Gerät abfragen und die abgefragten Werte in Readings speichern. Falls das Abfragen der Werte jedoch zu einer Verzögerung und damit zu einer Blockade von FHEM führen kann, ist es möglich, in der GetUpdate-Funktion nur die Aufforderung zum Senden bestimmter Daten an das angeschlossene Gerät zu senden und dann das Lesen über die oben beschriebene [[#X_Read|Read]]-Funktion zu implementieren.&lt;br /&gt;
&lt;br /&gt;
Eine genaue Beschreibung der Timer-Funktion gibt es [[DevelopmentModuleAPI#Timer|hier im Wiki]]&lt;br /&gt;
&lt;br /&gt;
== Logging / Debugging ==&lt;br /&gt;
Um Innerhalb eines Moduls eine Log-Meldung in die FHEM-Logdatei zu schreiben, wird die Funktion [[DevelopmentModuleAPI#Log3|Log3()]] aufgerufen.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
Log3 $name, 3, &amp;quot;X ($name) - Problem erkannt ...&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Eine genaue Beschreibung zu der Funktion inkl. Aufrufparameter findet man [[DevelopmentModuleAPI#Log3|hier]]. Es ist generell ratsam in der Logmeldung sowohl den Namen des eigenen Moduls zu schreiben, sowie den Namen des Geräts, welche diese Logmeldung produziert, da die Meldung, so wie sie ist, direkt in das Logfile wandert und es für User ohne diese Informationen schwierig ist, die Meldungen korrekt zuzuordnen.&lt;br /&gt;
&lt;br /&gt;
Die Funktion Log3() verwendet den Namen der Geräteinstanz um das &amp;lt;code&amp;gt;verbose&amp;lt;/code&amp;gt;-Attribut zu prüfen. In der Regel wird bei Modulfunktionen jedoch immer nur der Gerätehash &amp;lt;code&amp;gt;$hash&amp;lt;/code&amp;gt; übergeben. Um den Namen der Definition zu ermitteln ist es daher notwendig sich diesen aus dem Hash extrahieren:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
my $name = $hash-&amp;gt;{NAME};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Um für ein neues Modul das Verbose-Level zu erhöhen, ohne gleich für das Gesamte FHEM alle Meldungen zu erzeugen kann man den Befehl &lt;br /&gt;
&amp;lt;code&amp;gt;attr gerätename verbose&amp;lt;/code&amp;gt; verwenden. Beispielsweise &amp;lt;code&amp;gt;attr PM verbose 5&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Logmeldungen sollten je nach Art und Wichtigkeit für den Nutzer in unterschiedlichen Loglevels erzeugt werden. Es gibt insgesamt 5 Stufen in denen geloggt werden kann. Standardmäßig steht der systemweite Loglevel (&amp;lt;code&amp;gt;global&amp;lt;/code&amp;gt;-Attribut &amp;lt;code&amp;gt;verbose&amp;lt;/code&amp;gt;) auf der Stufe 3. Die Bedeutung der jeweiligen Stufen ist in der [http://fhem.de/commandref_DE.html#verbose commandref] beschrieben.&lt;br /&gt;
&lt;br /&gt;
Während der Entwicklung eines Moduls kann man für eigene Debug-Zwecke auch die Funktion [[DevelopmentModuleAPI#Debug|Debug()]] verwenden um schnell und einfach Debug-Ausgaben in das Log zu schreiben. Diese sollten in der endgültigen Fassung jedoch nicht mehr vorhanden sein. Sie dienen ausschließlich zum Debugging während der Entwicklung.&lt;br /&gt;
&lt;br /&gt;
Eine genaue Beschreibung der Log-Funktion gibt es [[DevelopmentModuleAPI#Logging|hier im Wiki]].&lt;br /&gt;
&lt;br /&gt;
== Zweistufiges Modell für Module ==&lt;br /&gt;
[[Datei:Zweistufiges Modulkonzept.jpg|mini|rechts]]&lt;br /&gt;
Es gibt viele Geräte, welche die Kommunikation mit weiteren Geräten mit tlw. unterschiedlichen Protokollen ermöglichen. Das typischste Beispiel bietet hier der [[CUL]], welcher via Funk mit verschiedenen Protokollen weitere Geräte ansprechen kann (z.B. Aktoren, Sensoren, ...). Hier bildet ein Gerät eine Brücke durch die weitere Geräte in FHEM zugänglich gemacht werden können. Dabei werden über einen Kommunikationsweg (z.B. serielle Schnittstelle, TCP, ...) beliebig viele Geräte gesteuert. Typische Beispiele dazu sind:&lt;br /&gt;
&lt;br /&gt;
* [[CUL]]: stellt Geräte mit verschiedenen Kommunikationsprotokollen via Funk bereit (u.a. [[FS20]], [[HomeMatic]], [[Funk-Heizkörperregler_Kurz-Bedienungsanleitung_FHT|FHT]], [[MAX]], ...)&lt;br /&gt;
* [[HMLAN]]: stellt HomeMatic Geräte via Funk bereit&lt;br /&gt;
* [[MAX#MAXLAN|MAXLAN]]: stellt [[MAX|MAX!]] Geräte via Funk bereit&lt;br /&gt;
* [[PanStamp#panStick.2FShield|panStamp]]: stellt weitere panStamp Geräte via Funk bereit&lt;br /&gt;
&lt;br /&gt;
Dabei wird die Kommunikation in 2 Stufen unterteilt:&lt;br /&gt;
* physisches Modul - z.B. 00_CUL.pm - zuständig für die physikalische Kommunikation mit der Hardware. Empfangene Daten müssen einem logischen Modul zugeordnet werden.&lt;br /&gt;
* logische Modul(e) - z.B. 10_FS20.pm - interpretiert protokollspezifische Nachrichten. Sendet protokollspezifische Daten über das physische Modul an die Hardware.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;physisches Modul&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das physische Modul öffnet die Datenverbindung zum Gerät (z.B. CUL) und verarbeitet sämtliche Daten. Es kümmert sich um den Erhalt der Verbindung (bsp. durch Keep-Alives) und konfiguriert das Gerät so, dass eine Kommunikation mit allen weiteren Geräten möglich ist (bsp. Frequenz, Modulation, Kanal, etc.).&lt;br /&gt;
&lt;br /&gt;
Empfangene Nutzdaten werden über die Funktion [[DevelopmentModuleAPI#Dispatch|Dispatch()]] an logische Module weitergegeben.&lt;br /&gt;
&lt;br /&gt;
Das Modul stellt eine [[#Die_Match-Liste|Match-Liste]] bereit, anhand FHEM die Nachricht einem Modul zuordnen kann, sofern dieses noch nicht geladen sein sollte. FHEM lädt dann automatisch dieses Modul nach, zwecks Verarbeitung der Nachricht. Anhand einer bereitgestellten [[#Die_Client-Liste|Client-Liste]] kann FHEM feststellen, welche logischen Module mit diesem Modul kommunizieren können.&lt;br /&gt;
&lt;br /&gt;
Das Modul stellt eine [[#X_Write|Write]]-Funktion zur Verfügung, über die logische Module Daten an die Hardware übertragen können. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;logisches Modul&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das logische Modul interpretiert die Nachricht über eine bereitgestellte [[#X_Parse|Parse]]-Funktion und erzeugt entsprechende Readings/Events. Es stellt über &amp;lt;code&amp;gt;set&amp;lt;/code&amp;gt;-/&amp;lt;code&amp;gt;get&amp;lt;/code&amp;gt;-Kommandos Steuerungsmöglichkeiten dem Nutzer zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
Es stellt FHEM einen [[#Der_Match-Ausdruck|Match-Ausdruck]] zur Verfügung anhand FHEM ermitteln kann, ob die Nachricht durch das logische Modul verarbeitet werden kann.&lt;br /&gt;
&lt;br /&gt;
=== Die Client-Liste ===&lt;br /&gt;
&lt;br /&gt;
Die Client-Liste ist eine Auflistung von Modulnamen (genauer: regulären Ausdrücken die auf Modulnamen passen) die in einem physischen Modul gesetzt ist. Damit wird definiert, mit welche logischen Modulen das physikalische Modul  kommunizieren kann. &lt;br /&gt;
&lt;br /&gt;
Eine Client-Liste ist eine Zeichenkette, welche aus allen logischen Modulnamen besteht. Die einzelnen Namen werden durch einen Doppelpunkt getrennt. Anstatt kompletter Modulnamen können auch reguläre Ausdrücke verwendet werden, die auf mehrere Modulnamen passen.&lt;br /&gt;
&lt;br /&gt;
Bsp.: Die Client-Liste von dem Modul CUL lautet daher wie folgt:&lt;br /&gt;
&lt;br /&gt;
 FS20:FHT.*:KS300:USF1000:BS:HMS:CUL_EM:CUL_WS:CUL_FHTTK:CUL_HOERMANN:ESA2000:CUL_IR:CUL_TX:Revolt:IT:UNIRoll:SOMFY:STACKABLE_CC:CUL_RFR:CUL_TCM97001:CUL_REDIRECT&lt;br /&gt;
&lt;br /&gt;
Alle hier aufgelisteten Module können über das Modul CUL Daten empfangen bzw. senden.&lt;br /&gt;
&lt;br /&gt;
Die Client-Liste hat generell folgende Funktion:&lt;br /&gt;
* Die Funktion [[DevelopmentModuleAPI#Dispatch|Dispatch()]] prüft nur Module, welche in der Client-Liste enthalten sind, ob diese die Nachricht verarbeiten können.&lt;br /&gt;
* Die Funktion [[DevelopmentModuleAPI#AssignIoPort|AssignIoPort()]] prüft anhand sämtlicher Client-Listen in FHEM, welches IO-Gerät für ein logisches Gerät nutzbar ist.&lt;br /&gt;
&lt;br /&gt;
Üblicherweise wird die Client-Liste in der [[#X_Initialize|Initialize]]-Funktion im Modul-Hash gesetzt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Initialize($)&lt;br /&gt;
{&lt;br /&gt;
	my ($hash) = @_;&lt;br /&gt;
	...&lt;br /&gt;
	$hash-&amp;gt;{Clients} = &amp;quot;FS20:KS300:FHT.*&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man kann die Client-Liste jedoch auch pro physikalisches Gerät setzen. Eine gesetzte Client-Liste in einem Gerät hat immer Vorrang vor der Liste im Modul-Hash. Eine gerätespezifische Client-Liste wird dann verwendet, wenn bspw. ein Gerät je nach Konfiguration nur bestimmte logische Module bedienen kann. Bspw. kann ein CUL je nach RF-Einstellungen FS20, uvm. oder nur HomeMatic bedienen. In einem solchen Fall wird die Client-Liste im Geräte-Hash gesetzt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Define($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $def ) = @_;&lt;br /&gt;
	...&lt;br /&gt;
	$hash-&amp;gt;{Clients} = &amp;quot;CUL_HM&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In vielen Modulen, welche nach dem zweistufigem Konzept arbeiten, beginnt und endet die Client-Liste mit einem Doppelpunkt. Dies ist ein historisches Überbleibsel, da der Prüfmechanismus die Client-Liste früher auf das Vorhandensein von &amp;lt;code&amp;gt;&#039;&#039;&#039;&amp;lt;u&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;:&amp;lt;/font&amp;gt;&amp;lt;/u&amp;gt;&#039;&#039;&#039;&amp;amp;lt;Modulname&amp;amp;gt;&#039;&#039;&#039;&amp;lt;u&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;:&amp;lt;/font&amp;gt;&amp;lt;/u&amp;gt;&#039;&#039;&#039;&amp;lt;/code&amp;gt; prüfte. Dies ist nun nicht mehr notwendig. Die einzelnen Modulnamen müssen lediglich durch einen Doppelpunkt getrennt werden.&lt;br /&gt;
&lt;br /&gt;
=== Die Match-Liste ===&lt;br /&gt;
{{Randnotiz|RNTyp=Info|RNText=&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&amp;lt;u&amp;gt;&#039;&#039;&#039;ACHTUNG&#039;&#039;&#039;:&amp;lt;/u&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
Sämtliche regulären Ausdrücke in der Match-Liste werden &amp;quot;case insensitive&amp;quot; überprüft. Das bedeutet, dass Groß-/Kleinschreibung nicht berücksichtigt wird.&lt;br /&gt;
&lt;br /&gt;
Um dennoch in einem regulären Ausdruck auf Groß-/Kleinschreibung zu prüfen, kann man dieses mit dem Modifizierer &amp;lt;code&amp;gt;(?-i)&amp;lt;/code&amp;gt; wieder aktivieren:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
my %matchListFHEMduino = (&lt;br /&gt;
    ....&lt;br /&gt;
    &amp;quot;5:FHEMduino_PT2262&amp;quot;   =&amp;gt; &amp;quot;^(?-i)IR.*\$&amp;quot;,&lt;br /&gt;
    ....&lt;br /&gt;
    &amp;quot;13:IT&amp;quot;                =&amp;gt; &amp;quot;^(?-i)i......\$&amp;quot;,&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Siehe dazu Forumsbeitrag: {{Link2Forum|Topic=33422}}&lt;br /&gt;
}}&lt;br /&gt;
Die Match-Liste ordnet eine Nachrichtensyntax (regulärer Ausdruck) einem Modulnamen zu und wird in einem physikalischen Modul gesetzt. Sollte eine Nachricht vom physikalischen Gerät empfangen werden, die durch kein geladenes Modul verarbeitet werden kann, so wird über die Match-Liste geprüft, welches Modul diese Nachricht verarbeiten kann. Dieses Modul wird anschließend geladen und die Nachricht durch dieses verarbeitet. In dieser Liste findet mittels regulärem Ausdruck eine Zuordnung der Nachrichtenstruktur zum verarbeitenden logischen Modul statt.&lt;br /&gt;
&lt;br /&gt;
Diese Liste wird ausschließlich in der [[DevelopmentModuleAPI#Dispatch|Dispatch()]]-Funktion verwendet. Sollte keine passendes Modul, welches bereits geladen ist, zur Verarbeitung einer Nachricht gefunden werden, so wird mithilfe der Match-Liste aufgrund der vorliegenden Nachricht das entsprechende Modul ermittelt. Dieses Modul wird dann direkt geladen und die Nachricht wird via [[#X_Parse|Parse]]-Funktion verarbeitet.&lt;br /&gt;
&lt;br /&gt;
Die Match-Liste ist eine Zuordnung von einem Sortierpräfix + Modulname zu einem regulären Ausdruck:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;1:FS20&amp;quot;  =&amp;gt; &amp;quot;^81..(04|0c)..0101a001&amp;quot;,&lt;br /&gt;
    &amp;quot;2:KS300&amp;quot; =&amp;gt; &amp;quot;^810d04..4027a001&amp;quot;,&lt;br /&gt;
    &amp;quot;3:FHT&amp;quot;   =&amp;gt; &amp;quot;^81..(04|09|0d)..(0909a001|83098301|c409c401)..&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Sortierpräfix dient als Sortierhilfe um so die Reihenfolge der Prüfung festzulegen. Bei der Prüfung wird der Hash mittels sort() sortiert und die regulären Ausdrücke werden dann nacheinander getestet. Daher sollten die präzisesten Ausdrücke immer zuerst getestet werden, sofern es weniger präzise Ausdrücke in der Match-Liste gibt. Dabei ist zu beachten, dass der Sortierpräfix nicht nach numerischen Regeln sortiert wird, sondern basierend auf der Zeichenreihenfolge.&lt;br /&gt;
&lt;br /&gt;
Üblicherweise wird die Match-Liste in der [[#X_Initialize|Initialize]]-Funktion im Modul-Hash gesetzt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Initialize($)&lt;br /&gt;
{&lt;br /&gt;
	my ($hash) = @_;&lt;br /&gt;
&lt;br /&gt;
	...&lt;br /&gt;
&lt;br /&gt;
	$hash-&amp;gt;{MatchList} = { &amp;quot;1:FS20&amp;quot;      =&amp;gt; &amp;quot;^81..(04|0c)..0101a001&amp;quot;,&lt;br /&gt;
			       &amp;quot;2:KS300&amp;quot;     =&amp;gt; &amp;quot;^810d04..4027a001&amp;quot;,&lt;br /&gt;
			       &amp;quot;3:FHT&amp;quot;       =&amp;gt; &amp;quot;^81..(04|09|0d)..(0909a001|83098301|c409c401)..&amp;quot; };&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man kann die Match-Liste, ähnlich wie bei der Client-Liste, auch pro physikalisches Gerät setzen. Dabei hat auch hier die Match-Liste eines Gerätes immer Vorrang vor der Match-Liste aus dem Modul-Hash:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Define($$)&lt;br /&gt;
{&lt;br /&gt;
	my ($hash, $def) = @_;&lt;br /&gt;
&lt;br /&gt;
	...&lt;br /&gt;
&lt;br /&gt;
	$hash-&amp;gt;{MatchList} = { &amp;quot;1:CUL_HM&amp;quot; =&amp;gt; &amp;quot;^A....................&amp;quot; };&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Der Match-Ausdruck ===&lt;br /&gt;
&lt;br /&gt;
Ein Match-Ausdruck wird in einem logischen Modul gesetzt und dient der Prüfung, ob eine Nachricht durch das eigene Modul via [[#X_Parse|Parse]]-Funktion verarbeitet werden kann. Es handelt sich hierbei um einen einzelnen regulären Ausdruck, den FHEM innerhalb der [[DevelopmentModuleAPI#Dispatch|Dispatch()]]-Funktion prüft. Nur wenn eine Nachricht via Dispatch() auf diesen Audruck matcht, wird die Parse-Funktion aufgerufen um die Nachricht zu verarbeiten. &lt;br /&gt;
&lt;br /&gt;
Der Hintergrund, warum man den Aufruf mit einem solchen Ausdruck vorher abprüft, liegt in der Möglichkeit, dass ein physikalisches Modul mehrere unterschiedliche logische Module ansprechen kann. So kann FHEM jedes geladene Modul durch diesen Match-Ausdruck prüfen, ob es diese Nachricht verarbeiten kann. Erst, wenn alle geladenen Module, aufgrund einer Prüfung des Ausdrucks, die Nachricht nicht verarbeiten können, wird via [[#Die_Match-Liste|Match-Liste]] ermittelt, welches Modul geladen werden muss um die Nachricht zu verarbeiten. &lt;br /&gt;
&lt;br /&gt;
Der Match-Ausdruck wird in der [[#X_Initialize|Initialize]]-Funktion zur Verfügung gestellt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Initialize($)&lt;br /&gt;
{&lt;br /&gt;
	my ($hash) = @_;&lt;br /&gt;
&lt;br /&gt;
	...&lt;br /&gt;
	&lt;br /&gt;
	# Dieses Modul verarbeitet FS20 Nachrichten&lt;br /&gt;
	$hash-&amp;gt;{Match} = &amp;quot;^81..(04|0c)..0101a001&amp;quot;; &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Die vollständige Implementierung ===&lt;br /&gt;
&lt;br /&gt;
Hier nun eine Zusammenfassung beim zweistufigen Modulkonzept in der jeweiligen Stufe implementiert werden muss, damit die Kommunikation funktioniert.&lt;br /&gt;
&lt;br /&gt;
==== physisches Modul ====&lt;br /&gt;
&lt;br /&gt;
Das physische Modul, welches als Kommunikationsbrücke zwischen der Hardware und logischen Modulen fungieren wird, sollte mindestens folgende Funktionen implementieren:&lt;br /&gt;
&lt;br /&gt;
* [[#X_Initialize|Initialize]]-Funktion - Zum Registrieren des Moduls in FHEM.&lt;br /&gt;
* [[#X_Define|Define]]-Funktion - Zum öffnen der Datenverbindung zur Hardware (IP-Adresse/serielle Schnittstelle/...).&lt;br /&gt;
* [[#X_Read|Read]]-Funktion - Zum Lesen von Daten, welche die Hardware übermittelt.&lt;br /&gt;
* [[#X_Read|Ready]]-Funktion - Zum Wiederaufbau der Verbindung bei Verbindungsabbruch, bzw. Prüfung auf lesbare Daten bei serieller Schnittstelle unter Windows.&lt;br /&gt;
* [[#X_Write|Write]]-Funktion - Zum Senden von Daten, welche logische Module via [[DevelopmentModuleAPI#IOWrite|IOWrite()]] an die Hardware übertragen möchten.&lt;br /&gt;
* [[#X_Undef|Undef]]-Funktion - Schließen der Verbindung zur Hardware beim Löschen via &amp;lt;code&amp;gt;delete&amp;lt;/code&amp;gt; bzw. &amp;lt;code&amp;gt;rereadcfg&amp;lt;/code&amp;gt;.&lt;br /&gt;
* [[#X_Shutdown|Shutdown]]-Funktion - Schließen der Verbindung zur Hardware beim Stopp von FHEM via &amp;lt;code&amp;gt;shutdown&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Desweiteren müssen in der [[#X_Initialize|Initialize]]-Funktion folgende Daten bereitgestellt werden:&lt;br /&gt;
&lt;br /&gt;
* [[#Die_Client-Liste|Client-Liste]] - Auflistung aller logischen Module, die über dieses Modul kommunizieren können&lt;br /&gt;
* [[#Die_Match-Liste|Match-Liste]] - Zuordnung von Nachrichtensyntax zu Modul zwecks Autoload-Funktionalität.&lt;br /&gt;
&lt;br /&gt;
==== logisches Modul ====&lt;br /&gt;
&lt;br /&gt;
Das logische Modul, bildet ein einzelnes Gerät ab, über das mit einem physikalisches Modul kommuniziert werden kann. Es sollte mindestens folgende Funktionen implementieren:&lt;br /&gt;
&lt;br /&gt;
* [[#X_Initialize|Initialize]]-Funktion - Zum Registrieren des Moduls in FHEM.&lt;br /&gt;
* [[#X_Define|Define]]-Funktion - Speichern des Definition Pointers (siehe [[#X_Parse|Parse-Funktion]])&lt;br /&gt;
* [[#X_Parse|Parse]]-Funktion - Zum Lesen von Daten, welche die Hardware übermittelt.&lt;br /&gt;
* [[#X_Undef|Undef]]-Funktion - Löschen des Definition Pointers beim Löschen via &amp;lt;code&amp;gt;delete&amp;lt;/code&amp;gt; bzw. &amp;lt;code&amp;gt;rereadcfg&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Desweiteren müssen in der [[#X_Initialize|Initialize]]-Funktion folgende Daten bereitgestellt werden:&lt;br /&gt;
&lt;br /&gt;
* [[#Der_Match-Ausdruck|Match-Ausdruck]] - Prüfausdruck, ob eine Nachricht durch dieses Modul verarbeitet werden kann.&lt;br /&gt;
&lt;br /&gt;
=== Kommunikation von der Hardware bis zu den logischen Modulen ===&lt;br /&gt;
&lt;br /&gt;
Die Gerätedefinition eines physische Moduls öffnet eine Verbindung zur Hardware. Die [[#X_Read|Read]]-Funktion wird bei anstehenden Daten aus der Hauptschleife von fhem.pl aufgerufen.&lt;br /&gt;
&lt;br /&gt;
Die Read-Funktion stellt dabei sicher, dass die Daten&lt;br /&gt;
* komplett (in der Regel über einen internen Puffer in &amp;lt;code&amp;gt;$hash&amp;lt;/code&amp;gt;) und&lt;br /&gt;
* korrekt (z.B. via Prüfung mittels regulärem Ausdruck)&lt;br /&gt;
sind und ruft die globale Funktion [[DevelopmentModuleAPI#Dispatch|Dispatch()]] mit einer kompletten Nachricht auf.&lt;br /&gt;
&lt;br /&gt;
Die Funktion Dispatch() sucht nach einer passenden Definition via [[#Die_Client-Liste|Client-Liste]] in physischen Definitionen/Modulen nach möglichen logischen Modulen zur Verarbeitung. Alle zum Zeitpunkt geladenen Module, die in der Client-Liste aufgeführt sind, werden über den [[#Der_Match-Ausdruck|Match-Ausdruck]] geprüft, ob sie mit der Nachricht etwas anfangen können. Sollte bei einem Modul der Match-Ausdruck passen, so wird die entsprechende [[#X_Parse|Parse]]-Funktion des logischen Moduls aufgerufen. Sofern keine passendes Modul gefunden wurde, um die Nachricht zu verarbeiten, wird in der [[#Die_Match-Liste|Match-Liste]] im Geräte- bzw. Modul-Hash der physischen Gerätedefinition nach dem passenden Modul gesucht. Sollte es darin ein Modul geben, was diese Art von Nachricht verarbeiten kann, so wird versucht dieses Modul zu laden um nun die Nachricht via Parse-Funktion zu verarbeiten. Es erfolgt in diesem Fall keine Vorprüfung durch den Match-Ausdruck.&lt;br /&gt;
&lt;br /&gt;
Durch Dispatch() wird nun die [[#X_Parse|Parse]]-Funktion des gefundenen logischen Moduls aufgerufen. Diese&lt;br /&gt;
* interpretiert die übergebene Nachricht,&lt;br /&gt;
* versucht eine existierende Gerätedefinition in FHEM zu finden (z.B. mittels Definition Pointer), für welche die Nachricht addressiert ist,&lt;br /&gt;
* setzt alle [[#Readings|Readings]] für die gefundene Gerätedefinition via [[DevelopmentModuleAPI#Readings_.2F_Events|readings*update]]()-Funktionen,&lt;br /&gt;
* gibt den Namen der logischen Definition zurück, welche die Nachricht verarbeitet hat.&lt;br /&gt;
&lt;br /&gt;
Sollte keine passende Gerätedefinition für die entsprechende Nachricht existieren (Adresse/ID/Kanal/...), wird der Gerätename &amp;quot;UNDEFINED&amp;quot; inkl. einem passenden &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt;-Statement zurückgegeben, um die Definition durch [[autocreate]] erzeugen zu lassen.&lt;br /&gt;
&lt;br /&gt;
Es findet während der Verarbeitung einer Nachricht durch Dispatch()/Parse-Funktion keine sofortige Eventverarbeitung (via [[DevelopmentModuleAPI#Dispatch|DoTrigger()]]) statt, wenn die [[DevelopmentModuleAPI#Readings_.2F_Events|readings*update]]()-Funktionen verwendet werden.&lt;br /&gt;
(Im Gegensatz zum direkten Aufrufen der readings*update Funktionen ohne vorhergehendes Dispatch() )&lt;br /&gt;
&lt;br /&gt;
Die Funktion Dispatch() triggert das Event-Handling für das von der Parse-Funktion zurückgegebene logische Device selbstständig.&lt;br /&gt;
&lt;br /&gt;
Optional führt die Funktion Dispatch() eine Überprüfung auf Nachrichtenduplikate beim Einsatz von mehreren IO-Geräten durch. Dazu wird eine implementierte [[#X_Fingerprint|Fingerprint]]-Funktion im physischen oder logischen Modul benötigt.&lt;br /&gt;
&lt;br /&gt;
=== Kommunikation von den logischen Modulen bis zur Hardware ===&lt;br /&gt;
&lt;br /&gt;
Um von einem logischen Modul eine Nachricht an die Hardware senden zu können, muss zunächst im logischen Gerät ein passenden IO-Gerät ausgewählt sein. Dazu muss die Funktion [[DevelopmentModuleAPI#AssignIoPort|AssignIoPort()]] ein entsprechendes IO-Gerät auswählen und in &amp;lt;code&amp;gt;$hash-&amp;gt;{IODev}&amp;lt;/code&amp;gt; setzen. Dieser Aufruf wird üblicherweise in der [[#X_Define|Define]]-Funktion des logischen Moduls ausgeführt. Erst, wenn ein IO-Gerät ausgewählt wurde, können Daten über das physikalische Gerät an die Hardware übermittelt werden.&lt;br /&gt;
&lt;br /&gt;
Zum Senden von Daten ruft das logische Modul die Funktion [[DevelopmentModuleAPI#IOWrite|IOWrite()]] samt Daten auf. Diese ruft für das entsprechende IO-Gerät die [[#X_Write|Write]]-Funktion auf und übergibt die Daten zum Schreiben an das physikalische Modul. Die Write-Funktion kümmert sich nun um die Übertragung der Daten an die Hardware. &lt;br /&gt;
&lt;br /&gt;
Keine direkten Zugriffe zwischen dem logischen und dem physischen Gerät gibt (d.h. keine direkten Aufrufe von Funktionen, kein direktes Überprüfen von &amp;lt;code&amp;gt;$hash&amp;lt;/code&amp;gt;-Inhalten, ...), so können die Module hintereinander geschaltet werden (z.B. für Routerfunktionen wie bei der [[RFR_CUL|RFR]]-Funktionalität) oder mittels [[FHEM2FHEM]] im RAW-Modus zwei FHEM-Installationen verbunden werden und die logischen Geräte können dennoch kommunizieren.&lt;br /&gt;
&lt;br /&gt;
=== Automatisches Anlegen von logischen Gerätedefinitionen (autocreate) ===&lt;br /&gt;
&lt;br /&gt;
Das logische Modul kann im Rahmen der [[#X_Parse|Parse]]-Funktion eine neue Gerätedefinition anlegen, sofern eine passende Definition nicht existieren sollte. Die Parse-Funktion gibt generell den Namen der logischen Gerätedefinition zurück, für welche die Nachricht verarbeitet wurde. Sollte keine passende Definition gefunden werden, so muss die Parse-Funktion folgenden Rückgabewert liefern (zusammenhängende Zeichenkette):&lt;br /&gt;
&lt;br /&gt;
 UNDEFINED &#039;&#039;&amp;amp;lt;Namensvorschlag&amp;amp;gt;&#039;&#039; &#039;&#039;&amp;amp;lt;Modulname&amp;amp;gt;&#039;&#039; &#039;&#039;&amp;amp;lt;Define-Parameter&amp;amp;gt;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Sollte also bspw. im Rahmen der Parse-Funktion zu Modul X eine Nachricht nicht einer existierenden Gerätedefinition zugeordnet werden können, so muss ein Namensvorschlag erstellt werden der eine eindeutige Komponente wie bspw. eine Adresse/ID/Kanal-Nr enthält. In der Regel wird hier immer der Modulname zusammen mit der eindeutigen Komponente, durch einen Unterstrich getrennt, verwendet (Bsp: &amp;lt;code&amp;gt;X_4834&amp;lt;/code&amp;gt;). Der Modulname ist in der Regel immer der, des eigenen Moduls. In besonderen Fällen kann man hier auch einen abweichenden Modulnamen angeben. Dies wird bspw. bei den [[PanStamp#FHEM-Module.2FDevice_Definition_Files|SWAP-Modulen]] eingesetzt. Als Define-Parameter müssen alle notwendigen Parameter angegeben werden, die beim Aufruf des &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt;-Befehls notwendig sind, damit eine neu angelegte Gerätedefinition Nachrichten zu dieser eindeutigen Adresse Daten verarbeitet. Dazu muss mind. die eindeutige Adresse mitgegeben werden.&lt;br /&gt;
&lt;br /&gt;
Beispiel für FS20:&lt;br /&gt;
&lt;br /&gt;
 UNDEFINED FS20_0ae42f8 FS20 0ae42 f8&lt;br /&gt;
&lt;br /&gt;
Sobald [[DevelopmentModuleAPI#Dispatch|Dispatch()]] einen solchen Rückgabewert von einer [[#X_Parse|Parse]]-Funktion erhält, wird diese Zeichenkette so wie sie ist via [[DevelopmentModuleAPI#DoTrigger|DoTrigger()]] als Event für die Definition &amp;lt;code&amp;gt;global&amp;lt;/code&amp;gt; getriggert.&lt;br /&gt;
&lt;br /&gt;
Sofern der Nutzer das Modul [[autocreate]] verwendet (definiert hat), kümmert sich dieses nun um das Anlegen einer entsprechenden Gerätedefinition. Es lauscht dabei auf generierte Events der Definition &amp;lt;code&amp;gt;global&amp;lt;/code&amp;gt; via [[#X_Notify|Notify]]-Funktion. Der Nutzer kann dabei das Verhalten von autocreate durch entsprechende Parameter beeinflussen.&lt;br /&gt;
&lt;br /&gt;
Das Modul, für welches autocreate eine neue Definition anlegen möchte, kann das Verhalten durch entsprechende Parameter im Modul-Hash beeinflussen. Dabei gilt, dass gesetzte Attribute durch den Nutzer generell Vorrang haben. Die entsprechenden Parameter werden dabei im Rahmen der [[#X_Initialize|Initialize]]-Funktion im Modul-Hash gesetzt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Initialize($)&lt;br /&gt;
{&lt;br /&gt;
	my ($hash) = @_;&lt;br /&gt;
 &lt;br /&gt;
	...&lt;br /&gt;
 &lt;br /&gt;
	$hash-&amp;gt;{AutoCreate} = {&amp;quot;X_.*&amp;quot;  =&amp;gt; { ATTR   =&amp;gt; &amp;quot;event-on-change-reading:.* event-min-interval:.*:300&amp;quot;,&lt;br /&gt;
	                                    FILTER =&amp;gt; &amp;quot;%NAME&amp;quot;,&lt;br /&gt;
	                                    GPLOT  =&amp;gt; &amp;quot;temp4hum4:Temp/Hum,&amp;quot;,&lt;br /&gt;
	                                    autocreateThreshold =&amp;gt; &amp;quot;2:140&amp;quot;&lt;br /&gt;
					  }&lt;br /&gt;
	                      };&lt;br /&gt;
			    &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hierbei wird unterhalb von &amp;lt;code&amp;gt;$hash-&amp;gt;{AutoCreate}&amp;lt;/code&amp;gt; eine Liste angelegt, wo einem regulären Ausdruck für einen anzulegenden Definitionsnamen entsprechende Optionen zugeordnet werden. Sobald durch autocreate eine Gerätedefintion angelegt wird, auf den ein hier gelisteter Ausdruck matcht, so werden die zugeordneten Optionen berücksichtigt.&lt;br /&gt;
&lt;br /&gt;
Hier eine Auflistung aller möglichen Optionen und ihrer Bedeutung:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Optionsname !! Beispiel !! Bedeutung&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ATTR&amp;lt;/code&amp;gt;|| &amp;lt;code&amp;gt;&amp;quot;event-on-change-reading:.* event-min-interval:.*:300&amp;quot;&amp;lt;/code&amp;gt; || Eine Auflistung von Attributen, die nach dem Anlegen einer Definition zusätzlich gesetzt werden. Es handelt sich hierbei um eine Leerzeichen-separierte Liste von Doppelpunkt-getrennten Tupels mit Attributname und -wert.&lt;br /&gt;
&lt;br /&gt;
Für das dargestellte Beispiel bedeutet dies, dass nach dem Anlegen der Definition folgende FHEM-Befehle zusätzlich ausgeführt werden:&lt;br /&gt;
&lt;br /&gt;
 attr &#039;&#039;&amp;amp;lt;Name&amp;amp;gt;&#039;&#039; event-on-change-reading .*&lt;br /&gt;
 attr &#039;&#039;&amp;amp;lt;Name&amp;amp;gt;&#039;&#039; event-min-interval .*:300&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FILTER&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;%NAME&amp;lt;/code&amp;gt;|| Sofern in der autocreate-Definiton das Attribut &amp;lt;code&amp;gt;filelog&amp;lt;/code&amp;gt; entsprechend durch den Nutzer gesetzt ist, wird eine zugehörige FileLog-Definition angelegt. Diese Option setzt den dabei benutzten Filter-Regexp, der beim Anlegen der FileLog-Definition gesetzt wird. &lt;br /&gt;
&lt;br /&gt;
Dabei werden folgende Platzhalter durch die entsprechenden Werte der neu angelegten Gerätedefinition ersetzt:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;%NAME&amp;lt;/code&amp;gt; - wird ersetzt durch den Definitionsnamen&lt;br /&gt;
* &amp;lt;code&amp;gt;%TYPE&amp;lt;/code&amp;gt; - wird ersetzt durch den Modulnamen&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;GPLOT&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;temp4hum4:Temp/Hum,&amp;quot;&amp;lt;/code&amp;gt; || Sofern eine FileLog-Definition angelegt wurde, kann man weiterführend dazu eine passende SVG-Definition erzeugen um Daten aus dem erzeugten FileLog zu visualisieren. Ein typischer Fall sind hierbei Temperatursensoren, wo es sinnvoll sein kann, einen passenden SVG-Plot mit Temperatur/Luftfeuchtigkeit direkt anzulegen.&lt;br /&gt;
&lt;br /&gt;
Es handelt sich hierbei um eine kommaseparierte Auflistung von gplot-Dateinamen und optionalen Label-Texten durch einen Doppelpunkt getrennt. Im genannten Beispiel entspricht &amp;lt;code&amp;gt;temp4hum4&amp;lt;/code&amp;gt; der zu verwendenden GnuPlot-Datei und &amp;lt;code&amp;gt;Temp/Hum&amp;lt;/code&amp;gt; dem zu verwendenden Label ([[SVG]] Attribut &amp;lt;code&amp;gt;label&amp;lt;/code&amp;gt;). Das Label wird auch durch FileLog verwendet als Link-Text zum entsprechenden SVG Plot. Alternativ kann auch nur die entsprechende GnuPlot-Datei anegeben werden ohne Label. Für jede angegebene GnuPlot-Datei wird anschließend eine entsprechende SVG-Definition erzeugt mit der vorher erzeugten FileLog-Definition als Datenquelle.&lt;br /&gt;
&lt;br /&gt;
Der gesamte Inhalt der &amp;lt;code&amp;gt;GPLOT&amp;lt;/code&amp;gt;-Option wird beim Anlegen einer FileLog-Definition dem Attribut &amp;lt;code&amp;gt;logtype&amp;lt;/code&amp;gt; als Wert plus dem Text &amp;lt;code&amp;gt;text&amp;lt;/code&amp;gt; zugewiesen. Daher muss der Inhalt der Option &amp;lt;code&amp;gt;GPLOT&amp;lt;/code&amp;gt; immer mit einem Komma enden. &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;autocreateThreshold&amp;lt;/code&amp;gt;|| &amp;lt;code&amp;gt;&amp;quot;2:10&amp;quot;|| Definiert, wie viele Aufrufe (im Bsp: &amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt;) von autocreate innerhalb welcher Zeit (im Bsp: &amp;lt;code&amp;gt;10&amp;lt;/code&amp;gt; Sek.) stattfinden müssen, bevor die Gerätedefinition tatsächlich durch autocreate angelegt wird. Dadurch kann das ungewollte Anlegen von Geräten verhindert werden die tatsächlich nicht in Echt existieren. Aufgrund von Funkstörungen kann es durchaus zum ungewollten Anlegen einer Definition kommen. Diese Funktion lässt eine Definition erst zu wenn innerhalb einer vorgegeben Zeit eine Mindestzahl an Nachrichten eintrifft.&lt;br /&gt;
&lt;br /&gt;
Die erste Zahl stellt dabei die Mindestanzahl an Nachrichten dar. Die Zweite Zahl stellt die Zeit in Sekunden dar, in der die Mindestanzahl an Nachrichten erreicht werden muss um eine entsprechende Gerätedefinition anzulegen. &lt;br /&gt;
&lt;br /&gt;
Sofern diese Option nicht gesetzt ist, wird standardmäßig &amp;lt;code&amp;gt;2:60&amp;lt;/code&amp;gt; verwendet.&lt;br /&gt;
&lt;br /&gt;
Diese Option kann durch den Anwender über das Attribut &amp;lt;code&amp;gt;autocreateThreshold&amp;lt;/code&amp;gt; übersteuert werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sofern diese Option nicht gesetzt ist&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;noAutocreatedFilelog&amp;lt;/code&amp;gt;|| &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;|| Flag. Sofern gesetzt, wird keine FileLog- und ggf. SVG-Definition erzeugt. Selbst wenn der Nutzer durch entsprechende Attribute das Anlegen wünscht. Diese Option ist sinnvoll für Module bzw. Geräte die keine Readings erzeugen.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Ergänzende Hinweise ==&lt;br /&gt;
Die Wahl der vorangestellten Nummer für den Dateinamen eines neuen Moduls hat keine Bedeutung mehr, es sei denn die Nummer ist 99. Module, die mit 99_ beginnen, werden von FHEM automatisch geladen. Module mit einer anderen Nummer nur wenn ein &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt;-Befehl dafür sorgt, dass das Modul geladen wird.&lt;br /&gt;
&lt;br /&gt;
Wenn ein Modul Initialisierungsdaten benötigt, sollten diese im Modul selbst enthalten sein. Eine zusätzliche Datei oder sogar ein Unterverzeichnis mit mehreren Dateien ist bei FHEM nicht üblich und sollte bei Modulen, die mit FHEM ausgeliefert werden nur in Rücksprache mit Rudolf König angelegt werden, da sie sonst bei einem Update nicht verteilt werden.&lt;br /&gt;
&lt;br /&gt;
== Weitere Informationen ==&lt;br /&gt;
Wenn man weitere Details wissen möchte, ist ein erster sinnvoller Schritt ein Blick in die Datei fhem.pl. Dort sieht man im Perl-Code wie die Module aufgerufen werden, was vorher passiert und was danach. Am Anfang der Datei (ca. ab Zeile 130) findet man beispielsweise eine Liste der globalen Variablen, die den Modulen zur Verfügung stehen sowie Details zu den wichtigen Hashes %modules und %defs. Wer mit Perl noch nicht so gut klar kommt, dem hilft eventuell ein Blick auf die Perldoc Website[http://perldoc.perl.org/] oder in das Perl-Buch seiner Wahl. Auch die FHEM Commandref [http://fhem.de/commandref.html] sollte nicht unterschätzt werden. Es stehen oft mehr interessante Details auch für Modulentwickler darin als man zunächst vermuten könnte.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== &amp;quot;Hello World&amp;quot; Beispiel ==&lt;br /&gt;
&lt;br /&gt;
98_Hello.pm&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
package main;&lt;br /&gt;
use strict;&lt;br /&gt;
use warnings;&lt;br /&gt;
&lt;br /&gt;
my %Hello_gets = (&lt;br /&gt;
	&amp;quot;whatyouwant&amp;quot;	=&amp;gt; &amp;quot;can&#039;t&amp;quot;,&lt;br /&gt;
	&amp;quot;whatyouneed&amp;quot;	=&amp;gt; &amp;quot;try sometimes&amp;quot;,&lt;br /&gt;
	&amp;quot;satisfaction&amp;quot;  =&amp;gt; &amp;quot;no&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
sub Hello_Initialize($) {&lt;br /&gt;
    my ($hash) = @_;&lt;br /&gt;
&lt;br /&gt;
    $hash-&amp;gt;{DefFn}      = &#039;Hello_Define&#039;;&lt;br /&gt;
    $hash-&amp;gt;{UndefFn}    = &#039;Hello_Undef&#039;;&lt;br /&gt;
    $hash-&amp;gt;{SetFn}      = &#039;Hello_Set&#039;;&lt;br /&gt;
    $hash-&amp;gt;{GetFn}      = &#039;Hello_Get&#039;;&lt;br /&gt;
    $hash-&amp;gt;{AttrFn}     = &#039;Hello_Attr&#039;;&lt;br /&gt;
    $hash-&amp;gt;{ReadFn}     = &#039;Hello_Read&#039;;&lt;br /&gt;
&lt;br /&gt;
    $hash-&amp;gt;{AttrList} =&lt;br /&gt;
          &amp;quot;formal:yes,no &amp;quot;&lt;br /&gt;
        . $readingFnAttributes;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub Hello_Define($$) {&lt;br /&gt;
    my ($hash, $def) = @_;&lt;br /&gt;
    my @param = split(&#039;[ \t]+&#039;, $def);&lt;br /&gt;
    &lt;br /&gt;
    if(int(@param) &amp;lt; 3) {&lt;br /&gt;
        return &amp;quot;too few parameters: define &amp;lt;name&amp;gt; Hello &amp;lt;greet&amp;gt;&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    my $hash-&amp;gt;{name}  = $param[0];&lt;br /&gt;
    my $hash-&amp;gt;{greet} = $param[2];&lt;br /&gt;
    &lt;br /&gt;
    return undef;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub Hello_Undef($$) {&lt;br /&gt;
    my ($hash, $arg) = @_; &lt;br /&gt;
    # nothing to do&lt;br /&gt;
    return undef;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub Hello_Get($@) {&lt;br /&gt;
	my ($hash, @param) = @_;&lt;br /&gt;
	&lt;br /&gt;
	return &#039;&amp;quot;get Hello&amp;quot; needs at least one argument&#039; if (int(@param) &amp;lt; 2);&lt;br /&gt;
	&lt;br /&gt;
	my $name = shift @param;&lt;br /&gt;
	my $opt = shift @param;&lt;br /&gt;
	if(!$Hello_gets{$opt}) {&lt;br /&gt;
		my @cList = keys %Hello_gets;&lt;br /&gt;
		return &amp;quot;Unknown argument $opt, choose one of &amp;quot; . join(&amp;quot; &amp;quot;, @cList);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	if($attr{$name}{formal} eq &#039;yes&#039;) {&lt;br /&gt;
	    return $Hello_gets{$opt}.&#039;, sir&#039;;&lt;br /&gt;
    }&lt;br /&gt;
	return $Hello_gets{$opt};&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub Hello_Set($@) {&lt;br /&gt;
	my ($hash, @param) = @_;&lt;br /&gt;
	&lt;br /&gt;
	return &#039;&amp;quot;set Hello&amp;quot; needs at least one argument&#039; if (int(@param) &amp;lt; 2);&lt;br /&gt;
	&lt;br /&gt;
	my $name = shift @param;&lt;br /&gt;
	my $opt = shift @param;&lt;br /&gt;
	my $value = join(&amp;quot;&amp;quot;, @param);&lt;br /&gt;
	&lt;br /&gt;
	if(!defined($Hello_gets{$opt})) {&lt;br /&gt;
		my @cList = keys %Hello_gets;&lt;br /&gt;
		return &amp;quot;Unknown argument $opt, choose one of &amp;quot; . join(&amp;quot; &amp;quot;, @cList);&lt;br /&gt;
	}&lt;br /&gt;
    $hash-&amp;gt;{STATE} = $Hello_gets{$opt} = $value;&lt;br /&gt;
    &lt;br /&gt;
	return &amp;quot;$opt set to $value. Try to get it.&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
sub Hello_Attr(@) {&lt;br /&gt;
	my ($cmd,$name,$attr_name,$attr_value) = @_;&lt;br /&gt;
	if($cmd eq &amp;quot;set&amp;quot;) {&lt;br /&gt;
        if($attr_name eq &amp;quot;formal&amp;quot;) {&lt;br /&gt;
			if($attr_value !~ /^yes|no$/) {&lt;br /&gt;
			    my $err = &amp;quot;Invalid argument $attr_value to $attr_name. Must be yes or no.&amp;quot;;&lt;br /&gt;
			    Log 3, &amp;quot;Hello: &amp;quot;.$err;&lt;br /&gt;
			    return $err;&lt;br /&gt;
			}&lt;br /&gt;
		} else {&lt;br /&gt;
		    return &amp;quot;Unknown attr $attr_name&amp;quot;;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	return undef;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&lt;br /&gt;
=pod&lt;br /&gt;
=begin html&lt;br /&gt;
&lt;br /&gt;
&amp;lt;a name=&amp;quot;Hello&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Hello&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
    &amp;lt;i&amp;gt;Hello&amp;lt;/i&amp;gt; implements the classical &amp;quot;Hello World&amp;quot; as a starting point for module development. &lt;br /&gt;
    You may want to copy 98_Hello.pm to start implementing a module of your very own. See &lt;br /&gt;
    &amp;lt;a href=&amp;quot;http://wiki.fhem.de/wiki/DevelopmentModuleIntro&amp;quot;&amp;gt;DevelopmentModuleIntro&amp;lt;/a&amp;gt; for an &lt;br /&gt;
    in-depth instruction to your first module.&lt;br /&gt;
    &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
    &amp;lt;a name=&amp;quot;Hellodefine&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
    &amp;lt;b&amp;gt;Define&amp;lt;/b&amp;gt;&lt;br /&gt;
    &amp;lt;ul&amp;gt;&lt;br /&gt;
        &amp;lt;code&amp;gt;define &amp;amp;lt;name&amp;amp;gt; Hello &amp;amp;lt;greet&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
        &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
        Example: &amp;lt;code&amp;gt;define HELLO Hello TurnUrRadioOn&amp;lt;/code&amp;gt;&lt;br /&gt;
        &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
        The &amp;quot;greet&amp;quot; parameter has no further meaning, it just demonstrates&lt;br /&gt;
        how to set a so called &amp;quot;Internal&amp;quot; value. See &amp;lt;a href=&amp;quot;http://fhem.de/commandref.html#define&amp;quot;&amp;gt;commandref#define&amp;lt;/a&amp;gt; &lt;br /&gt;
        for more info about the define command.&lt;br /&gt;
    &amp;lt;/ul&amp;gt;&lt;br /&gt;
    &amp;lt;br&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
    &amp;lt;a name=&amp;quot;Helloset&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
    &amp;lt;b&amp;gt;Set&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
    &amp;lt;ul&amp;gt;&lt;br /&gt;
        &amp;lt;code&amp;gt;set &amp;amp;lt;name&amp;amp;gt; &amp;amp;lt;option&amp;amp;gt; &amp;amp;lt;value&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
        &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
        You can &amp;lt;i&amp;gt;set&amp;lt;/i&amp;gt; any value to any of the following options. They&#039;re just there to &lt;br /&gt;
        &amp;lt;i&amp;gt;get&amp;lt;/i&amp;gt; them. See &amp;lt;a href=&amp;quot;http://fhem.de/commandref.html#set&amp;quot;&amp;gt;commandref#set&amp;lt;/a&amp;gt; &lt;br /&gt;
        for more info about the set command.&lt;br /&gt;
        &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
        Options:&lt;br /&gt;
        &amp;lt;ul&amp;gt;&lt;br /&gt;
              &amp;lt;li&amp;gt;&amp;lt;i&amp;gt;satisfaction&amp;lt;/i&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
                  Defaults to &amp;quot;no&amp;quot;&amp;lt;/li&amp;gt;&lt;br /&gt;
              &amp;lt;li&amp;gt;&amp;lt;i&amp;gt;whatyouwant&amp;lt;/i&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
                  Defaults to &amp;quot;can&#039;t&amp;quot;&amp;lt;/li&amp;gt;&lt;br /&gt;
              &amp;lt;li&amp;gt;&amp;lt;i&amp;gt;whatyouneed&amp;lt;/i&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
                  Defaults to &amp;quot;try sometimes&amp;quot;&amp;lt;/li&amp;gt;&lt;br /&gt;
        &amp;lt;/ul&amp;gt;&lt;br /&gt;
    &amp;lt;/ul&amp;gt;&lt;br /&gt;
    &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;a name=&amp;quot;Helloget&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
    &amp;lt;b&amp;gt;Get&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
    &amp;lt;ul&amp;gt;&lt;br /&gt;
        &amp;lt;code&amp;gt;get &amp;amp;lt;name&amp;amp;gt; &amp;amp;lt;option&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
        &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
        You can &amp;lt;i&amp;gt;get&amp;lt;/i&amp;gt; the value of any of the options described in &lt;br /&gt;
        &amp;lt;a href=&amp;quot;#Helloset&amp;quot;&amp;gt;paragraph &amp;quot;Set&amp;quot; above&amp;lt;/a&amp;gt;. See &lt;br /&gt;
        &amp;lt;a href=&amp;quot;http://fhem.de/commandref.html#get&amp;quot;&amp;gt;commandref#get&amp;lt;/a&amp;gt; for more info about &lt;br /&gt;
        the get command.&lt;br /&gt;
    &amp;lt;/ul&amp;gt;&lt;br /&gt;
    &amp;lt;br&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
    &amp;lt;a name=&amp;quot;Helloattr&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
    &amp;lt;b&amp;gt;Attributes&amp;lt;/b&amp;gt;&lt;br /&gt;
    &amp;lt;ul&amp;gt;&lt;br /&gt;
        &amp;lt;code&amp;gt;attr &amp;amp;lt;name&amp;amp;gt; &amp;amp;lt;attribute&amp;amp;gt; &amp;amp;lt;value&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
        &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
        See &amp;lt;a href=&amp;quot;http://fhem.de/commandref.html#attr&amp;quot;&amp;gt;commandref#attr&amp;lt;/a&amp;gt; for more info about &lt;br /&gt;
        the attr command.&lt;br /&gt;
        &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
        Attributes:&lt;br /&gt;
        &amp;lt;ul&amp;gt;&lt;br /&gt;
            &amp;lt;li&amp;gt;&amp;lt;i&amp;gt;formal&amp;lt;/i&amp;gt; no|yes&amp;lt;br&amp;gt;&lt;br /&gt;
                When you set formal to &amp;quot;yes&amp;quot;, all output of &amp;lt;i&amp;gt;get&amp;lt;/i&amp;gt; will be in a&lt;br /&gt;
                more formal language. Default is &amp;quot;no&amp;quot;.&lt;br /&gt;
            &amp;lt;/li&amp;gt;&lt;br /&gt;
        &amp;lt;/ul&amp;gt;&lt;br /&gt;
    &amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=end html&lt;br /&gt;
&lt;br /&gt;
=cut&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der HTML-Code zwischen den Tags &amp;lt;code&amp;gt;=pod&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;=cut&amp;lt;/code&amp;gt; dient zur Generierung der commandref.html. Der HTML-Inhalt wird automatisch beim Verteilen des Moduls im Rahmen des Update-Mechanismus aus jedem Modul extrahiert und daraus die Commandref in verschiedenen Sprachen erstellt. Eine detaillierte Beschreibung wie ein Commandref-Abschnitt in einem Modul definiert wird, siehe: [[Guidelines zur Dokumentation]]&lt;br /&gt;
&lt;br /&gt;
== Noch zu beschreiben ==&lt;br /&gt;
* DevIO&lt;br /&gt;
* AsyncOutputFn / asyncOutput&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Development]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=DevelopmentModuleIntro&amp;diff=20027</id>
		<title>DevelopmentModuleIntro</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=DevelopmentModuleIntro&amp;diff=20027"/>
		<updated>2017-02-16T19:42:07Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: /* X_Notify */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Dieser Text ist in Arbeit und muss noch an einigen Stellen ergänzt werden. }}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Um neue Geräte, Dienste, o.ä. in FHEM verfügbar zu machen, kann man ein eigenes Modul in Perl schreiben. Ein Modul wird in FHEM automatisch geladen, wenn ein entsprechendes Device in FHEM definiert wird. Das Modul ermöglicht eine spezifische Kommunikation mit einem physikalischen Gerät, stellt Ergebnisse (&amp;quot;Readings&amp;quot;) und Events innerhalb von FHEM zur Verfügung und erlaubt es, das Gerät mit &amp;quot;Set&amp;quot;-/&amp;quot;Get&amp;quot;-Befehlen zu beeinflussen. Dieser Artikel soll den Einstieg in die Entwicklung eigener Module erleichtern.&lt;br /&gt;
&lt;br /&gt;
Mit dem FHEM-Befehl &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt; werden Devices in FHEM basierend auf einem Modul definiert. Dieser Befehl sorgt dafür, dass ein neues Modul bei Bedarf geladen und initialisiert wird. Ein gutes Beispiel ist hierbei die zentrale Konfigurationsdatei &amp;quot;fhem.cfg&amp;quot; in der sämtliche Devices in Form von &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt;-Statements gespeichert sind.&lt;br /&gt;
&lt;br /&gt;
Damit das funktioniert müssen der Name des Moduls und der Name der [[#X_Initialize|Initialisierungsfunktion]]  identisch sein. Das folgende Beispiel soll dies verdeutlichen:&lt;br /&gt;
&lt;br /&gt;
Ein Jeelink USB-Stick könnte beispielsweise mit dem Befehl &amp;lt;code&amp;gt;define JeeLink1 &#039;&#039;JeeLink&#039;&#039; /dev/ttyUSB0@57600&amp;lt;/code&amp;gt; definiert werden.&lt;br /&gt;
&lt;br /&gt;
In fhem.pl wird der define-Befehl verarbeitet und geprüft, ob ein Modul mit dem Namen &amp;quot;JeeLink&amp;quot; schon geladen ist und falls nicht ein Modul mit Namen XY_JeeLink.pm im Modulverzeichnis (z.B. /opt/fhem/FHEM) gesucht und dann geladen. &lt;br /&gt;
Danach wird die Funktion &amp;lt;code&amp;gt;&#039;&#039;JeeLink&#039;&#039;_Initialize()&amp;lt;/code&amp;gt; aufgerufen um das Modul in FHEM zu registrieren. Eine Moduldatei muss dazu eine Funktion &amp;lt;code&amp;gt;&#039;&#039;&amp;amp;lt;Modulname&amp;amp;gt;&#039;&#039;_Initialize()&amp;lt;/code&amp;gt; enthalten. Durch den Aufruf dieser Funktion wird FHEM mitgeteilt, welche Funktionalitäten dieses Modul unterstützt.&lt;br /&gt;
&lt;br /&gt;
In der Initialisierungsfunktion des Moduls werden die Namen aller weiteren Perl-Funktionen des Moduls, die von fhem.pl aus aufgerufen werden, bekannt gemacht. Dazu wird für jedes Modul ein eigener Hash (genauer &amp;quot;Modul-Hash&amp;quot;) mit entsprechenden Werten gefüllt, der in fhem.pl für jedes Modul entsprechend abgelegt wird. Dadurch weiß FHEM wie dieses Modul anzusprechen ist.&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau eines Moduls ==&lt;br /&gt;
&lt;br /&gt;
=== Dateiname ===&lt;br /&gt;
&lt;br /&gt;
Ein FHEM-Modul wird als Perl-Modul mit der Dateiendung *.pm abgespeichert. Der Dateiname folgt dabei folgendem Schema:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;&#039;&#039;[&#039;&#039;&#039;Schlüsselnummer&#039;&#039;&#039;]&#039;&#039;&amp;lt;font color=&amp;quot;grey&amp;quot;&amp;gt;_&amp;lt;/font&amp;gt;&#039;&#039;[&#039;&#039;&#039;Modulname&#039;&#039;&#039;]&#039;&#039;&amp;lt;font color=&amp;quot;grey&amp;quot;&amp;gt;.pm&amp;lt;/font&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Schlüsselnummer&#039;&#039;&#039; - Eine zweistellige Zahl zwischen 00 - 99. Die Schlüsselnummer hat aktuell keine technische Relevanz mehr. In früheren FHEM-Versionen ist sie relevant für [[#Zweistufiges_Modell_f.C3.BCr_Module|zweistufige Module]] (Reihenfolge für [[DevelopmentModuleAPI#Dispatch|Dispatch()]] um logische Module zu prüfen). Die allgemeine Empfehlung ist hierbei eine Schlüsselnummer eines Moduls zu verwenden, welches eine ähnliche Funktionalität bietet. Die Schlüsselnummer 99 hat hierbei eine besondere Bedeutung, da alle Module mit dieser Schlüsselnummer beim Start von FHEM automatisch geladen werden, selbst, wenn sie in der Konfiguration nicht verwendet werden. Daher wird für myUtils 99 als Schlüsselnummer verwendet (99_myUtils.pm). Module mit der Schlüsselnummer 99 werden im SVN nicht akzeptiert (siehe [[SVN Nutzungsregeln]])&lt;br /&gt;
* &#039;&#039;&#039;Modulname&#039;&#039;&#039; - Der Name des Moduls wie er in FHEM bei dem Anlegen einer Gerätedefinition zu verwenden ist. Der Modulname sollte nur aus den folgenden möglichen Zeichen bestehen: Groß-/Kleinbuchstaben, Zahlen sowie Unterstrich (_)&lt;br /&gt;
&lt;br /&gt;
=== Inhaltlicher Aufbau ===&lt;br /&gt;
&lt;br /&gt;
Ein Modul ist inhaltlich in folgende Abschnitte unterteilt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
#  72_MYMODULE.pm &lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
package main;&lt;br /&gt;
&lt;br /&gt;
# Laden evtl. abhängiger Perl- bzw. FHEM-Module&lt;br /&gt;
use HttpUtils;&lt;br /&gt;
use [...]&lt;br /&gt;
&lt;br /&gt;
# FHEM Modulfunktionen&lt;br /&gt;
&lt;br /&gt;
sub MYMODULE_Initialize() {&lt;br /&gt;
   ...&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub MYMODULE_Define() {&lt;br /&gt;
   ...&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
# Eval-Rückgabewert für erfolgreiches&lt;br /&gt;
# Laden des Moduls&lt;br /&gt;
1;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Beginn der Commandref&lt;br /&gt;
&lt;br /&gt;
=pod&lt;br /&gt;
=item [helper|device|command]&lt;br /&gt;
=item summary Kurzbeschreibung in Englisch was MYMODULE steuert/unterstützt&lt;br /&gt;
=item summary_DE Kurzbeschreibung in Deutsch was MYMODULE steuert/unterstützt&lt;br /&gt;
&lt;br /&gt;
=begin html&lt;br /&gt;
 Englische Commandref in HTML&lt;br /&gt;
=end html&lt;br /&gt;
&lt;br /&gt;
=begin html_DE&lt;br /&gt;
 Deustche Commandref in HTML&lt;br /&gt;
=end html&lt;br /&gt;
&lt;br /&gt;
# Ende der Commandref&lt;br /&gt;
=cut&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man kann hierbei von folgender Reihenfolge sprechen:&lt;br /&gt;
&lt;br /&gt;
# Perl-Code, welcher das Modul implementiert&lt;br /&gt;
# Die Zeile &amp;lt;code&amp;gt;1;&amp;lt;/code&amp;gt; nachdem der Perl-Code abgeschlossen ist. Dies dient FHEM der Erkennung, dass das Modul erfolgreich und vollständig geladen wurde. Sollte diese Zeile nicht enthalten sein, wird FHEM beim Laden des Moduls die Fehlermeldung &amp;lt;code&amp;gt;Error:Modul 72_MYMODULE deactivated&amp;lt;/code&amp;gt; in das Logfile schreiben.&lt;br /&gt;
# Commandref zur Dokumentation des Moduls. Diese Dokumentation soll dem User die möglichen Befehle/Attribute/Readings/Events vermitteln. Weitere Informationen und Hinweise findet man in den [[Guidelines zur Dokumentation]].&lt;br /&gt;
&lt;br /&gt;
== Der Hash einer Geräteinstanz ==&lt;br /&gt;
Eine Besonderheit in Perl sind [http://de.wikipedia.org/wiki/Assoziatives_Array#Perl assoziative Arrays], (nicht ganz richtig als &amp;quot;Hash&amp;quot; bezeichnet) in denen die Adressierung nicht über eine Zählvariable erfolgt, sondern über einen beliebigen String. Die internen Abläufe bei der Adressierung führen dazu, dass die Speicherung in und der Abruf aus Hashes relativ langsam ist.&lt;br /&gt;
&lt;br /&gt;
Der zentrale Speicherort für Informationen einer Geräteinstanz bei FHEM ist ein solcher Hash, der seinerseits in fhem.pl von einem globalen Hash referenziert wird. &lt;br /&gt;
&lt;br /&gt;
In fhem.pl werden alle Gerätedefinitionen in dem globalen Hash &amp;lt;code&amp;gt;%defs&amp;lt;/code&amp;gt; abgelegt. Der Inhalt von &amp;lt;code&amp;gt;$defs{&#039;&#039;&amp;amp;lt;Name&amp;amp;gt;&#039;&#039;}&amp;lt;/code&amp;gt; in fhem.pl verweist dabei auf den Hash der Geräteinstanz in Form einer Hashreferenz. Diesen Verweis (also nur die Adresse) bekommen die Funktionen eines Moduls übergeben (i.d.R. als &amp;lt;code&amp;gt;$hash&amp;lt;/code&amp;gt; bezeichnet), welche direkt von fhem.pl aufgerufen werden. In dem Hash stehen beispielsweise die internen Werte des Geräts, die im Frontend als &amp;quot;Internals&amp;quot; angezeigt werden, sowie die Readings des Geräts. &lt;br /&gt;
&lt;br /&gt;
Beispiele:&lt;br /&gt;
*&amp;lt;code&amp;gt;$hash-&amp;gt;{NAME}&amp;lt;/code&amp;gt; enthält den Namen der Geräteinstanz, &lt;br /&gt;
*&amp;lt;code&amp;gt;$hash-&amp;gt;{TYPE}&amp;lt;/code&amp;gt; enthält die Typbezeichnung des Geräts (Modulname)&lt;br /&gt;
&lt;br /&gt;
==Ausführung von Modulen==&lt;br /&gt;
FHEM arbeitet intern nicht parallel, sondern arbeitet alle Aufgaben seriell nacheinander kontinuierlich ab. Daher wäre es ungünstig, wenn Module Daten von einem physikalischen Gerät abfragen wollen und dabei innerhalb der selben Funktion auf die Antwort des Geräts warten. In dieser Zeit, in der FHEM auf die Antwort des Gerätes warten muss, wäre der Rest von FHEM blockiert. Da immer nur eine Aufgabe zur selben Zeit bearbeitet wird, müssen alle weiteren Aufgaben solange warten. Eine Datenkommunikation innerhalb eines Moduls sollte daher immer ohne Blockierung erfolgen. Dadurch kann FHEM die Wartezeit effizient für andere Aufgaben nutzen um bspw. anstehende Daten für andere Module zu verarbeiten. Es gibt in FHEM entsprechende Mechanismen, welche eine &amp;quot;Non-Blocking&amp;quot;-Kommunikation über verschiedene Wege (z.B. seriell, HTTP, TCP, ...) ermöglichen.&lt;br /&gt;
&lt;br /&gt;
Dafür werden in FHEM zwei zentrale Listen gepflegt, in der die Filedeskriptoren der geöffneten Kommunikatonsverbindungen gespeichert sind. Auf Linux- bzw. Unix-basierten Plattformen wird der select-Befehl des Betriebssystems verwendet um Filedeskriptoren auf lesbare Daten zu überprüfen. In FHEM gibt es dazu eine Liste (&amp;lt;code&amp;gt;%selectlist&amp;lt;/code&amp;gt;), in der die Filedeskriptoren sämtlicher Geräte (z.B. serielle Verbindung, TCP-Verbindung, etc.) gespeichert sind. &lt;br /&gt;
&lt;br /&gt;
In der zentralen Schleife (Main-Loop) von fhem.pl wird mit &amp;lt;code&amp;gt;select()&amp;lt;/code&amp;gt; überwacht, ob über eine der geöffneten Schnittstellen Daten zum Lesen anstehen. Wenn dies der Fall ist, dann wird die Lesefunktion ([[#X_Read|X_Read]]) des zuständigen Moduls aufgerufen, damit es die Daten entgegennimmt und verarbeitet. Anschließend wird die Schleife weiter ausgeführt.&lt;br /&gt;
&lt;br /&gt;
Auf Windows-Systemen funktioniert dies anders. Hier können USB/Seriell-Geräte nicht per &amp;lt;code&amp;gt;select()&amp;lt;/code&amp;gt; überwacht werden. In FHEM unter Windows werden daher diese Schnittstellen kontinuierlich abgefragt ob Daten bereitstehen. Dafür müssen Module zusätzlich zur Lesefunktion eine Abfragefunktion ([[#X_Ready|X_Ready]]) implementieren, welche prüft, ob Daten zum Lesen anstehen. Auch auf Linux/Unix-Plattformen hat diese Funktion eine Aufgabe. Falls nämlich eine Schnittstelle ausfällt, beziehungsweise ein CUL oder USB-zu-Seriell Adapter ausgesteckt wird, dann wird über diese Funktion regelmäßig geprüft ob die Schnittstelle wieder verfügbar wird.&lt;br /&gt;
&lt;br /&gt;
Innerhalb der eigentlichen Lesefunktion (X_Read) werden dann die Daten vom zugehörigen Gerät gelesen, das nötige Protokoll implementiert um die Daten zu interpretieren und Werte in Readings geschrieben.&lt;br /&gt;
&lt;br /&gt;
Auch wenn von einem Anwender über einen Get-Befehl Daten aktiv von einem Gerät angefordert werden, sollte nicht blockierend gewartet werden. Eine asynchrone Ausgabe, sobald das Ergebnis vorliegt, ist über [[DevelopmentModuleAPI#asyncOutput|asyncOutput()]] möglich. Siehe {{Link2Forum|Topic=43771|Message=357870|LinkText=Beschreibung}} und {{Link2Forum|Topic=43771|Message=360935|LinkText=Beispiel}}. Weitere Anwendungsbeispiele finden sich im  {{Link2Forum|Topic=43052|Message=353477|LinkText=PLEX Modul}} und im überarbeiteten und nicht-blockierenden {{Link2Forum|Topic=42771|Message=348498|LinkText=SYSSTAT Modul}}.&lt;br /&gt;
&lt;br /&gt;
== Wichtige globale Variablen aus fhem.pl ==&lt;br /&gt;
&lt;br /&gt;
FHEM arbeitet mit einer Vielzahl an internen Variablen. Die nun folgenden aufgelisteten Variablen sind die wichtigsten, welche man im Rahmen der Modulprogrammierung kennen sollte:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Variable !! Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$init_done&amp;lt;/code&amp;gt; || Dient der Erkennung für fhem.pl sowie den Modulen, ob FHEM den Initialisierungsvorgang abgeschlossen hat. Beim Starten von FHEM ist &amp;lt;code&amp;gt;$init_done&amp;lt;/code&amp;gt; gleich &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;. Erst, wenn das Einlesen der Konfiguration, sowie des State-Files (Readings) abgeschlossen ist, wird &amp;lt;code&amp;gt;$init_done&amp;lt;/code&amp;gt; auf &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; gesetzt.&lt;br /&gt;
Das gleiche Verfahren wird auch bei dem Befehl &amp;lt;code&amp;gt;rereadcfg&amp;lt;/code&amp;gt; angewandt. Während &amp;lt;code&amp;gt;rereadcfg&amp;lt;/code&amp;gt; ausgeführt wird (Konfiguration löschen, neu einlesen), ist &amp;lt;code&amp;gt;$init_done&amp;lt;/code&amp;gt; gleich &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Dies ist insbesondere in der [[#X_Define|Define]]-Funktion eines Moduls relevant.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;%attr&amp;lt;/code&amp;gt; || In &amp;lt;code&amp;gt;%attr&amp;lt;/code&amp;gt; werden sämtliche gesetzten Attribute aller Geräte gespeichert. Diese Datenstruktur wird generell durch den &amp;lt;code&amp;gt;attr&amp;lt;/code&amp;gt;-Befehl verwaltet. Hierbei wird einem Gerätenamen eine Mehrzahl an Attributnamen mit einem Wert zugeordnet. Attribut-Inhalte können über die Funktion [[DevelopmentModuleAPI#AttrVal|AttrVal()]] ausgelesen werden.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;%cmds&amp;lt;/code&amp;gt; || In &amp;lt;code&amp;gt;%cmds&amp;lt;/code&amp;gt; wird jedem in FHEM existierendem Befehl die entsprechende Funktion zugewiesen, welche diesen Befehl umsetzt. Module können durch das Eintragen eines Befehlsnamen samt Funktion in &amp;lt;code&amp;gt;%cmds&amp;lt;/code&amp;gt; über die [[#X_Initialize|Initialize]]-Funktion eines Moduls einen (oder mehrere) eigene Befehle in FHEM registrieren.&lt;br /&gt;
&lt;br /&gt;
Die Struktur ist dabei wiefolgt:&lt;br /&gt;
&lt;br /&gt;
  $cmds{&#039;&#039;&amp;amp;lt;Befehlsname&amp;amp;gt;&#039;&#039;} = {  Fn  =&amp;gt; &amp;quot;&#039;&#039;&amp;amp;lt;Funktionsname&amp;amp;gt;&#039;&#039;&amp;quot;,&lt;br /&gt;
                            Hlp =&amp;gt; &amp;quot;&#039;&#039;&amp;amp;lt;Aufrufsyntax&amp;amp;gt;&#039;&#039;&amp;quot;};&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;%data&amp;lt;/code&amp;gt;|| Der eigentliche Zweck von &amp;lt;code&amp;gt;%data&amp;lt;/code&amp;gt; ist dem Nutzer eine Möglichkeit zum Speichern von temporären Daten im globalen Kontext zu ermöglichen. Einige Module verwenden &amp;lt;code&amp;gt;%data&amp;lt;/code&amp;gt; jedoch auch um modul- &amp;amp; geräteübergreifend Daten auszutauschen.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;%defs&amp;lt;/code&amp;gt;|| In &amp;lt;code&amp;gt;%defs&amp;lt;/code&amp;gt; werden sämtliche Gerätedefinitionen, bzw. die Hash-Referenzen auf diese, gespeichert. Hier ist jedem Gerätenamen eine Hash-Referenz zugeordnet.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;%modules&amp;lt;/code&amp;gt;|| In &amp;lt;code&amp;gt;%modules&amp;lt;/code&amp;gt; sind alle geladenen Module gelistet mit ihren entsprechenden Initialisierungsdaten (Funktionsnamen, Attribut-Listen, spezielle Einstellungen, ...). Hier wird für jeden Modulname der Modul-Hash aus der [[#X_Initialize|Initialize]]-Funktion gespeichert. &lt;br /&gt;
Desweiteren legen viele Module, welche nach dem [[DevelopmentModuleIntro#Zweistufiges_Modell_f.C3.BCr_Module|zweistufigen Modulkonzept]] hier eine Rückwärtszuordnung von Geräteadressen zu Geräte-Hash an.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;%readyfnlist&amp;lt;/code&amp;gt;|| In &amp;lt;code&amp;gt;%readyfnlist&amp;lt;/code&amp;gt; sind alle zu prüfenden Verbindungen mit ihrer entsprechendem Geräte-Hash gelistet. FHEM prüft alle hier gelisteten Geräte regelmäßig über eine Aufruf der entsprechenden [[#X_Ready|Ready]]-Funktion.&lt;br /&gt;
&lt;br /&gt;
Bei einer Nutzung von dem Hilfsmodul DevIo.pm zum Aufbau einer Kommunikationsverbindung, kümmert sich DevIo selbständig um den entsprechenden Eintrag in &amp;lt;code&amp;gt;%readyfnlist&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;%selectlist&amp;lt;/code&amp;gt;|| In &amp;lt;code&amp;gt;%selectlist&amp;lt;/code&amp;gt; sind alle geöffneten Verbindungen mit ihrer entsprechendem Geräte-Hash gelistet. FHEM prüft alle hier gelisteten Geräte, ob der geöffnete Filedeskriptor unter &amp;lt;code&amp;gt;$hash-&amp;gt;{FD}&amp;lt;/code&amp;gt; Daten zum Lesen bereitgestellt hat. Ist dass der Fall, wird die entsprechende [[#X_Read|Read]]-Funktion aufgerufen, um anstehende Daten durch das Modul zu verarbeiten.&lt;br /&gt;
Bei einer Nutzung von dem Hilfsmodul DevIo.pm zum Aufbau einer Kommunikationsverbindung, kümmert sich DevIo selbständig um den entsprechenden Eintrag in &amp;lt;code&amp;gt;%selectlist&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Es gibt durchaus viele weitere globale Variablen, die jedoch für sehr spezielle Anwendungsfälle und z.T. nur einzelne Module gedacht sind und daher hier nicht aufgeführt werden.&lt;br /&gt;
&lt;br /&gt;
== Internals ==&lt;br /&gt;
Daten, die ein Modul im Geräte-Hash speichert nennt man Internals. Sie werden als Unterstruktur des Hashes der jeweiligen Geräteinstanz gespeichert, beispielswiese &amp;lt;code&amp;gt;$hash-&amp;gt;{NAME}&amp;lt;/code&amp;gt; für den Gerätenamen, welcher beim Define-Befehl übergeben wurde und als Internal gespeichert wird. Diese Daten spielen für FHEM eine sehr wichtige Rolle, da sämtliche gerätespezifischen Daten als Internal im Gerätehash gespeichert werden.&lt;br /&gt;
&lt;br /&gt;
Falls Werte wie z.B. ein Intervall nicht über den Define-Befehl gesetzt werden sollen und im Betrieb einfach änderbar sein sollten, ist eine alternative Möglichkeit die Speicherung in so genannten Attributen. Dann würde man den Define-Befehl so implementieren, dass er kein Intervall übergeben bekommt und statt dessen das Interval als Attribut über den Befehl &amp;lt;code&amp;gt;attr&amp;lt;/code&amp;gt; gesetzt wird.&lt;br /&gt;
&lt;br /&gt;
Generell werden alle Werte, welche direkt in der ersten Ebene von &amp;lt;code&amp;gt;$hash&amp;lt;/code&amp;gt; (Gerätehash) gespeichert werden auf der Detail-Seite einer Definition in der FHEMWEB Oberfläche angezeigt. Es gibt jedoch Ausnahmen:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;$hash-&amp;gt;{helper}{URL]&amp;lt;/code&amp;gt; - Alle Elemente, welche als Unterelement wieder einen Hash besitzen werden nicht in FHEMWEB dargestellt. Typischerweise speichern Module Daten unter &amp;lt;code&amp;gt;$hash-&amp;gt;{helper}&amp;lt;/code&amp;gt; interne Daten zwischen, die für den User nicht relevant sind, sondern nur der internen Verarbeitung dienen.&lt;br /&gt;
* &amp;lt;code&amp;gt;$hash-&amp;gt;{&#039;&#039;&#039;.&#039;&#039;&#039;&amp;lt;font color=&amp;quot;grey&amp;quot;&amp;gt;ELEMENT&amp;lt;/font&amp;gt;}&amp;lt;/code&amp;gt; - Alle Knoten, welche mit einem Punkt beginnen werden in der FHEMWEB Oberfläche nicht angezeigt. Man kann diese Daten jedoch beim Aufruf des [[List|list-Kommandos]] einsehen.&lt;br /&gt;
&lt;br /&gt;
Es gibt bereits vorbelegte Internals welche in FHEM dazu dienen definitionsbezogene Informationen wie bspw. Namen und Readings zu speichern. Dies sind im besonderen:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;min-width: 13em;&amp;quot; | Internal !!  Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash-&amp;gt;{NAME}&amp;lt;/code&amp;gt;  || Der Definitionsname, mit dem das Gerät angelegt wurde.  &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash-&amp;gt;{READINGS}&amp;lt;/code&amp;gt;  || Enthält alle aktuell vorhandenen Readings. Daten unterhalb dieses Knotens sollte man nicht direkt manipulieren. Um Readings zu Erzeugen gibt es entsprechende [[DevelopmentModuleAPI#Readings_.2F_Events|Reading-Funktionen]].&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash-&amp;gt;{NR}&amp;lt;/code&amp;gt;  || Die Positions-Nr. der Definition innerhalb der Konfiguration. Diese dient dazu die Konfiguration in der gleichen Reihenfolge zu speichern, wie die einzelnen Geräte angelegt wurden.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash-&amp;gt;{TYPE}&amp;lt;/code&amp;gt;  || Der Modulname, mit welchem die Definition angelegt wurde.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash-&amp;gt;{DEF}&amp;lt;/code&amp;gt;  || Sämtliche Argumente, welche beim &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt;-Befehl nach dem Modulnamen übergeben wurden.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash-&amp;gt;{CFGFN}&amp;lt;/code&amp;gt;  || Der Dateiname der Konfigurationsdatei in der diese Definition enthalten ist (sofern nicht in fhem.cfg). Dieser Wert ist nur gefüllt, wenn man mit mehreren Konfigurationsdateien arbeitet, welche dann in fhem.cfg via include-Befehl eingebunden werden.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash-&amp;gt;{NTFY_ORDER}&amp;lt;/code&amp;gt;  || Sofern das Modul Events via [[DevelopmentModuleIntro#X_Notify|Notify-Funktion]] verarbeitet enthält jede Definition eine Notify-Order als Zeichenkette bestehend aus dem Notify Order Prefix und dem Definitionsnamen. Details zur Funktionsweise gibt es in der Beschreibung zur [[DevelopmentModuleIntro#X_Notify|Notify-Funktion]] im Abschnitt &amp;quot;Reihenfolge für den Aufruf der Notify-Funktion beeinflussen&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash-&amp;gt;{NOTIFYDEV}&amp;lt;/code&amp;gt;  || Sofern das Modul Events via NotifyFn verarbeitet kann man damit die Definitionen, von denen man Events erhalten will begrenzen. Details zur Funktionsweise gibt es in der Beschreibung zur [[DevelopmentModuleIntro#X_Notify|Notify-Funktion]] im Abschnitt &amp;quot;Begrenzung der Aufrufe auf bestimmte Geräte&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash-&amp;gt;{IODev}&amp;lt;/code&amp;gt;  || Hier wird das zugeordnete IO-Gerät durch [[DevelopmentModuleAPI#AssignIoPort|AssignIoPort()]] gespeichert, welches für den Datentransport und -empfang dieses logischen Gerätes zuständig ist. Dieser Wert existiert nur bei Modulen die nach dem [[DevelopmentModuleIntro#Zweistufiges_Modell_f.C3.BCr_Module|zweistufigen Modulkonzept]] arbeiten. &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash-&amp;gt;{CHANGED}&amp;lt;/code&amp;gt;  || Hier werden alle Events kurzzeitig gesammelt, welche für die Eventverarbeitung anstehen. Insbesondere die [[DevelopmentModuleAPI#Readings_.2F_Events|Reading-Funktionen]] speichern hier alle Events zwischen um sie nach Abschluss via [[DevelopmentModuleAPI#DoTrigger|DoTrigger()]] zu verarbeiten. &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash-&amp;gt;{FD}&amp;lt;/code&amp;gt;  || Wenn die Definition eine Netzwerkverbindung oder serielle Schnittstelle geöffnet hat (z.B. via DevIo), so wird der entsprechende File-Deskriptor in diesem Internal gespeichert. Damit kann FHEM alle geöffneten Filedeskriptoren der entsprechenden Definition zuordnen um bei ankommenden Daten die Definition via [[DevelopmentModuleIntro#X_Read|Read-Funktion]] damit zu versorgen.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash-&amp;gt;{EXCEPT_FD}&amp;lt;/code&amp;gt;  || Ähnlich wie &amp;lt;code&amp;gt;$hash-&amp;gt;{FD}&amp;lt;/code&amp;gt;. Sofern die Definition in &amp;lt;code&amp;gt;[[#Wichtige_globale_Variablen_aus_fhem.pl|%selectlist]]&amp;lt;/code&amp;gt; eingetragen ist und ein Fildeskriptor in diesem Internal gesetzt ist, wird bei einer auftretenden Exception bzw. Interrupt die [[DevelopmentModuleIntro#X_Except|Except]]-Funktion des entsprechenden Moduls aufgerufen um darauf zu reagieren.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Generell sollte man die meisten der hier genannten systemweiten Internals nicht modifizieren, da ansonsten die korrekte Funktionsweise von FHEM nicht mehr garantiert werden kann.&lt;br /&gt;
&lt;br /&gt;
== Readings ==&lt;br /&gt;
Daten, welche von einem Gerät gelesen werden und in FHEM in einer für Menschen verständlichen Form zur Verfügung gestellt werden können, werden Readings genannt. Sie geben den Status des Gerätes wieder und erzeugen Events innerhalb von FHEM auf die andere Geräte reagieren können. Sie werden als Unterstruktur des Hashes der jeweiligen Geräteinstanz gespeichert, beispielsweise &lt;br /&gt;
*&amp;lt;code&amp;gt;$hash-&amp;gt;{READINGS}{temperature}{VAL}&amp;lt;/code&amp;gt; für die Temperatur eines Fühlers&lt;br /&gt;
*&amp;lt;code&amp;gt;$hash-&amp;gt;{READINGS}{temperature}{TIME}&amp;lt;/code&amp;gt; für den Zeitstempel der Messung&lt;br /&gt;
&lt;br /&gt;
Für den lesenden Zugriff auf Readings steht die Funktion &amp;lt;code&amp;gt;[[DevelopmentModuleAPI#ReadingsVal|ReadingsVal()]]&amp;lt;/code&amp;gt; zur Verfügung. Ein direkter Zugriff auf die Datenstruktur sollte nicht vorgenommen werden.&lt;br /&gt;
&lt;br /&gt;
Readings werden im Statefile von FHEM automatisch auf der Festplatte zwischengespeichert, damit sie nach einem Neustart sofort wieder zur Verfügung stehen. Dadurch ist der letzte Status eines Gerätes vor einem Neustart nachvollziehbar.&lt;br /&gt;
&lt;br /&gt;
Readings, die mit einem Punkt im Namen beginnen, haben eine funktionale Besonderheit. Sie werden im FHEMWEB nicht angezeigt und können somit als &amp;quot;Permanentspeicher&amp;quot; für kleinere Daten innerhalb des Moduls genutzt werden. Um größere Datenmengen permanent zu speichern sollte man jedoch die Funktion &amp;lt;code&amp;gt;[[DevelopmentModuleAPI#setKeyValue|setKeyValue()]]&amp;lt;/code&amp;gt; verwenden.&lt;br /&gt;
&lt;br /&gt;
Zum Setzen von Readings sollen &lt;br /&gt;
*bei Gruppen von Readings der Funktionsblock &amp;lt;code&amp;gt;[[DevelopmentModuleAPI#readingsBeginUpdate|readingsBeginUpdate()]]&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;[[DevelopmentModuleAPI#readingsBulkUpdate|readingsBulkUpdate()]]&amp;lt;/code&amp;gt; (mehrfach wiederholt), &amp;lt;code&amp;gt;[[DevelopmentModuleAPI#readingsEndUpdate|readingsEndUpdate()]]&amp;lt;/code&amp;gt;&lt;br /&gt;
*bei einzelnen Updates die Funktion &amp;lt;code&amp;gt;[[DevelopmentModuleAPI#readingsSingleUpdate|readingsSingleUpdate()]]&amp;lt;/code&amp;gt; &lt;br /&gt;
aufgerufen werden. Dabei kann man auch angeben, ob dabei ein Event ausgelöst werden soll oder nicht. Events erzeugen, je nach Hardwareperformance, spürbare Last auf dem System (siehe [[DevelopmentModuleIntro#X_Notify|NotifyFn]]), das Ändern von Readings ohne dass dabei Events erzeugt werden jedoch nicht.&lt;br /&gt;
&lt;br /&gt;
Eine Sequenz zum Setzen von Readings könnte folgendermaßen aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
readingsBeginUpdate($hash);&lt;br /&gt;
readingsBulkUpdate($hash, $readingName1, $wert1 );&lt;br /&gt;
readingsBulkUpdate($hash, $readingName2, $wert2 );&lt;br /&gt;
readingsEndUpdate($hash, 1);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Attribute ==&lt;br /&gt;
Damit der Nutzer das Verhalten einer einzelnen Gerätedefinition zur Laufzeit individuell anpassen kann, gibt es in FHEM für jede Definition sogenannte Attribute, welche mit dem Befehl &amp;lt;code&amp;gt;attr&amp;lt;/code&amp;gt; gesetzt werden können.&lt;br /&gt;
Diese stehen dann dem Modul unmittelbar zur Verfügung um das Verhalten während der Ausführung zu beeinflussen. Attribute werden zusammen mit dem &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt;-Befehl der jeweiligen Definition beim Speichern der aktuellen Konfiguration von FHEM in die Konfigurationsdatei geschrieben. Beim Neustart werden die entsprechenden Befehle ausgeführt um alle Definition inkl. Attribute wieder anzulegen. Zur Laufzeit werden Attribute in dem globalen Hash &amp;lt;code&amp;gt;%attr&amp;lt;/code&amp;gt; mit dem Definitionsnamen als Index (&amp;lt;code&amp;gt;$attr{$name} = $value&amp;lt;/code&amp;gt;) gespeichert. Ein Attribut mit dem Namen &amp;lt;code&amp;gt;header&amp;lt;/code&amp;gt; würde beispielsweise mit &amp;lt;code&amp;gt;$attr{$name}{header}&amp;lt;/code&amp;gt; adressiert. Generell sollte &amp;lt;code&amp;gt;%attr&amp;lt;/code&amp;gt; nicht durch direkten Zugriff manipuliert/benutzt werden.&lt;br /&gt;
&lt;br /&gt;
Zum Auslesen von Attributen sollte die Funktion [[DevelopmentModuleAPI#AttrVal|AttrVal()]] verwendet werden.&lt;br /&gt;
&lt;br /&gt;
Welche Attribute ein Modul unterstützt muss in der Funktion &amp;lt;code&amp;gt;[[#X_Initialize|X_Initialize]]&amp;lt;/code&amp;gt; durch Setzen von &amp;lt;code&amp;gt;$hash-&amp;gt;{AttrList}&amp;lt;/code&amp;gt; bekannt gemacht werden (siehe unten).&lt;br /&gt;
&lt;br /&gt;
Wenn beim Setzen von Attributen in einer Gerätedefinition entsprechende Werte geprüft werden sollen oder zusätzliche Funktionalitäten implementiert werden müssen, dann muss dies in der Funktion &amp;lt;code&amp;gt;[[#X_Attr|X_Attr]]&amp;lt;/code&amp;gt; (siehe unten) implementiert werden. Hier kann man bspw. einen Syntaxcheck für Attribut-Werte implementieren um ungültige Werte zurückzuweisen.&lt;br /&gt;
&lt;br /&gt;
== Modulfunktionen ==&lt;br /&gt;
&lt;br /&gt;
Damit fhem.pl ein Modul nutzen kann, muss dieses entsprechende Funktionen mit einer vorgegebenen Aufrufsyntax implementieren. Durch die Bekanntgabe dieser modulspezifischen Funktionen können Daten zwischen fhem.pl und einem Modul entsprechend ausgetauscht werden. Es gibt verschiedene Arten von Funktionen die ein Modul anbieten muss bzw. kann, je nach Funktionsumfang.&lt;br /&gt;
&lt;br /&gt;
=== Die wichtigsten Funktionen in einem Modul ===&lt;br /&gt;
&lt;br /&gt;
Folgende Funktion muss ein Modul mit dem beispielhaften Namen &amp;quot;X&amp;quot; mindestens bereitstellen:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;text-align:left&amp;quot; | Funktionsname !! style=&amp;quot;text-align:left&amp;quot; | Kurzbeschreibung&lt;br /&gt;
|-&lt;br /&gt;
|  [[#X_Initialize|X_Initialize]] || Initialisiert das Modul und gibt den Namen zusätzlicher Modulfunktionen bekannt, sowie modulspezifische Einstellungen. Wird direkt nach dem erfolgreichen Laden des Moduls durch fhem.pl aufgerufen.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Die folgenden Funktionen sind die wichtigsten Funktionen, welche je nach Anwendungsfall zu implementieren sind. Es handelt sich hierbei um die wichtigsten Vertreter, welche in den meisten Modulen Verwendung finden. Nicht alle Funktionen machen jedoch in jedem Modul Sinn. Generell sollte auch hier bei jeder Funktion der Modulname vorangestellt werden um ein einheitliches Namensschema zu gewährleisten. Hier die wichtigsten Modulfunktionen:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;text-align:left&amp;quot; | Funktionsname !! style=&amp;quot;text-align:left&amp;quot; class=&amp;quot;unsortable&amp;quot;| Kurzbeschreibung&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Define|X_Define]] || Wird im Rahmen des &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt;-Befehls aufgerufen.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Undef|X_Undef]] || Wird im Rahmen des &amp;lt;code&amp;gt;delete&amp;lt;/code&amp;gt;-Befehls, sowie &amp;lt;code&amp;gt;rereadcfg&amp;lt;/code&amp;gt;-Befehl aufgerufen. Dient zum Abbau von offenen Verbindungen, Timern, etc.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Delete|X_Delete]] || Wird im Rahmen des beim &amp;lt;code&amp;gt;delete&amp;lt;/code&amp;gt;-Befehls aufgerufen wenn das Gerät endgültig gelöscht wird um weiterführende Aktionen vor dem Löschen durchzuführen.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Get|X_Get]] || Wird im Rahmen des &amp;lt;code&amp;gt;get&amp;lt;/code&amp;gt;-Befehls aufgerufen um Daten vom Gerät abzufragen&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Set|X_Set]]  || Wird im Rahmen des &amp;lt;code&amp;gt;set&amp;lt;/code&amp;gt;-Befehls aufgerufen um Daten an das Gerät zu senden.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Attr|X_Attr]]  || Wird im Rahmen des &amp;lt;code&amp;gt;attr&amp;lt;/code&amp;gt;-Befehls aufgerufen um Attributwerte zu prüfen)&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Read|X_Read]]  || Wird durch FHEM aufgerufen, wenn ein gelisteter Filedeskriptor in &amp;lt;code&amp;gt;[[#Wichtige_globale_Variablen_aus_fhem.pl|%selectlist]]&amp;lt;/code&amp;gt; Daten zum Lesen bereitstellt.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Ready|X_Ready]]  || Wird unter Windows durch FHEM aufgerufen um zyklisch einen seriellen Filedeskriptor auf lesbare Daten zu prüfen. Unter Linux dient diese Funktion dem Wiederaufbau verlorener Verbindungen.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Notify|X_Notify]]  || Verarbeitet Events von anderen Geräten innerhalb von FHEM&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Rename|X_Rename]] || Wird aufgerufen, wenn ein Gerät umbenannt wird.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Shutdown|X_Shutdown]] || Wird beim Herunterfahren von FHEM ausgeführt.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Diese Funktionen werden in diesem Abschnitt genauer beschrieben.&lt;br /&gt;
&lt;br /&gt;
==== X_Initialize ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Initialize($)&lt;br /&gt;
{&lt;br /&gt;
	my ($hash) = @_;&lt;br /&gt;
	...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das &amp;lt;code&amp;gt;X&amp;lt;/code&amp;gt; im Namen muss dabei auf den Namen des Moduls bzw. des definierten Gerätetyps geändert werden. Im Modul mit der Datei &amp;lt;code&amp;gt;36_JeeLink.pm&amp;lt;/code&amp;gt; beispielsweise ist der Name der Funktion &amp;lt;code&amp;gt;JeeLink_Initialize&amp;lt;/code&amp;gt;. Die Funktion wird von fhem.pl nach dem Laden des Moduls aufgerufen und bekommt eine leere Hashreferenz für den Initialisierungsvorgang übergeben. &lt;br /&gt;
&lt;br /&gt;
Dieser Hash muss nun von X_Initialize mit allen modulrelevanten Funktionsnamen gefüllt werden. Anschließend wird dieser Hash durch fhem.pl im globalen Hash &amp;lt;code&amp;gt;%modules&amp;lt;/code&amp;gt; gespeichert. &amp;lt;code&amp;gt;$modules{ModulName}&amp;lt;/code&amp;gt; wäre dabei der Hash für das Modul mit dem Namen &amp;lt;code&amp;gt;ModulName&amp;lt;/code&amp;gt;. Es handelt sich also nicht um den oben beschriebenen Hash der Geräteinstanzen sondern einen Hash, der für jedes Modul existiert und modulspezifische Daten wie bspw. die implementierten Modulfunktionen enthält. Die Initialize-Funktion setzt diese Funktionsnamen, in den Hash des Moduls wie folgt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
$hash-&amp;gt;{DefFn}         = &amp;quot;X_Define&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{UndefFn}       = &amp;quot;X_Undef&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{DeleteFn}      = &amp;quot;X_Delete&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{SetFn}         = &amp;quot;X_Set&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{GetFn}         = &amp;quot;X_Get&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{AttrFn}        = &amp;quot;X_Attr&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{ReadFn}        = &amp;quot;X_Read&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{ReadyFn}       = &amp;quot;X_Ready&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{NotifyFn}      = &amp;quot;X_Notify&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{RenameFn}      = &amp;quot;X_Rename&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{ShutdownFn}    = &amp;quot;X_Shutdown&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Um eine entsprechende Funktion in FHEM bekannt zu machen muss dazu der Funktionsname, wie er im Modul als &amp;lt;code&amp;gt;sub &amp;amp;lt;&#039;&#039;Funktionsname&#039;&#039;&amp;amp;gt;() { ... }&amp;lt;/code&amp;gt; definiert ist, als Zeichenkette in &amp;lt;code&amp;gt;$hash&amp;lt;/code&amp;gt; gesetzt werden. Dabei sollten die entsprechenden Funktionsnamen immer den Modulnamen (in diesem Beispiel &amp;lt;code&amp;gt;X&amp;lt;/code&amp;gt;) als Präfix verwenden.&lt;br /&gt;
Auf diese Weise können sämtliche modulspezifisch implementierten Funktionen wie &amp;lt;code&amp;gt;X_Read&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;X_Parse&amp;lt;/code&amp;gt; etc. durch Zuweisung an &amp;lt;code&amp;gt;$hash-&amp;gt;{ReadFn}&amp;lt;/code&amp;gt; bzw. &amp;lt;code&amp;gt;$hash-&amp;gt;{ParseFn}&amp;lt;/code&amp;gt; usw. bekannt gemacht werden.&lt;br /&gt;
&lt;br /&gt;
Darüber hinaus sollten die vom Modul unterstützten Attribute definiert werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
$hash-&amp;gt;{AttrList} =&lt;br /&gt;
  &amp;quot;do_not_notify:1,0 &amp;quot; . &lt;br /&gt;
  &amp;quot;header &amp;quot; .&lt;br /&gt;
  $readingFnAttributes;  &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Auflistung aller unterstützten modulspezifischen Attribute erfolgt in Form einer durch Leerzeichen getrennten Liste in &amp;lt;code&amp;gt;$hash-&amp;gt;{AttrList}}&amp;lt;/code&amp;gt;. Es gibt in FHEM globale Attribute, die in allen Gerätedefinitionen verfügbar sind und nur modulspezifische Attribute die jedes Modul via &amp;lt;code&amp;gt;$hash-&amp;gt;{AttrList}&amp;lt;/code&amp;gt; über die eigene Initialize-Funktion setzt.  In fhem.pl werden dann die entsprechenden Attributwerte beim Aufruf eines &amp;lt;code&amp;gt;attr&amp;lt;/code&amp;gt;-Befehls in die globale Datenstruktur &amp;lt;code&amp;gt;$attr{$name}&amp;lt;/code&amp;gt;, z.B. &amp;lt;code&amp;gt;$attr{$name}{header}&amp;lt;/code&amp;gt; für das Attribut &amp;lt;code&amp;gt;header&amp;lt;/code&amp;gt; gespeichert. Falls im Modul weitere Aktionen oder Prüfungen beim Setzen eines Attributs nötig sind, dann kann wie im Beispiel oben die [[#X_Attr|Attr]]-Funktion implementiert und in der Initialize-Funktion bekannt gemacht werden.&lt;br /&gt;
&lt;br /&gt;
Die Variable &amp;lt;code&amp;gt;$readingFnAttributes&amp;lt;/code&amp;gt;, die im obigen Beispiel an die Liste der unterstützten Attribute angefügt wird, definiert Attributnamen, die dann zusätzlich gemacht werden, wenn das Modul zum Setzen von Readings die Funktionen &amp;lt;code&amp;gt;[[DevelopmentModuleAPI#readingsBeginUpdate|readingsBeginUpdate()]]&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;[[DevelopmentModuleAPI#readingsBulkUpdate|readingsBulkUpdate()]]&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;[[DevelopmentModuleAPI#readingsEndUpdate|readingsEndUpdate()]]&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;[[DevelopmentModuleAPI#readingsSingleUpdate|readingsSingleUpdate()]]&amp;lt;/code&amp;gt; verwendet. In diesen Funktionen werden Attribute wie &amp;lt;code&amp;gt;event-min-interval&amp;lt;/code&amp;gt; oder auch &amp;lt;code&amp;gt;event-on-change-reading&amp;lt;/code&amp;gt; ausgewertet. Für Details hierzu siehe commandref zu [http://fhem.de/commandref.html#readingFnAttributes readingFnAttributes].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Nutzung von parseParams()&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Funktion &amp;lt;code&amp;gt; [[DevelopmentModuleAPI#parseParams|parseParams()]]&amp;lt;/code&amp;gt; unterstützt Modulautoren beim Parsen von Übergabeparametern, welche bei &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;get&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;set&amp;lt;/code&amp;gt; Kommandos an die entsprechenden Modulfunktionen übergeben werden. Dadurch lassen sich auf einfache Weise insbesondere komplexe Parameter (wie bspw. Perl-Ausdrücke) sehr einfach parsen.&lt;br /&gt;
&lt;br /&gt;
Diese Zusatzfunktion kann man in der Initialize-Funktion einfach über folgenden Parameter für [[#X_Define|Define]]-, [[#X_Get|Get]]- und [[#X_Set|Set]]-Funktion modulweit aktivieren:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;$hash-&amp;gt;{parseParams} = 1;&amp;lt;/source&amp;gt;&lt;br /&gt;
Sobald es gesetzt ist wird automatisch durch fhem.pl &amp;lt;code&amp;gt;[[DevelopmentModuleAPI#parseParams|parseParams()]]&amp;lt;/code&amp;gt; aufgerufen und die an die [[#X_Define|Define]]-, [[#X_Get|Get]]- und [[#X_Set|Set]]-Funktion übergebenen Parameter ändern sich wie weiter unten in den jeweiligen Funktionen beschrieben.&lt;br /&gt;
&lt;br /&gt;
==== X_Define ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Define($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $def ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
 &lt;br /&gt;
	return $error;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Define-Funktion eines Moduls wird von FHEM aufgerufen wenn der Define-Befehl für ein Geräte ausgeführt wird und das Modul bereits geladen und mit der Initialize-Funktion initialisiert ist. Sie ist typischerweise dazu da, die übergebenen Parameter zu prüfen und an geeigneter Stelle zu speichern sowie einen Kommunikationsweg zum Gerät zu öffnen (z.B. TCP-Verbindung, USB-Schnittstelle o.ä.) oder einen [[#Pollen_von_Geräten|Status-Timer]] zu starten.&lt;br /&gt;
Sie beginnt typischerweise mit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Define($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $def ) = @_;&lt;br /&gt;
	my @a = split( &amp;quot;[ \t][ \t]*&amp;quot;, $def );&lt;br /&gt;
	...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Als Übergabeparameter bekommt die Define-Funktion den Hash der Geräteinstanz sowie den die im &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt;-Befehl übergebenen Parameter. Welche bzw. wie viele Parameter &lt;br /&gt;
akzeptiert werden und welcher Syntax diese entsprechen müssen ist Sache dieser Funktion. Im obigen Beispiel wird die Argumentzeile &amp;lt;code&amp;gt;$def&amp;lt;/code&amp;gt; in ein Array aufgeteilt (durch Leerzeichen/Tabulator getrennt) und so können die vom Modul bzw. der Define-Funktion erwarteten Werte über das Array der Reihe nach verarbeitet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
my $name   = $a[0];&lt;br /&gt;
my $module = $a[1];&lt;br /&gt;
my $url    = $a[2];&lt;br /&gt;
my $inter  = 300;&lt;br /&gt;
&lt;br /&gt;
if(int(@a) == 4) { &lt;br /&gt;
	$inter = $a[3]; &lt;br /&gt;
	if ($inter &amp;lt; 5) {&lt;br /&gt;
		return &amp;quot;interval too small, please use something &amp;gt; 5s, default is 300 seconds&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Damit die übergebenen Werte auch anderen Funktionen zur Verfügung stehen und an die jeweilige Geräteinstanz gebunden sind, werden die Werte typischerweise als Internals im Hash der Geräteinstanz gespeichert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
$hash-&amp;gt;{url} 		= $url;&lt;br /&gt;
$hash-&amp;gt;{Interval}	= $inter;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sobald alle Parameter korrekt verarbeitet wurden, wird in der Regel die erste Verbindung zum Gerät aufgebaut. Je nach Art des Geräts kann das eine permanente Datenverbindung sein (z.B. serielle Schnittstelle oder TCP-Verbindung) oder das Starten eines regelmäßigen Timers, der zyklisch den Status z.B. via [[HttpUtils|HTTP]] ausliest.&lt;br /&gt;
&lt;br /&gt;
Sollten im Rahmen der Define-Funktion Syntax-Probleme der Übergabeparameter festgestellt werden oder es kann bspw. keine Verbindung aufgebaut werden, so ist als Funktionsrückgabewert eine entsprechende Fehlermeldung zurückzugeben. Nur wenn alle Übergabeparameter akzeptiert werden, darf &amp;lt;code&amp;gt;undef&amp;lt;/code&amp;gt; zurückgegeben werden. Sobald eine Define-Funktion eine Fehlermeldung zurückmeldet, wird der define-Befehl durch FHEM zurückgewiesen und der User erhält die Fehlermeldung, welche die Define-Funktion produziert hat, als Ausgabe zurück.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Verfügbarkeit von Attributen&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Während die Define-Funktion ausgeführt wird, sollte man nicht davon ausgehen, dass alle vom Nutzer konfigurierten Attribute via [[DevelopmentModuleAPI#AttrVal|AttrVal()]] verfügbar sind. Attribute stehen in der Define-Funktion nur dann zur Verfügung, wenn FHEM sich nicht in der Initialisierungsphase befindet (globale Variable &amp;lt;code&amp;gt;$init_done&amp;lt;/code&amp;gt; ist wahr; der Nutzer hat die Gerätedefinition modifiziert). Daher sollte man weiterführende Funktion, welche auf gesetzte Attribute angewiesen sind, nur dann in der Define-Funktion starten, wenn &amp;lt;code&amp;gt;$init_done&amp;lt;/code&amp;gt; zutrifft.&lt;br /&gt;
&lt;br /&gt;
Andernfalls sollte man den Aufruf in der Notify-Funktion durchführen sobald &amp;lt;code&amp;gt;global:INITIALIZED&amp;lt;/code&amp;gt; bzw. &amp;lt;code&amp;gt;global:REREADCFG&amp;lt;/code&amp;gt; getriggert wurde:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Define($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $def ) = @_;&lt;br /&gt;
 &lt;br /&gt;
	...&lt;br /&gt;
&lt;br /&gt;
	$hash-&amp;gt;{NOTIFYDEV} = &amp;quot;global&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	X_FunctionWhoNeedsAttr($hash) if($init_done);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub X_Notify($$)&lt;br /&gt;
{&lt;br /&gt;
	my ($own_hash, $dev_hash) = @_;&lt;br /&gt;
	my $ownName = $own_hash-&amp;gt;{NAME}; # own name / hash&lt;br /&gt;
 &lt;br /&gt;
	return &amp;quot;&amp;quot; if(IsDisabled($ownName)); # Return without any further action if the module is disabled&lt;br /&gt;
 &lt;br /&gt;
	my $devName = $dev_hash-&amp;gt;{NAME}; # Device that created the events&lt;br /&gt;
	my $events = deviceEvents($dev_hash, 1);&lt;br /&gt;
&lt;br /&gt;
	if($devName eq &amp;quot;global&amp;quot; &amp;amp;&amp;amp; grep(m/^INITIALIZED|REREADCFG$/, @{$events}))&lt;br /&gt;
	{&lt;br /&gt;
		 X_FunctionWhoNeedsAttr($hash);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dadurch wird die Modulfunktion X_FunctionWhoNeedsAttr() nach dem Start erst aufgerufen, wenn alle Attribute aus der Konfiguration geladen wurden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Nutzung von parseParams()&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zum Aufteilen und Parsen von &amp;lt;code&amp;gt;$def&amp;lt;/code&amp;gt; lässt sich die Funktion [[DevelopmentModuleAPI#parseParams|parseParams]] verwenden um die einzelnen Argumente einfach zu parsen. Wenn in X_Initialize &amp;lt;code&amp;gt;$hash-&amp;gt;{parseParams} = 1;&amp;lt;/code&amp;gt; gesetzt wurde dann wird parseParams automatisch aufgerufen und X_Define ändert sich wie folgt:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Define($$$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $a, $h ) = @_;&lt;br /&gt;
	...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die genauen Möglichkeiten von parseParams sind in dem entsprechenden [[DevelopmentModuleAPI#parseParams|Artikel]] dokumentiert.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Nutzung von DevIo&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn eine physische Schnittstelle geöffnet werden soll und dann bei verfügbaren Eingabedaten eine Lese-Funktion von FHEM aufgerufen werden soll, dann kann man in der Define-Funktion die Funktion DevIo_OpenDev aufrufen, die sich um alles weitere kümmert. Sie öffnet die Schnittstelle und fügt den Filedeskriptor an die globale Liste offener Verbindungen (selectlist / readyfnlist) an. Damit kann FHEM in seiner Hauptschleife erkennen, von welchem Gerät Daten bereit stehen und die zuständigen Funktionen aufrufen.&lt;br /&gt;
&lt;br /&gt;
Um DevIo mitzuteilen welche Verbindung genau zu öffnen ist, muss das Internal &amp;lt;code&amp;gt;$hash-&amp;gt;{DeviceName} mit einer entsprechenden Syntax gefüllt sein (z.B. &amp;lt;code&amp;gt;&amp;quot;/dev/ttyUSB0@9600&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;192.168.2.105:3000&amp;quot;&amp;lt;/code&amp;gt;, ...). Üblicherweise wird diese Information als Argument im &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt;-Befehl vom Nutzer angegeben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
my $ret = DevIo_OpenDev( $hash, 0, &amp;quot;X_DeviceInit&amp;quot; );&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die optionale Funktion &amp;lt;code&amp;gt;X_DevInit&amp;lt;/code&amp;gt; wird zur weiteren Initialisierung der Verbindung von &amp;lt;code&amp;gt;DevIo_OpenDev&amp;lt;/code&amp;gt; aufgerufen. Der zweite Übergabeparameter an &amp;lt;code&amp;gt;DevIo_OpenDev&amp;lt;/code&amp;gt; (hier &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;) steht für reopen und wird benötigt, da die Funktion auch aufgerufen wird, wenn ein USB-Geräte beispielsweise im Betrieb aus- und wieder eingesteckt wird. In diesem Fall wird die Funktion mit &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; aufgerufen. Dies ist jedoch nur in der [[#X_Ready|X_Ready]]-Funktion notwendig. In der Define-Funktion wird immer &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; (erster Verbindungsversuch) angegen&lt;br /&gt;
&lt;br /&gt;
==== X_Undef ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Undef ($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $name ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
 &lt;br /&gt;
	return $error;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Die Undef-Funktion wird aufgerufen wenn ein Gerät mit &amp;lt;code&amp;gt;delete&amp;lt;/code&amp;gt; gelöscht wird oder bei der Abarbeitung des Befehls &amp;lt;code&amp;gt;rereadcfg&amp;lt;/code&amp;gt;, der ebenfalls alle Geräte löscht und danach das Konfigurationsfile neu einliest. Entsprechend müssen in der Funktion typische Aufräumarbeiten durchgeführt werden wie das saubere Schließen von Verbindungen oder das Entfernen von internen Timern, sofern diese im Modul zum Pollen verwendet wurden (siehe Abschnitt [[#Pollen_von_Geräten|Pollen von Geräten]]). &lt;br /&gt;
&lt;br /&gt;
Zugewiesene Variablen im Hash der Geräteinstanz, Internals oder Readings müssen hier nicht gelöscht werden. In fhem.pl werden die entsprechenden Strukturen beim Löschen der Geräteinstanz ohnehin vollständig gelöscht.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Undef($$)    &lt;br /&gt;
{                     &lt;br /&gt;
	my ( $hash, $name) = @_;       &lt;br /&gt;
	DevIo_CloseDev($hash);         &lt;br /&gt;
	RemoveInternalTimer($hash);    &lt;br /&gt;
	return undef;                  &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sollten im Rahmen der Undef-Funktion Probleme festgestellt werden, die ein Löschen nicht zulassen, so ist als Funktionsrückgabewert eine entsprechende Fehlermeldung zurückzugeben. Nur wenn die Undef-Funktion erfolgreich durchgeführt wurde, darf &amp;lt;code&amp;gt;undef&amp;lt;/code&amp;gt; zurückgegeben werden. Nur dann wird eine Gerätedefinition von FHEM auch tatsächlich gelöscht bzw. neu angelegt. Sollte die Undef-Funktion jedoch eine Fehlermeldung zurückgeben, wird der entsprechende Vorgang (&amp;lt;code&amp;gt;delete&amp;lt;/code&amp;gt; bzw. &amp;lt;code&amp;gt;rereadcfg&amp;lt;/code&amp;gt;) für dieses Gerät abgebrochen. Es bleibt dann unverändert in FHEM bestehen.&lt;br /&gt;
&lt;br /&gt;
==== X_Delete ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Delete ($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $name ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
 &lt;br /&gt;
	return $error;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Delete-Funktion ist das Gegenstück zur Funktion [[#X_Define|X_Define]] und wird aufgerufen wenn ein Gerät mit dem Befehl &amp;lt;code&amp;gt;delete&amp;lt;/code&amp;gt; gelöscht wird. &lt;br /&gt;
&lt;br /&gt;
Wenn ein Gerät in FHEM gelöscht wird, wird zuerst die Funktion [[#X_Undef|X_Undef]] aufgerufen um offene Verbindungen zu schließen, anschließend wird die Funktion X_Delete aufgerufen. Diese dient eher zum Aufräumen von dauerhaften Daten, welche durch das Modul evtl. für dieses Gerät spezifisch erstellt worden sind. Es geht hier also eher darum, alle Spuren sowohl im laufenden FHEM-Prozess, als auch dauerhafte Daten bspw. im physikalischen Gerät zu löschen die mit dieser Gerätedefinition zu tun haben.&lt;br /&gt;
&lt;br /&gt;
Dies kann z.B. folgendes sein:&lt;br /&gt;
&lt;br /&gt;
* Löschen von Dateien im Dateisystem die während der Nutzung dieses Geräts angelegt worden sind.&lt;br /&gt;
* Lösen von evtl. Pairings mit dem physikalischen Gerät &lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Delete($$)    &lt;br /&gt;
{                     &lt;br /&gt;
	my ( $hash, $name ) = @_;       &lt;br /&gt;
&lt;br /&gt;
	# Löschen von Geräte-assoziiertem Temp-File&lt;br /&gt;
	unlink($attr{global}{modpath}.&amp;quot;/FHEM/FhemUtils/$name.tmp&amp;quot;;)&lt;br /&gt;
&lt;br /&gt;
	return undef;&lt;br /&gt;
}    &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sollten im Rahmen der Delete-Funktion Probleme festgestellt werden, die ein Löschen nicht zulassen, so ist als Funktionsrückgabewert eine entsprechende Fehlermeldung zurückzugeben. Nur die Delete-Funktion erfolgreich durchgeführt wurde, darf &amp;lt;code&amp;gt;undef&amp;lt;/code&amp;gt; zurückgegeben werden. Nur dann wird eine Gerätedefinition von FHEM auch tatsächlich gelöscht. Sollte die Delete-Funktion eine Fehlermeldung zurückgeben, wird der Löschvorgang abgebrochen und das Gerät bleibt weiter in FHEM bestehen.&lt;br /&gt;
&lt;br /&gt;
==== X_Get ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Get ($$@)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $name, $opt, @args ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
 &lt;br /&gt;
	return $result;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Die Get-Funktion wird aufgerufen wenn der FHEM-Befehl &amp;lt;code&amp;gt;get&amp;lt;/code&amp;gt; mit einem Gerät dieses Moduls ausgeführt wird. Mit &amp;lt;code&amp;gt;get&amp;lt;/code&amp;gt; werden typischerweise Werte von einem Gerät abgefragt. In vielen Modulen wird auf diese Weise auch der Zugriff auf generierte Readings ermöglicht. Der Get-Funktion wird dabei der Geräte-Hash, der Gerätename, sowie die Aufrufparameter des get-Befehls übergeben. Als Rückgabewert wird das Ergebnis des entsprechenden Befehls in Form einer Zeichenkette zurückgegeben. Der Rückgabewert &amp;lt;code&amp;gt;undef&amp;lt;/code&amp;gt; hat hierbei keine besondere Bedeutung und wird behandelt wie eine leere Zeichenkette &amp;lt;code&amp;gt;&amp;quot;&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Get($$@)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $name, $opt, @args ) = @_;&lt;br /&gt;
&lt;br /&gt;
	return &amp;quot;\&amp;quot;get $name\&amp;quot; needs at least one argument&amp;quot; unless(defined($opt)));&lt;br /&gt;
&lt;br /&gt;
	if($opt eq &amp;quot;status&amp;quot;) &lt;br /&gt;
	{&lt;br /&gt;
	   ...&lt;br /&gt;
	}&lt;br /&gt;
	elsif($opt eq &amp;quot;powser&amp;quot;)&lt;br /&gt;
	{&lt;br /&gt;
	   ...&lt;br /&gt;
	}&lt;br /&gt;
	...&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		return &amp;quot;Unknown argument $opt, choose one of status power [...]&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn eine unbekannte Option an die Get-Funktion übergeben wird, so muss als Rückgabewert der Funktion eine bestimmte Syntax einhalten um FHEM mitzuteilen, welche Optionen für einen Get-Befehl aktuell unterstützt werden. Die Rückgabe muss dabei folgender Syntax entsprechen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&#039;&#039;&#039;unknown&#039;&#039;&#039; argument &#039;&#039;&amp;lt;font color=&amp;quot;grey&amp;quot;&amp;gt;[Parameter]&amp;lt;/font&amp;gt;&#039;&#039; &#039;&#039;&#039;choose one of&#039;&#039;&#039; &#039;&#039;&amp;lt;font color=&amp;quot;grey&amp;quot;&amp;gt;[Liste möglicher Optionen]&amp;lt;/font&amp;gt;&#039;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hierbei sind die fett gedruckten Teile der Rückmeldung besonders wichtig. Sind diese nicht vorhanden, kann FHEM nicht die möglichen Get-Kommandos für das entsprechende Gerät ermitteln. Es muss am Anfang der Meldung das Stichwort &amp;quot;unknown&amp;quot; vorkommen gefolgt von einer frei definierbaren Fehlermeldung (i.d.R der übergebene Parameter, welcher ungültig ist). Anschließend folgt &amp;quot;choose one of&amp;quot; mit einer anschließenden Liste möglicher Optionen getrennt durch ein Leerzeichen. &lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;return &amp;quot;unknown argument $opt choose one of state temperature humidity&amp;quot;;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hier werden als mögliche Optionen für einen Get-Befehl folgende Parameter angegeben:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;temperature&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;humidity&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dies würde in folgenden, mögliche Get-Befehle für einen User resultieren:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;get &#039;&#039;&amp;amp;lt;NAME&amp;amp;gt;&#039;&#039; state&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;get &#039;&#039;&amp;amp;lt;NAME&amp;amp;gt;&#039;&#039; temperature&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;get &#039;&#039;&amp;amp;lt;NAME&amp;amp;gt;&#039;&#039; humidity&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Ausgabe einer solchen Meldung ist sehr wichtig, da sie im GUI-Modul verwendet wird um die möglichen &amp;lt;code&amp;gt;get&amp;lt;/code&amp;gt;-Optionen zu ermitteln und als Auswahl anzubieten. Im weiteren Verlauf der Get-Funktion könnte man dann mit dem physischen Gerät kommunizieren und den gefragten Wert direkt abfragen und diesen als Return-Wert der Get-Funktion zurückgeben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Nutzung von parseParams()&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn in [[#X_Initialize|X_Initialize]] &amp;lt;code&amp;gt;$hash-&amp;gt;{parseParams} = 1;&amp;lt;/code&amp;gt; gesetzt wurde dann wird [[DevelopmentModuleAPI#parseParams|parseParams]] automatisch aufgerufen und X_Get ändert sich wie folgt:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Get($$$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $a, $h ) = @_;&lt;br /&gt;
	...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die genauen Möglichkeiten von parseParams sind in dem entsprechenden [[DevelopmentModuleAPI#parseParams|Artikel]] dokumentiert.&lt;br /&gt;
&lt;br /&gt;
==== X_Set ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Set ($$@)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $name, $cmd, @args ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
 &lt;br /&gt;
	return $error;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Set-Funktion ist das Gegenteil zur [[#X_Get|Get]]-Funktion. Sie ist dafür gedacht, Daten zum physischen Gerät zu schicken, bzw. entsprechende Aktionen im Gerät selber auszulösen. Ein Set-Befehl dient daher der direkten Steuerung des physikalischen Gerätes in dem es bspw. Zustände verändert (wie &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;off&amp;lt;/code&amp;gt;). Der Set-Funktion wird dabei der Geräte-Hash, der Gerätename, sowie die Aufrufparameter des set-Befehls übergeben. Als Rückgabewert kann eine Fehlermeldung in Form Zeichenkette zurückgegeben werden. Der Rückgabewert &amp;lt;code&amp;gt;undef&amp;lt;/code&amp;gt; bedeutet hierbei, dass der Set-Befehl erfolgreich durchgeführt wurde. Eine Set-Funktion gibt daher nur im Fehlerfall eine Rückmeldung mit einer entsprechenden Fehlermeldung. Der Wert &amp;lt;code&amp;gt;undef&amp;lt;/code&amp;gt; wird als &amp;quot;erfolgreich&amp;quot; interpretiert. Rückmeldungen von set-Befehlen sämtlicher Module, die im Rahmen eines ausgeführten [[Notify]] auftreten werden im FHEM Logfile festgehalten.&lt;br /&gt;
&lt;br /&gt;
Falls nur interne Daten, die ausschließlich für das Modul relevant sind, gesetzt werden müssen, so sollte statt Set die [[#X_Attr|Attr]]-Funktion verwendet werden. Attribute werden bei Save-Config auch in der Fhem.cfg gesichert. Set-Befehle nicht, da sie nur zur Steuerungszwecken im laufenden Betrieb von FHEM dienen.&lt;br /&gt;
 &lt;br /&gt;
Eine Set-Funktion ist ähnlich aufgebaut wie die Get-Funktion, sie bekommt jedoch in der Regel weitere zusätzliche Parameter übergeben um Zustände zu setzen. &lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Set($@)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $name, $cmd, @args ) = @_;&lt;br /&gt;
&lt;br /&gt;
	return &amp;quot;\&amp;quot;set $name\&amp;quot; needs at least one argument&amp;quot; unless(defined($cmd)));&lt;br /&gt;
&lt;br /&gt;
	if($cmd eq &amp;quot;status&amp;quot;)&lt;br /&gt;
	{&lt;br /&gt;
	   if($args[0] eq &amp;quot;up&amp;quot;)&lt;br /&gt;
	   {&lt;br /&gt;
	      ...&lt;br /&gt;
	   }&lt;br /&gt;
	   elsif($args[0] eq &amp;quot;down&amp;quot;)&lt;br /&gt;
	   {&lt;br /&gt;
	      ...&lt;br /&gt;
	   }&lt;br /&gt;
	   else&lt;br /&gt;
	   {&lt;br /&gt;
	      return &amp;quot;Unknown value $args[0] for $cmd, choose one of status power&amp;quot;;&lt;br /&gt;
	   }   &lt;br /&gt;
	}&lt;br /&gt;
	elsif($cmd eq &amp;quot;power&amp;quot;)&lt;br /&gt;
	{&lt;br /&gt;
	   if($args[0] eq &amp;quot;on&amp;quot;)&lt;br /&gt;
	   {&lt;br /&gt;
	      ...&lt;br /&gt;
	   }&lt;br /&gt;
	   elsif($args[0] eq &amp;quot;off&amp;quot;)&lt;br /&gt;
	   {&lt;br /&gt;
	      ...&lt;br /&gt;
	   }  &lt;br /&gt;
	   else&lt;br /&gt;
	   {&lt;br /&gt;
	      return &amp;quot;Unknown value $args[0] for $cmd, choose one of status power&amp;quot;;&lt;br /&gt;
	   }       &lt;br /&gt;
	}&lt;br /&gt;
	...&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		return &amp;quot;Unknown argument $cmd, choose one of status power&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn eine unbekannte Option an die Set-Funktion übergeben wird, so muss als Rückgabewert der Funktion eine bestimmte Syntax eingehalten werden um FHEM mitzuteilen, welche Optionen für einen Set-Befehl aktuell unterstützt werden. Die Rückgabe muss dabei folgender Syntax entsprechen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&#039;&#039;&#039;unknown&#039;&#039;&#039; argument &#039;&#039;&amp;lt;font color=&amp;quot;grey&amp;quot;&amp;gt;[Parameter]&amp;lt;/font&amp;gt;&#039;&#039; &#039;&#039;&#039;choose one of&#039;&#039;&#039; &#039;&#039;&amp;lt;font color=&amp;quot;grey&amp;quot;&amp;gt;[Liste möglicher Optionen]&amp;lt;/font&amp;gt;&#039;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hierbei sind die fett gedruckten Teile der Rückmeldung besonders wichtig. Sind diese nicht vorhanden, kann FHEM nicht die möglichen Set-Kommandos für das entsprechende Gerät ermitteln. Es muss am Anfang der Meldung das Stichwort &amp;quot;unknown&amp;quot; vorkommen gefolgt von einer frei definierbaren Fehlermeldung (i.d.R der übergebene Parameter, welcher ungültig ist). Anschließend folgt &amp;quot;choose one of&amp;quot; mit einer anschließenden Liste möglicher Optionen getrennt durch ein Leerzeichen. &lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;return &amp;quot;unknown argument $cmd choose one of state power&amp;quot;;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hier werden als mögliche Optionen für einen Get-Befehl folgende Parameter angegeben:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;power&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dies würde in folgenden, mögliche Get-Befehle für einen User resultieren:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;get &#039;&#039;&amp;amp;lt;NAME&amp;amp;gt;&#039;&#039; state&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;get &#039;&#039;&amp;amp;lt;NAME&amp;amp;gt;&#039;&#039; power&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Ausgabe einer solchen Meldung ist sehr wichtig, da sie im GUI-Modul verwendet wird um die möglichen &amp;lt;code&amp;gt;set&amp;lt;/code&amp;gt;-Optionen zu ermitteln und als Auswahl anzubieten&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Nutzung von SetExtensions.pm&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn man dem Nutzer zusätzlich zu den Set-Befehlen &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;off&amp;lt;/code&amp;gt; auch weiterführende Befehle wie &amp;lt;code&amp;gt;on-for-timer&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;on-till&amp;lt;/code&amp;gt;, usw. anbieten möchte, obwohl die zu steuernde Hardware solche Kommandos nicht unterstützt, kann man dies über das Hilfsmodul SetExtensions.pm realisieren.&lt;br /&gt;
&lt;br /&gt;
Das Hilfsmodul SetExtensions.pm bietet weiterführende Set-Kommandos basierend auf den Befehlen &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;off&amp;lt;/code&amp;gt; an. Dabei werden durch interne Timer bzw. eigens angelegten [[at]]-Definitionen diese Befehle durch FHEM selber umgesetzt. Je nach ausgeführtem Befehl wird der &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt;- bzw. &amp;lt;code&amp;gt;off&amp;lt;/code&amp;gt;-Befehl dann durch FHEM zum richtigen Zeitpunkt ausgeführt. Vorausgesetzt das Modul unterstützt in der Set-Funktion die Befehle &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;off&amp;lt;/code&amp;gt;, so werden durch den Einsatz von SetExtensions.pm folgende Befehle zusätzlich unterstützt:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Set-Kommando !! Beispiel !! Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;on-for-timer &#039;&#039;&amp;amp;lt;Dauer&amp;amp;gt;&#039;&#039;&amp;lt;/code&amp;gt;  || style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;on-for-timer 120&amp;lt;/code&amp;gt; || Schaltet das Gerät sofort mit dem &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt;-Befehl ein und nach der angegebenen Dauer in Sekunden via &amp;lt;code&amp;gt;off&amp;lt;/code&amp;gt; wieder aus.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;off-for-timer &#039;&#039;&amp;amp;lt;Dauer&amp;amp;gt;&#039;&#039;&amp;lt;/code&amp;gt;  || style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;off-for-timer 120&amp;lt;/code&amp;gt; || Schaltet das Gerät sofort mit dem &amp;lt;code&amp;gt;off&amp;lt;/code&amp;gt;-Befehl aus und nach der angegebenen Dauer in Sekunden via &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt; wieder ein.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;on-till &#039;&#039;&amp;amp;lt;Zeitpunkt&amp;amp;gt;&#039;&#039;&amp;lt;/code&amp;gt;  || style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;on-till 16:30&amp;lt;/code&amp;gt; || Schaltet das Gerät sofort mit dem &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt;-Befehl ein und zum angegebenen Zeitpunkt via &amp;lt;code&amp;gt;off&amp;lt;/code&amp;gt; wieder aus.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;off-till &#039;&#039;&amp;amp;lt;Zeitpunkt&amp;amp;gt;&#039;&#039;&amp;lt;/code&amp;gt;  || style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;off-till 16:30&amp;lt;/code&amp;gt; || Schaltet das Gerät sofort mit dem &amp;lt;code&amp;gt;off&amp;lt;/code&amp;gt;-Befehl aus und zum angegebenen Zeitpunkt via &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt; wieder ein.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;on-till-overnight &#039;&#039;&amp;amp;lt;Zeitpunkt&amp;amp;gt;&#039;&#039;&amp;lt;/code&amp;gt;  || style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;on-till-overnight 01:00&amp;lt;/code&amp;gt; || Ähnlich wie &amp;lt;code&amp;gt;on-till&amp;lt;/code&amp;gt;. Der übergebene Zeitpunkt wird aber nicht geprüft, ob er für den heutigen Tag bereits überschritten wurde. Dadurch kann man Abends einen Zeitpunkt setzen, der erst am nächsten Tag zutrifft.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;off-till-overnight &#039;&#039;&amp;amp;lt;Zeitpunkt&amp;amp;gt;&#039;&#039;&amp;lt;/code&amp;gt;  || style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;off-till-overnight 01:00&amp;lt;/code&amp;gt; || Ähnlich wie &amp;lt;code&amp;gt;off-till&amp;lt;/code&amp;gt;. Der übergebene Zeitpunkt wird aber nicht geprüft, ob er für den heutigen Tag bereits überschritten wurde. Dadurch kann man Abends einen Zeitpunkt setzen, der erst am nächsten Tag zutrifft.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;blink &#039;&#039;&amp;amp;lt;Anzahl&amp;amp;gt; &amp;amp;lt;Interval&amp;amp;gt;&#039;&#039;&amp;lt;/code&amp;gt;  || style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;blink 3 1&amp;lt;/code&amp;gt; || Schaltet das Gerät via &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt; für &amp;lt;code&amp;gt;&#039;&#039;&amp;amp;lt;Interval&amp;amp;gt;&#039;&#039;&amp;lt;/code&amp;gt; Sekunden ein und anschließend via &amp;lt;code&amp;gt;off&amp;lt;/code&amp;gt; wieder aus. Nach &amp;lt;code&amp;gt;&#039;&#039;&amp;amp;lt;Interval&amp;amp;gt;&#039;&#039;&amp;lt;/code&amp;gt; Sekunden wird das ganze wiederholt, solange bis die angegebene Anzahl erreicht ist.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;intervals &#039;&#039;&amp;amp;lt;Start&amp;amp;gt;-&amp;amp;lt;Ende&amp;amp;gt;&#039;&#039; &#039;&#039;&amp;amp;lt;Start&amp;amp;gt;-&amp;amp;lt;Ende&amp;amp;gt;&#039;&#039; ...&amp;lt;/code&amp;gt; || style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;intervals 07:00-08:00 16:30-18:00&amp;lt;/code&amp;gt; || Schaltet das Gerät innerhalb der übergebenen Zeiträumen via &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt; ein. Sobald die aktuelle Zeit ausserhalb dieser Zeiträume liegt, wird das Gerät via &amp;lt;code&amp;gt;off&amp;lt;/code&amp;gt; wieder ausgeschaltet. Es können dabei beliebig viele Zeiträume angegeben werden.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;toggle&amp;lt;/code&amp;gt; || style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;toggle&amp;lt;/code&amp;gt;  || Sofern der aktuelle Status &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt; ist, wird das Gerät via &amp;lt;code&amp;gt;off&amp;lt;/code&amp;gt; ausgeschaltet. Andernfalls wird es via &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt; eingeschaltet.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Eine kurze Beschreibung zu den möglichen Befehlen durch SetExtensions.pm gibt es auch in der Commandref zum [http://fhem.de/commandref.html#set Set-Befehl].&lt;br /&gt;
&lt;br /&gt;
Um SetExtensions.pm in der Set-Funktion nutzen zu können müssen folgende Aktionen durchgeführt werden:&lt;br /&gt;
&lt;br /&gt;
# Laden von SetExtensions.pm via &amp;lt;code&amp;gt;use SetExtensions;&amp;lt;/code&amp;gt; am Anfang des Moduls&lt;br /&gt;
# Aufruf und Rückgabe der Funktion [[DevelopmentModuleAPI#SetExtensions|SetExtensions()]] sofern die Set-Funktion mit dem übergebenen Befehl nichts anfangen kann.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
use SetExtensions;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
sub X_Set($@)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $name, $cmd, @args ) = @_;&lt;br /&gt;
	my $cmdList = &amp;quot;on off&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	return &amp;quot;\&amp;quot;set $name\&amp;quot; needs at least one argument&amp;quot; unless(defined($cmd)));&lt;br /&gt;
&lt;br /&gt;
	if($cmd eq &amp;quot;on&amp;quot;)&lt;br /&gt;
	{&lt;br /&gt;
		# Gerät einschalten...&lt;br /&gt;
	}&lt;br /&gt;
	elsif($cmd eq &amp;quot;off&amp;quot;)&lt;br /&gt;
	{&lt;br /&gt;
		# Gerät ausschalten...&lt;br /&gt;
	}&lt;br /&gt;
	...&lt;br /&gt;
	else # wenn der übergebene Befehl nicht durch X_Set() verarbeitet werden kann, Weitergabe an SetExtensions()&lt;br /&gt;
	{&lt;br /&gt;
		return SetExtensions($hash, $cmdList, $name, $cmd, @args);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sollte der übergebene Set-Befehl auch für SetExtensions unbekannt sein (bspw. &amp;lt;code&amp;gt;set &#039;&#039;&amp;amp;lt;Name&amp;amp;gt;&#039;&#039; ?&amp;lt;/code&amp;gt;), so generiert SetExtensions() eine entsprechende Usage-Meldung, welche innerhalb der Set-Funktion an FHEM zurückgegeben werden muss.&lt;br /&gt;
&lt;br /&gt;
Eine ausführliche Beschreibung zu der Funktion SetExtensions() gibt es in der  [[DevelopmentModuleAPI#SetExtensions|API-Referenz]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Nutzung von parseParams()&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn in [[#X_Initialize|X_Initialize]] &amp;lt;code&amp;gt;$hash-&amp;gt;{parseParams} = 1;&amp;lt;/code&amp;gt; gesetzt wurde dann wird [[DevelopmentModuleAPI#parseParams|parseParams]] automatisch aufgerufen und X_Set ändert sich wie folgt:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Set($$$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $a, $h ) = @_;&lt;br /&gt;
	...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die genauen Möglichkeiten von parseParams sind in dem entsprechenden [[DevelopmentModuleAPI#parseParams|Artikel]] dokumentiert.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Nutzung von FHEMWEB-Widgets&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das GUI-Modul [[FHEMWEB]] kann für die einzelnen Set-Optionen, die das Modul versteht, automatisch Eingabehilfen wie Drop-Down Boxen oder Slider erzeugen. In der Detailansicht der GUI kann der Anwender dann die jeweiligen Werte komfortabel auswählen. Dafür muss die Set-Funktion, wenn sie mit der Option &amp;lt;code&amp;gt;?&amp;lt;/code&amp;gt; aufgerufen wird, nicht nur einen Text mit  &amp;lt;code&amp;gt;&amp;quot;Unknown ... choose one of ...&amp;quot;&amp;lt;/code&amp;gt; zurückgeben sondern den einzelnen Set-Optionen in diesem Rückgabetext nach einem Doppelpunkt entsprechende Zusatzinformationen anhängen.&lt;br /&gt;
Meist prüft man in den Modulen gar nicht auf die Option &amp;lt;code&amp;gt;?&amp;lt;/code&amp;gt; sondern gibt generell bei unbekannten Optionen diesen Text zurück. Das Modul FHEMWEB ermittelt die Syntax eines Gerätes jedoch immer mit dem Befehl:&lt;br /&gt;
 set &#039;&#039;&amp;amp;lt;NAME&amp;amp;gt;&#039;&#039; ?&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
	return &amp;quot;Unknown argument $cmd, choose one of state:up,down power:on,off on:noArg off:noArg&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit Kommata getrennte Werte ergeben eine Drop-Down Liste, mit der der User die Werte auswählen kann&lt;br /&gt;
&amp;lt;pre&amp;gt;timer:30,120,300&lt;br /&gt;
mode:verbose,ultra,relaxed&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wird kein Doppelpunkt zum Kommando angegeben, so wird eine Eingabezeile angezeigt, die die freie Eingabe eines Wertes erlaubt.&lt;br /&gt;
&lt;br /&gt;
Man kann jedoch die Eingabe-/Auswahlmöglichkeiten durch Widgets vereinfachen. Dazu gibt man hinter dem Doppelpunkt einen Widgetnamen und widgetspezifische Parameter an. Es existieren mehrere solcher Widgets in FHEMWEB. Die gebräuchlichsten sind:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Zusatz !! Beispiel !! Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;noArg&#039;&#039;&#039; || &amp;lt;code&amp;gt;reset:noArg&amp;lt;/code&amp;gt;|| Es werden keine weiteren Argumente mehr benötigt. In so einem Fall wird bei der Auswahl keine Textbox oder ähnliches angezeigt, da keine weiteren Argumente für diesen Befehl notwendig sind.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;slider&#039;&#039;&#039;:&amp;lt;min&amp;gt;,&amp;lt;step&amp;gt;,&amp;lt;max&amp;gt; || &amp;lt;code&amp;gt;dim:slider,0,1,100&amp;lt;/code&amp;gt;|| Es wird ein Schieberegler angezeigt um den Parameter auszuwählen. Dabei werden als Zusatzparameter Minimum, Schrittweite und Maximum angegeben.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;colorpicker&#039;&#039;&#039; || &amp;lt;code&amp;gt;rgb:colorpicker,RGB&amp;lt;/code&amp;gt;|| Es wird ein Colorpicker angezeigt, der dem Anwender die Auswahl einer Farbe ermöglicht. Die genaue Parametersyntax kann man dem Artikel zum  [[Color#Colorpicker|Colorpicker]] entnehmen.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;multiple&#039;&#039;&#039; || &amp;lt;code&amp;gt;group:multiple,Telefon,Multimedia,Licht,Heizung&amp;lt;/code&amp;gt; || Es erscheint ein Auswahldialog, wo man verschiedene Werte durch klicken auswählen kann. Optional kann man in einem Freitext eigene Werte ergänzen. dieser Dialog wird bspw. bei der Raum-Auswahl (Attribut &amp;quot;room&amp;quot;) oder der Gruppen-Auswahl (Attribut &amp;quot;group&amp;quot;) in FHEMWEB genutzt. &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;sortable&#039;&#039;&#039; || &amp;lt;code&amp;gt;command:sortable,monday,tuesday,...&amp;lt;/code&amp;gt; || Es erscheint ein Auswahldialog, wo man verschiedene Werte auswählen und sortieren kann. Man kann dabei Werte durch Klicken auswählen und durch Drag&#039;n&#039;Drop sortieren.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Es gibt noch weitere solcher Widgets. Eine genaue Auflistung dazu findet sich in der [http://fhem.de/commandref.html#widgetOverride commandref] unter widgetOverride zu FHEMWEB.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweise&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Damit in einer Eingabe bereits der aktuelle Wert vorbelegt bzw. in einer Auswahlliste der aktuelle Wert vorselektiert ist, muss es im Modul bzw. Gerät ein Reading mit dem gleichen Namen wie die Set-Option geben. Der Wert des gleichnamigen Readings wird dann als Vorbelegung / Vorselektion verwendet. &lt;br /&gt;
* Der User kann sich in der Raumübersicht nach wie vor via [[WebCmd|webCmd]] eine entsprechende Steuerung anlegen.&lt;br /&gt;
&lt;br /&gt;
==== X_Attr ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Attr ($$$$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $cmd, $name, $attrName, $attrValue  ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
 &lt;br /&gt;
	return $error;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Attr-Funktion dient der Prüfung von Attributen, welche über den &amp;lt;code&amp;gt;attr&amp;lt;/code&amp;gt;-Befehl gesetzt werden können. Sobald versucht wird, ein Attribut für ein Gerät zu setzen, wird vorher die Attr-Funktion des entsprechenden Moduls aufgerufen um zu prüfen, ob das Attribut aus Sicht des Moduls korrekt ist.&lt;br /&gt;
Liegt ein Problem mit dem Attribut bzw. dem Wert vor, so muss die Funktion eine aussagekräftige Fehlermeldung zurückgeben, welche dem User angezeigt wird.&lt;br /&gt;
Sofern das übergebene Attribut samt Inhalt korrekt ist, gibt die Attr-Funktion den Wert &amp;lt;code&amp;gt;undef&amp;lt;/code&amp;gt; zurück. Erst dann wird das Attribut in der globalen Datenstruktur &amp;lt;code&amp;gt;%attr&amp;lt;/code&amp;gt; gespeichert und ist somit erst aktiv.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
X_Attr(@)&lt;br /&gt;
{&lt;br /&gt;
	my ( $cmd, $name, $attrName, $attrValue ) = @_;&lt;br /&gt;
    &lt;br /&gt;
  	# $cmd  - Vorgangsart - kann die Werte &amp;quot;del&amp;quot; (löschen) oder &amp;quot;set&amp;quot; (setzen) annehmen&lt;br /&gt;
	# $name - Gerätename&lt;br /&gt;
	# $attrName/$attrValue sind Attribut-Name und Attribut-Wert&lt;br /&gt;
    &lt;br /&gt;
	if ($cmd eq &amp;quot;set&amp;quot;) {&lt;br /&gt;
		if ($aName eq &amp;quot;Regex&amp;quot;) {&lt;br /&gt;
			eval { qr/$aVal/ };&lt;br /&gt;
			if ($@) {&lt;br /&gt;
				Log3 $name, 3, &amp;quot;X ($name) - Invalid regex in attr $name $aName $aVal: $@&amp;quot;;&lt;br /&gt;
				return &amp;quot;Invalid Regex $aVal: $@&amp;quot;;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	return undef;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zusätzlich ist es möglich auch übergebene Attributwerte zu verändern bzw. zu korrigieren, indem man im Parameterarray &amp;lt;code&amp;gt;@_&amp;lt;/code&amp;gt; den ursprünglichen Wert anpasst. Dies erfolgt im Beispiel über die Modifikation des Wertes mit Index 3 (entspricht dem 4. Element) im Parameterarray, also &amp;lt;code&amp;gt;$_[3]&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Da das Attribut zum Zeitpunkt des Aufrufs der Attr-Funktion noch nicht gespeichert ist, wird der neue Wert zu diesem Zeitpunkt noch nicht via [[DevelopmentModuleAPI#AttrVal|AttrVal()]] zurückgegeben. Erst, wenn die Attr-Funktion mit &amp;lt;code&amp;gt;undef&amp;lt;/code&amp;gt; beendet ist, wird der neue Wert in FHEM gespeichert und steht dann via AttrVal() zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
Die Attr-Funktion bekommt nicht den Hash der Geräteinstanz übergeben, da sie normalerweise keine Werte dort speichern muss, sondern lediglich das Attribut auf Korrektheit prüfen muss.&lt;br /&gt;
Im obigen Beispiel wird für ein Attribut mit Namen &amp;quot;Regex&amp;quot; geprüft ob der reguläre Ausdruck fehlerhaft ist. Sofern dieser OK ist, wird &amp;lt;code&amp;gt;undef&amp;lt;/code&amp;gt; zurückgegeben und fhem.pl speichert den Wert des Attributs in &amp;lt;code&amp;gt;%attr&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Attributnamen mit Platzhaltern&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Falls man Attribute in der [[#X_Initialize|Initialize]]-Funktion mit Platzhaltern definiert (Wildcard-Attribute) wie z.B.:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
    $hash-&amp;gt;{AttrList} =&lt;br /&gt;
      &amp;quot;reading[0-9]*Name &amp;quot; .&lt;br /&gt;
    # usw.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
dann können Anwender Attribute wie reading01Name, reading02Name etc. setzen. Leider funktioniert das bisher nicht durch Klicken in der Web-Oberfläche, da FHEMWEB nicht alle denkbaren Ausprägungen in einem Dropdown anbieten kann. Der Benutzer muss solche Attribute manuell über den &amp;lt;code&amp;gt;attr&amp;lt;/code&amp;gt;-Befehl eingeben.&lt;br /&gt;
&lt;br /&gt;
Man kann jedoch in der Attr-Funktion neu gesetzte Ausprägungen von Wildcard-Attributen an die gerätespezifische userattr-Variable anfügen. Dann können bereits gesetzte Attribute in FHEMWEB durch Klicken ausgewählt und geändert werden.&lt;br /&gt;
Dazu reicht ein Aufruf der Funktion [[DevelopmentModuleAPI#addToDevAttrList|addToDevAttrList()]]: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
    addToDevAttrList($name, $aName);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== X_Read ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Read ($)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Die X_Read-Funktion wird aufgerufen, wenn ein dem Gerät zugeordneter Filedeskriptor (serielle Schnittstelle, TCP-Verbindung, ...) Daten zum Lesen bereitgestellt hat. Die Daten müssen nun eingelesen und interpretiert werden.&lt;br /&gt;
&lt;br /&gt;
Im folgenden Beispiel wird über eine serielle Schnittstelle (beziehungsweise über einen USB-To-Seriell-Konverter) von einem angeschlossenen Gerät gelesen. Dazu werden die bisher verfügbaren Daten mit der Funktion &amp;lt;code&amp;gt;DevIo_SimpleRead&amp;lt;/code&amp;gt; gelesen. Da die Übertragung möglicherweise noch nicht vollständig ist, kann es sein, dass kurz darauf die X_Read-Funktion wieder aufgerufen wird und ein weiterer Teil oder der Rest der Daten gelesen werden kann.&lt;br /&gt;
Die Funktion muss daher prüfen ob schon alle erwarteten Daten angekommen sind und gegebenenfalls die bisher gelesenen Daten in einem eigenen Puffer (idealerweise in &amp;lt;code&amp;gt;$hash&amp;lt;/code&amp;gt;) zwischenspeichern. Im Beispiel ist dies &amp;lt;code&amp;gt;$hash-&amp;gt;{helper}{BUFFER}&amp;lt;/code&amp;gt; an den die aktuell gelesenen Daten angehängt werden, bis die folgende Prüfung ein für das jeweilige Protokoll vollständige Frame erkennt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Read($)&lt;br /&gt;
{&lt;br /&gt;
	my ($hash) = @_;&lt;br /&gt;
	my $name = $hash-&amp;gt;{NAME};&lt;br /&gt;
	&lt;br /&gt;
	# einlesen der bereitstehenden Daten&lt;br /&gt;
	my $buf = DevIo_SimpleRead($hash);		&lt;br /&gt;
	return &amp;quot;&amp;quot; if ( !defined($buf) );&lt;br /&gt;
	Log3 $name, 5, &amp;quot;X ($name) - received data: &amp;quot;.$buf;    &lt;br /&gt;
&lt;br /&gt;
	# Daten in Hex konvertieren und an den Puffer anhängen&lt;br /&gt;
	$hash-&amp;gt;{helper}{BUFFER} .= unpack (&#039;H*&#039;, $buf);	&lt;br /&gt;
	Log3 $name, 5, &amp;quot;X ($name) - current buffer content: &amp;quot;.$hash-&amp;gt;{helper}{BUFFER};&lt;br /&gt;
&lt;br /&gt;
	# prüfen, ob im Buffer ein vollständiger Frame zur Verarbeitung vorhanden ist.&lt;br /&gt;
	if ($hash-&amp;gt;{helper}{BUFFER} =~ &amp;quot;ff1002(.{4})(.*)1003(.{4})ff(.*)&amp;quot;) {&lt;br /&gt;
	...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die zu lesenden Nutzdaten können dann je nach Protokoll des Geräts beispielsweise an einer festgelegten Stelle im Frame (dann in &amp;lt;code&amp;gt;$hash-&amp;gt;{helper}{BUFFER}&amp;lt;/code&amp;gt;) stehen oder aus dem Kontext mit einem Regex-Match extrahiert werden und via [[DevelopmentModuleAPI#Readings_.2F_Events|Reading-Funktionen]] in Readings gespeichert werden (siehe unten).&lt;br /&gt;
&lt;br /&gt;
Der Rückgabewert der Read-Funktion wird nicht geprüft und hat daher keinerlei Bedeutung.&lt;br /&gt;
&lt;br /&gt;
==== X_Ready ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Ready ($)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
    &lt;br /&gt;
	return $success;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wird im Main-Loop aufgerufen falls das Modul in der globalen Liste &amp;lt;code&amp;gt;%readyfnlist&amp;lt;/code&amp;gt; existiert. Diese Funktion hat je nachdem auf welchem OS FHEM ausgeführt wird unterschiedliche Aufgaben:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;UNIX-artiges Betriebssystem:&#039;&#039;&#039; prüfen, ob eine Verbindung nach einem Verbindungsabbruch wieder aufgebaut werden kann. Sobald der Verbindungsaufbau erfolgreich war, muss die Funktion einen erfolgreichen Wahrheitswert zurückliefern (z.B. &amp;quot;1&amp;quot;) und den eigenen Eintrag entsprechend aus &amp;lt;code&amp;gt;%readyfnlist&amp;lt;/code&amp;gt; löschen.&lt;br /&gt;
* &#039;&#039;&#039;Windows-Betriebssystem:&#039;&#039;&#039; prüfen, ob lesbare Daten für ein serielles Device (via COM1, COM2, ...) vorliegen. Sofern lesbare Daten vorliegen, muss Funktion einen erfolgreichen Wahrheitswert zurückliefern (z.B. &amp;quot;1&amp;quot;). Zusätzlich dazu muss die Funktion, wie bei UNIX-artigen Betriebssystem, ebenfalls bei einem Verbindungsabbruch einen neuen Verbindungsversuch initiieren. Der Eintrag in &amp;lt;code&amp;gt;%readyfnlist&amp;lt;/code&amp;gt; bleibt solange erhalten, bis die Verbindung seitens FHEM beendet wird.&lt;br /&gt;
&lt;br /&gt;
Der Windows-spezifische Teil zur Datenprüfung ist dabei nur zu implementieren, wenn das Modul über eine serielle Verbindung kommuniziert.&lt;br /&gt;
&lt;br /&gt;
Bei der Nutzung des Moduls DevIo wird dem Modulentwickler der Umgang mit &amp;lt;code&amp;gt;%readyfnlist&amp;lt;/code&amp;gt; abgenommen, da DevIo sich selbst um die entsprechenden Einträge kümmert und diese selbstständig wieder entfernt.&lt;br /&gt;
&lt;br /&gt;
In der Regel sieht eine Ready-Funktion immer gleich aus.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Ready($)&lt;br /&gt;
{&lt;br /&gt;
	my ($hash) = @_;&lt;br /&gt;
      &lt;br /&gt;
	# Versuch eines Verbindungsaufbaus, sofern die Verbindung beendet ist.&lt;br /&gt;
	return DevIo_OpenDev($hash, 1, undef ) if ( $hash-&amp;gt;{STATE} eq &amp;quot;disconnected&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
	# This is relevant for Windows/USB only&lt;br /&gt;
	if(defined($hash-&amp;gt;{USBDev})) {&lt;br /&gt;
		my $po = $hash-&amp;gt;{USBDev};&lt;br /&gt;
		my ( $BlockingFlags, $InBytes, $OutBytes, $ErrorFlags ) = $po-&amp;gt;status;&lt;br /&gt;
		return ( $InBytes &amp;gt; 0 );&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== X_Notify ====&lt;br /&gt;
&lt;br /&gt;
Die X_Notify-Funktion wird aus der Funktion [[DevelopmentModuleAPI#DoTrigger|DoTrigger()]] in fhem.pl heraus aufgerufen sobald ein Modul Events erzeugt hat. Damit kann ein Modul auf Events anderer Module reagieren. Typische Beispiele sind dabei das [[FileLog]]-Modul oder das [[notify]]-Modul.&lt;br /&gt;
&lt;br /&gt;
Die Notify-Funktion bekommt dafür zwei Hash-Referenzen übergeben: den Hash des eigenen Geräts und den Hash des Geräts, dass die Events erzeugt hat. &lt;br /&gt;
Über den Hash des eigenen Geräts kann die Notify-Funktion beispielsweise auf die Internals oder Attribute des eigenen Geräts zugreifen.&lt;br /&gt;
Über den Hash des Gerätes und der [[DevelopmentModuleAPI#deviceEvents|deviceEvents()]]-Funktion kann man auf die generierten Events zugreifen. Über den zweiten Parameter dieser Routine lässt sich bestimmen ob für das Reading &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt; ein &#039;normales&#039; Event (d.h. in der form &amp;lt;code&amp;gt;state: &amp;lt;wert&amp;gt;&amp;lt;/code&amp;gt;) erzeugen soll (Wert: 1) oder ob z.b. aus Gründen der Rückwärtskompatibilität ein Event ohne &amp;lt;code&amp;gt;state: &amp;lt;/code&amp;gt; erzeugt werden soll. Falls dem Anwender die Wahl des verwendeten Formats überlassen werden soll ist hierzu das [http://fhem.de/commandref_DE.html#addStateEvent addStateEvent-Attribut] vorzusehen.&lt;br /&gt;
&lt;br /&gt;
Der direkte Zugriff auf &amp;lt;code&amp;gt;$hash-&amp;gt;{CHANGED}&amp;lt;/code&amp;gt; ist nicht mehr zu empfehlen.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Notify($$)&lt;br /&gt;
{&lt;br /&gt;
  my ($own_hash, $dev_hash) = @_;&lt;br /&gt;
  my $ownName = $own_hash-&amp;gt;{NAME}; # own name / hash&lt;br /&gt;
&lt;br /&gt;
  return &amp;quot;&amp;quot; if(IsDisabled($ownName)); # Return without any further action if the module is disabled&lt;br /&gt;
&lt;br /&gt;
  my $devName = $dev_hash-&amp;gt;{NAME}; # Device that created the events&lt;br /&gt;
&lt;br /&gt;
  my $events = deviceEvents($dev_hash,1);&lt;br /&gt;
  return if( !$events );&lt;br /&gt;
&lt;br /&gt;
  foreach my $event (@{$events}) {&lt;br /&gt;
    $event = &amp;quot;&amp;quot; if(!defined($event));&lt;br /&gt;
&lt;br /&gt;
    # Examples:&lt;br /&gt;
    # $event = &amp;quot;readingname: value&amp;quot; &lt;br /&gt;
    # or&lt;br /&gt;
    # $event = &amp;quot;INITIALIZED&amp;quot; (for $devName equal &amp;quot;global&amp;quot;)&lt;br /&gt;
    #&lt;br /&gt;
    # processing $event with further code&lt;br /&gt;
  }&lt;br /&gt;
  return undef;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Begrenzung der Aufrufe auf bestimmte Geräte&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Da die Notify-Funktion für jedes definierte Gerät mit all seinen Events aufgerufen wird, muss sie in einer Schleife jedesmal prüfen und entscheiden, ob es mit dem jeweiligen Event etwas anfangen kann. Ein Gerät, dass die Notify-Funktion implementiert, sieht dafür typischerweise einen regulären Ausdruck vor, welcher für die Filterung verwendet wird.&lt;br /&gt;
&lt;br /&gt;
Wenn man nur gezielt von bestimmten Definitionen Events erhalten will, kann man diese auch in Form einer [http://fhem.de/commandref_DE.html#devspec devspec] in &amp;lt;code&amp;gt;$hash-&amp;gt;{NOTIFYDEV}&amp;lt;/code&amp;gt; angeben. Bspw. kann man in der Define-Funktion diesen Wert setzen. Dadurch wird die Notify-Funktion nur aufgerufen wenn eine der Definitionen, auf welche die devspec passt, ein Event erzeugt hat. Ein typischer Fall ist die Begrenzung von Events auf &amp;quot;global&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
in der Define-Funktion:&lt;br /&gt;
&lt;br /&gt;
$hash-&amp;gt;{NOTIFYDEV} = &amp;quot;global&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{NOTIFYDEV} = &amp;quot;global,Definition_A,Definition_B&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{NOTIFYDEV} = &amp;quot;global,TYPE=CUL_HM&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dies schont insbesondere bei grossen Installationen Ressourcen, da die Notify-Funktion nicht sämtliche Events, sondern nur noch Events der gewünschten Definitionen erhält. Dadurch erfolgen deutlich weniger Aufrufe der Notify-Funktion, was Systemressourcen schont.&lt;br /&gt;
&lt;br /&gt;
Sofern in der [[#X_Define|Define-Funktion]] eine Regexp als Argument übergeben wird, die ähnlich wie beim Modul [[notify]] auf Events wie &amp;lt;code&amp;gt;&amp;amp;lt;Definitionsname&amp;amp;gt;&amp;lt;/code&amp;gt; bzw. &amp;lt;code&amp;gt;&amp;amp;lt;Definitionsname&amp;amp;gt;:&amp;amp;lt;Event&amp;amp;gt;&amp;lt;/code&amp;gt; reagiert, so sollte man in der Define-Funktion die Funktion [[DevelopmentModuleAPI#notifyRegexpChanged|notifyRegexpChanged()]] verwenden. Diese versucht einen passenden Eintrag für &amp;lt;code&amp;gt;$hash-&amp;gt;{NOTIFYDEV}&amp;lt;/code&amp;gt; basierend auf der übergebenen Regexp zu setzen, sofern dies möglich ist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Reihenfolge für den Aufruf der Notify-Funktion beeinflussen&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sobald ein Event ausgelöst wurde, stellt sich FHEM eine Liste aller relevanten Geräte-Hashes zusammen, welche via Notify-Funktion prüfen müssen, ob das Event relevant ist. Dabei wird die Liste nach &amp;lt;code&amp;gt;$hash-&amp;gt;{NTFY_ORDER}&amp;lt;/code&amp;gt; sortiert. Diese enthält ein Order-Präfix in Form einer Ganzzahl, sowie den Namen der Definition (Bsp: &amp;lt;code&amp;gt;&#039;&#039;&#039;50&#039;&#039;&#039;-Lampe_Wohnzimmer&amp;lt;/code&amp;gt;). Dadurch kann man jedoch nicht sicherstellen, dass Events von bestimmten Modulen zuerst verarbeitet werden.&lt;br /&gt;
&lt;br /&gt;
Wenn das eigene Modul bei der Eventverarbeitung gegenüber den anderen Modulen eine bestimmte Reihenfolge einhalten muss, kann man in der [[#X_Initialize|Initialize]]-Funktion durch Setzen von &amp;lt;code&amp;gt;$hash-&amp;gt;{NotifyOrderPrefix}&amp;lt;/code&amp;gt; diese Reihenfolge beeinflussen. Standardmäßig werden Module immer mit einem Order-Präfix von &amp;quot;50-&amp;quot; in FHEM registriert. Durch die Veränderung dieses Präfixes kann man das eigene Modul in der Reihenfolge gegenüber anderen Modulen bei der Eventverarbeitung beeinflussen. &lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Initialize($)&lt;br /&gt;
{&lt;br /&gt;
	my ($hash) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
	&lt;br /&gt;
	$hash-&amp;gt;{NotifyOrderPrefix} = &amp;quot;45-&amp;quot;  # Alle Definitionen des Moduls X werden bei der Eventverarbeitung zuerst geprüft&lt;br /&gt;
	&lt;br /&gt;
	# oder...&lt;br /&gt;
	&lt;br /&gt;
	$hash-&amp;gt;{NotifyOrderPrefix} = &amp;quot;55-&amp;quot;  # Alle Definitionen des Moduls X werden bei der Eventverarbeitung als letztes geprüft&lt;br /&gt;
	&lt;br /&gt;
&amp;lt;/source&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
Da dieses Präfix bei eventverarbeitenden Definitionen in &amp;lt;code&amp;gt;$hash-&amp;gt;{NTFY_ORDER}&amp;lt;/code&amp;gt; dem Definitionsnamen vorangestellt wird bewirkt es bei einer normalen aufsteigenden Sortierung nach &amp;lt;code&amp;gt;$hash-&amp;gt;{NTFY_ORDER}&amp;lt;/code&amp;gt; eine veränderte Reihenfolge. Alle Module die in der Initialize-Funktion nicht &amp;lt;code&amp;gt;$hash-&amp;gt;{NotifyOrderPrefix}&amp;lt;/code&amp;gt; explizit setzen, werden mit &amp;quot;50-&amp;quot; als Standardwert vorbelegt.&lt;br /&gt;
&lt;br /&gt;
==== X_Rename ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Rename ($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $new_name, $old_name) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Rename-Funktion wird ausgeführt, nachdem ein Gerät umbenannt wurde. Auf diese Weise kann ein Modul auf eine Namensänderung reagieren, wenn das Gerät &amp;lt;code&amp;gt;$old_name&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;$new_name&amp;lt;/code&amp;gt; umbenannt wurde. Ein typischer Fall ist das Umsetzen der Namensänderungen bei Daten die mittels [[DevelopmentModuleAPI#setKeyValue|setKeyValue()]] gespeichert wurden. Hierbei müssen die Daten, welche unter dem alten Namen gespeichert sind, auf den neuen Namen geändert werden.&lt;br /&gt;
&lt;br /&gt;
Der Rename-Funktion wird lediglich der alte, sowie der neue Gerätename übergeben. Der Rückgabewert wird nicht ausgewertet.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Rename ($)&lt;br /&gt;
{&lt;br /&gt;
	my ( $new_name, $old_name ) = @_;&lt;br /&gt;
&lt;br /&gt;
	my $old_index = &amp;quot;Module_X_&amp;quot;.$old_name.&amp;quot;_data&amp;quot;;&lt;br /&gt;
	my $new_index = &amp;quot;Module_X_&amp;quot;.$new_name.&amp;quot;_data&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	my ($err, $data) = getKeyValue($old_index);&lt;br /&gt;
	return undef unless(defined($old_pwd));&lt;br /&gt;
&lt;br /&gt;
	setKeyValue($new_index, $data);&lt;br /&gt;
	setKeyValue($old_index, undef);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== X_Shutdown ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Shutdown ($)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Mit der X_Shutdown Funktion kann ein Modul Aktionen durchführen bevor FHEM gestoppt wird. Dies kann z.B. der ordnungsgemäße Verbindungsabbau mit dem physikalischen Gerät sein (z.B. Session beenden, Logout, etc.). Als Übergabeparameter wird der Geräte-Hash bereitgestellt. Der Rückgabewert einer Shutdown-Funktion wird nicht ausgewertet und ist daher irrelevant.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Shutdown($)&lt;br /&gt;
{&lt;br /&gt;
	my ($hash) = @_;&lt;br /&gt;
&lt;br /&gt;
	# Verbindung schließen&lt;br /&gt;
	DevIo_CloseDev($hash);&lt;br /&gt;
        return undef;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Funktionen für zweistufiges Modulkonzept ===&lt;br /&gt;
&lt;br /&gt;
Für das [[#Zweistufiges_Modell_für_Module|zweistufige Modulkonzept]] gibt es weiterhin:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;text-align:left&amp;quot; | Funktionsname !! style=&amp;quot;text-align:left&amp;quot; class=&amp;quot;unsortable&amp;quot; | Kurzbeschreibung&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Parse|X_Parse]] || Zustellen von Daten via [[DevelopmentModuleAPI#Dispatch|Dispatch()]] vom physischen Modul zum logischen Modul zwecks der Verarbeitung.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Write|X_Write]]|| Zustellen von Daten via [[DevelopmentModuleAPI#Dispatch|IOWrite()]] vom logischen zum physischen Modul um diese an die Hardware weiterzureichen.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Fingerprint|X_Fingerprint]] || Rückgabe eines &amp;quot;Fingerabdrucks&amp;quot; einer Nachricht. Dient der Erkennung von Duplikaten im Rahmen von [[DevelopmentModuleAPI#Dispatch|Dispatch()]]. Kann im physischen, als auch logischen Modul benutzt werden.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Für das zweistufige Modulkonzept muss in einem logischen Modul eine [[#X_Parse|Parse]]-Funktion im Modul-Hash registriert werden. In einem physikalischen Modul muss eine [[#X_Write|Write]]-Funktion definiert sein. Diese dienem dem Datenaustausch in beide Richtungen und werden von dem jeweils anderen Modul indirekt aufgerufen.&lt;br /&gt;
&lt;br /&gt;
In der [[#X_Initialize|Initialize]]-Funktion werden diese wie folgt definiert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
$hash-&amp;gt;{ParseFn}       = &amp;quot;X_Parse&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{WriteFn}       = &amp;quot;X_Write&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{FingerprintFn} = &amp;quot;X_Fingerprint&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Funktionen werden in diesem Abschnitt genauer beschrieben.&lt;br /&gt;
&lt;br /&gt;
==== X_Parse ====&lt;br /&gt;
{{Randnotiz|RNTyp=Info|RNText=&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&amp;lt;u&amp;gt;&#039;&#039;&#039;ACHTUNG&#039;&#039;&#039;:&amp;lt;/u&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
Dieser Abschnitt geht davon aus, dass das Modul mit dem Namen &amp;quot;X&amp;quot; ein &#039;&#039;&#039;logisches Modul&#039;&#039;&#039; im Sinne des zweistufigen Modulkonzepts ist, also Daten mit einem übergeordneten, physikalischen Modul austauscht.}}&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Parse ($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $io_hash, $message) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
	&lt;br /&gt;
	return $found;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Funktion X_Parse wird aufgerufen, sobald von dem IO-Gerät &amp;lt;code&amp;gt;$io_hash&amp;lt;/code&amp;gt; eine Nachricht &amp;lt;code&amp;gt;$message&amp;lt;/code&amp;gt; via [[DevelopmentModuleAPI#Dispatch|Dispatch()]] zur Verarbeitung angefragt wird. Die Parse-Funktion muss dann prüfen, zu welcher Gerätedefinition diese Nachricht gehört und diese entsprechend verarbeiten.&lt;br /&gt;
&lt;br /&gt;
Üblicherweise enthält eine Nachricht immer eine Komponente durch welche sich die Nachricht einem Gerät zuordnen lässt (z.B. Adresse, ID-Nummer, ...). Eine solche Identifikation sollte man im Rahmen der [[#X_Define|Define]]-Funktion im logischen Modul an geeigneter Stelle speichern, um in der Parse-Funktion eine einfache Zuordnung von Adresse/ID einer Nachricht zur entsprechenden Gerätedefinition zu haben. Dazu wird in der Regel im Modul-Hash im modulspezifischen Berreich eine Liste &amp;lt;code&amp;gt;defptr&amp;lt;/code&amp;gt; (Definition Pointer) geführt, welche jede eindeutige Adresse/ID dem entsprechenden Geräte-Hash zuordnet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sub X_Define ($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $def) = @_;&lt;br /&gt;
	my @a = split(&amp;quot;[ \t][ \t]*&amp;quot;, $def);&lt;br /&gt;
	my $name = $a[0];&lt;br /&gt;
&lt;br /&gt;
	...&lt;br /&gt;
	&lt;br /&gt;
	# erstes Argument ist die eindeutige Geräteadresse&lt;br /&gt;
	my $address = $a[1];&lt;br /&gt;
&lt;br /&gt;
	# Adresse rückwärts dem Hash zuordnen (für ParseFn)&lt;br /&gt;
	$modules{X}{defptr}{$address} = $hash;&lt;br /&gt;
&lt;br /&gt;
	...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Auf Basis dieses Definition Pointers kann die Parse-Funktion nun sehr einfach prüfen, ob für die empfangene Nachricht bereits eine entsprechende Gerätedefinition existiert. Sofern diese existiert, kann die Nachricht entsprechend verarbeitet werden. Sollte jedoch keine passende Gerätedefinition zu der empfangenen Nachricht existieren, so muss die Parse-Funktion den Gerätenamen &amp;quot;UNDEFINED&amp;quot; zusammen mit den Argumenten für einen &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt;-Befehl zurückgeben, welcher ein passendes Gerät in FHEM anlegen würde (durch [[autocreate]]).&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sub X_Parse ($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $io_hash, $message) = @_;&lt;br /&gt;
	&lt;br /&gt;
	# Die Stellen 10-15 enthalten die eindeutige Identifikation des Geräts&lt;br /&gt;
	my $address = substr($message, 10, 5); &lt;br /&gt;
&lt;br /&gt;
	# wenn bereits eine Gerätedefinition existiert (via Definition Pointer aus Define-Funktion)&lt;br /&gt;
	if(my $hash = $modules{X}{defptr}{$address}) &lt;br /&gt;
	{&lt;br /&gt;
		...  # Nachricht für $hash verarbeiten&lt;br /&gt;
		&lt;br /&gt;
		# Rückgabe des Gerätenamens, für welches die Nachricht bestimmt ist.&lt;br /&gt;
		return $hash-&amp;gt;{NAME}; &lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		# Keine Gerätedefinition verfügbar&lt;br /&gt;
		# Daher Vorschlag define-Befehl: &amp;lt;NAME&amp;gt; &amp;lt;MODULNAME&amp;gt; &amp;lt;ADDRESSE&amp;gt;&lt;br /&gt;
		return &amp;quot;UNDEFINED X_&amp;quot;.$address.&amp;quot; X $address&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== X_Write ====&lt;br /&gt;
{{Randnotiz|RNTyp=Info|RNText=&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&amp;lt;u&amp;gt;&#039;&#039;&#039;ACHTUNG&#039;&#039;&#039;:&amp;lt;/u&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
Dieser Abschnitt geht davon aus, dass das Modul mit dem Namen &amp;quot;X&amp;quot; ein &#039;&#039;&#039;physisches Modul&#039;&#039;&#039; im Sinne des zweistufigen Modulkonzepts ist, also Daten mit untergeordneten logischen Modulen austauscht. }}&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Write ($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, @arguments) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
	&lt;br /&gt;
	return $return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Write-Funktion wird durch die Funktion [[DevelopmentModuleAPI#IOWrite|IOWrite()]] aufgerufen, sobald eine logische Gerätedefinition Daten per IO-Gerät an die Hardware übertragen möchte. Dazu kümmert sich die Write-Funktion um die Übertragung der Nachricht in geeigneter Form an die verbundene Hardware. Als Argumente wird der Hash des physischen Gerätes übertragen, sowie alle weiteren Argumente, die das logische Modul beim Aufruf von IOWrite() mitgegeben hat. Im Normalfall ist das ein Skalar mit der zu sendenden Nachricht in Textform. Es kann aber auch sein, dass weitere Daten zum Versand notwendig sind (evtl. Schlüssel, Session-Key, ...). Daher ist die Parametersyntax einer zu schreibenden Nachricht via IOWrite-/Write-Funktion zwischen logischem und physikalischen Modul abzustimmen.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Write ($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $message, $address) = @_;&lt;br /&gt;
	&lt;br /&gt;
	DevIo_SimpleWrite($hash, $address.$message, 2);&lt;br /&gt;
&lt;br /&gt;
	return undef;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== X_Fingerprint ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Fingerprint($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $io_name, $msg ) = @_;&lt;br /&gt;
 &lt;br /&gt;
	...&lt;br /&gt;
 &lt;br /&gt;
	return ( $io_name, $fingerprint );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Fingerprint-Funktion dient der Erkennung von Duplikaten empfangener Nachrichten. Diese Funktion kann dabei sowohl im physischen, als auch im logischen Modul implementiert sein. Je nachdem auf welcher Ebene man für eine Nachricht einen Fingerprint bilden kann. &lt;br /&gt;
&lt;br /&gt;
Als Parameter wird der Name des IO-Geräts &amp;lt;code&amp;gt;$io_name&amp;lt;/code&amp;gt; übergeben, sowie die Nachricht &amp;lt;code&amp;gt;$msg&amp;lt;/code&amp;gt;, welche empfangen wurde. Nun muss aus dieser Nachricht ein eindeutiger Fingerprint gebildet werden. Dies bedeutet, dass alle variablen Inhalte, die aufgrund des Empfangs dieser Nachricht über unterschiedliche IO-Geräte enthalten sein können, entfernt werden müssen. Dies können bspw. Empfangsadressen von IO-Geräten sein oder Session-ID&#039;s die in der Nachricht enthalten sind. Alle Fingerprints sämtlicher Nachrichten, die innerhalb der letzten 500 Millisekunden (konfigurierbar via &amp;lt;code&amp;gt;global&amp;lt;/code&amp;gt; Attribut &amp;lt;code&amp;gt;dupTimeout&amp;lt;/code&amp;gt;) empfangen wurden, werden gegen diesen generierten Fingerprint getestet. Sollte innerhalb dieser Zeit bereits eine Nachricht mit diesem Fingerprint verarbeitet worden sein, so wird sie als Duplikat erkannt und nicht weiter verarbeitet. In diesem Fall gibt [[DevelopmentModuleAPI#Dispatch|Dispatch()]] den Namen der Gerätedefinition zurück, welche eine Nachricht mit dem selben Fingerprint bereits verarbeitet hat. Es erfolgt dann kein Aufruf der [[#X_Parse|Parse]]-Funktion.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Fingerprint($$)&lt;br /&gt;
{&lt;br /&gt;
  my ( $io_name, $msg ) = @_;&lt;br /&gt;
&lt;br /&gt;
  substr( $msg, 2, 2, &amp;quot;--&amp;quot; ); # entferne Empfangsadresse&lt;br /&gt;
  substr( $msg, 4, 1, &amp;quot;-&amp;quot; );  # entferne Hop-Count&lt;br /&gt;
&lt;br /&gt;
  return ( $io_name, $msg );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es wird zuerst, sofern implementiert, die Fingerprint-Funktion des physischen Moduls aufgerufen. Sollte sich hierdurch kein Duplikat erkennen lassen, wird die Fingerprint-Funktion jedes möglichen geladenen logischen Moduls aufgerufen, sofern implementiert. &lt;br /&gt;
&lt;br /&gt;
Sollte sowohl im physischen, als auch im logischen Modul keine Fingerprint-Funktion implementiert sein, so wird keinerlei Duplikatserkennung durchgeführt.&lt;br /&gt;
&lt;br /&gt;
=== FHEMWEB-spezifische Funktionen ===&lt;br /&gt;
&lt;br /&gt;
FHEMWEB bietet Modulautoren die Möglichkeit an durch spezielle Funktionsaufrufe in Modulen, eigene HTML-Inhalte zu verwenden. Dadurch können in Verbindung mit zusätzlichem JavaScript komplexe Dialoge/Inhalte/Steuermöglichkeiten dargestellt werden. &lt;br /&gt;
&lt;br /&gt;
Eine genaue Auflistung aller FHEMWEB-spezifischen Funktionsaufrufe gibt es in dem separaten Artikel [[DevelopmentFHEMWEB]]&lt;br /&gt;
&lt;br /&gt;
=== sonstige Funktionen ===&lt;br /&gt;
&lt;br /&gt;
In diesem Abschnitt werden weitere Funktionen behandelt die zum Teil aus FHEM, aber auch aus anderen Modulen aufgerufen werden. Sie sind dabei nur in speziellen Anwendungsfällen relevant. Hier eine Auflistung aller sonstigen Modulfunktionen:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Funktionsname !! class=&amp;quot;unsortable&amp;quot; | Kurzbeschreibung&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_DbLog_split|X_DbLog_split]] || Wird durch das Modul 93_DbLog.pm aufgerufen. Dient dem korrekten Split eines moduleigenen Events in Name/Wert/Einheit für die Nutzung einer Datenbank.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Except|X_Except]]|| Wird aufgerufen, sobald ein ein geöffneter Filedescriptor in [[#Wichtige_globale_Variablen_aus_fhem.pl|&amp;lt;code&amp;gt;%selectlist&amp;lt;/code&amp;gt;]], der unter &amp;lt;code&amp;gt;$hash-&amp;gt;{EXCEPT_FD}&amp;lt;/code&amp;gt; im Geräte-Hash gesetzt ist, einen Interrupt bzw. Exception auslöst.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Copy|X_Copy]]|| Wird durch das Modul 98_copy.pm aufgerufen im Rahmen des &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt;-Befehls sobald ein Gerät kopiert wurde.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_State|X_State]]|| Wird aufgerufen im Rahmen des &amp;lt;code&amp;gt;setstate&amp;lt;/code&amp;gt;-Befehls bevor der Status einer Gerätedefinition bzw. eines zugehörigen Readings gesetzt wird.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_AsyncOutput|X_AsyncOutput]]|| Nur Relevant für Module die via [[TcpServerUtils]] eine Client-Verbindung zu FHEM ermöglichen (z.B. FHEMWEB und telnet). Ermöglicht die asynchrone Ausgabe von Daten via [[DevelopmentModuleAPI#asyncOutput|asyncOutput()]] an einen einzelnen verbundenen Client.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_ActivateInform|X_ActivateInform]]|| Nur Relevant für Module die via [[TcpServerUtils]] eine Client-Verbindung zu FHEM ermöglichen (z.B. FHEMWEB und telnet). Ermöglicht das aktivieren des inform-Mechanismus zum senden von Events für einen einzelnen verbundenen Client.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Authorize|X_Authorize]]|| Wird aufgerufen im Rahmen von [[DevelopmentModuleAPI#Authorize|Authorize()]] um eine gewünschte Vorgangs-Art zu autorisieren.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Authenticate|X_Authenticate]]||  Wird aufgerufen im Rahmen von [[DevelopmentModuleAPI#Authenticate|Authenticate()]] um eine Authentifizierung zu prüfen und ggf. zu genehmigen.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In der [[#X_Initialize|Initialize]]-Funktion werden diese wie folgt definiert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
$hash-&amp;gt;{DbLog_splitFn} = &amp;quot;X_DbLog_split&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{ExceptFn} = &amp;quot;X_Except&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{CopyFn} = &amp;quot;X_Copy&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{AsyncOutputFn} = &amp;quot;X_AsyncOutput&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{ActivateInformFn} = &amp;quot;X_ActivateInform&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{StateFn} = &amp;quot;X_State&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{AuthorizeFn} = &amp;quot;X_Authorize&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{AuthenticateFn} = &amp;quot;X_Authenticate&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Diese Funktionen werden in diesem Abschnitt genauer beschrieben.&lt;br /&gt;
==== X_DbLog_split ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_DbLog_split ($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $event, $device_name ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
    &lt;br /&gt;
	return  ( $reading, $value, $unit );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die DbLog_split-Funktion wird durch das Modul [[DbLog]] aufgerufen, sofern der Nutzer DbLog benutzt. Sofern diese Funktion implementiert ist, kann der Modulautor das Auftrennen von Events in den Reading-Namen, -Wert und der Einheit selbst steuern. Andernfalls nimmt DbLog diese Auftrennung selber mittels Trennung durch Leerzeichen sowie vordefinierten Regeln zu verschiedenen Modulen vor. Je nachdem, welche Readings man in seinem Modul implementiert, passt diese standardmäßige Trennung jedoch nicht immer.&lt;br /&gt;
&lt;br /&gt;
Der Funktion werden folgende Eingangsparameter übergeben:&lt;br /&gt;
# Das generierte Event (Bsp: &amp;lt;code&amp;gt;temperature: 20.5 °C&amp;lt;/code&amp;gt;)&lt;br /&gt;
# Der Name des Geräts, welche das Event erzeugt hat (Bsp: &amp;lt;code&amp;gt;Temperatursensor_Wohnzimmer&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Es ist nicht möglich in der DbLog_split-Funktion auf die verarbeitende DbLog-Definition zu referenzieren.&lt;br /&gt;
&lt;br /&gt;
Als Rückgabewerte muss die Funktion folgende Werte bereitstellen:&lt;br /&gt;
# Name des Readings (Bsp: &amp;lt;code&amp;gt;temperature&amp;lt;/code&amp;gt;)&lt;br /&gt;
# Wert des Readings (Bsp: &amp;lt;code&amp;gt;20.5&amp;lt;/code&amp;gt;)&lt;br /&gt;
# Einheit des Readings (Bsp: &amp;lt;code&amp;gt;°C&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_DbLog_splitFn($$)&lt;br /&gt;
{&lt;br /&gt;
	my ($event, $device) = @_;&lt;br /&gt;
	my ($reading, $value, $unit);&lt;br /&gt;
        my $devhash = $defs{$device}&lt;br /&gt;
&lt;br /&gt;
	if($event =~ m/temperature/) {&lt;br /&gt;
	   $reading = &#039;temperature&#039;;&lt;br /&gt;
	   $value = substr($event,12,4);&lt;br /&gt;
	   $unit = &#039;°C&#039;;&lt;br /&gt;
	}   &lt;br /&gt;
        &lt;br /&gt;
        return ($reading, $value, $unit);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== X_Except ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Except ($)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die X_Except-Funktion wird durch fhem.pl aufgerufen, wenn die Gerätedefinition &amp;lt;code&amp;gt;$hash&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;[[#Wichtige_globale_Variablen_aus_fhem.pl|%selectlist]]&amp;lt;/code&amp;gt; aufgeführt ist und der Filedeskriptor in &amp;lt;code&amp;gt;$hash-&amp;gt;{EXCEPT_FD}&amp;lt;/code&amp;gt; eine Exception bzw. Interrupt auslöst. &lt;br /&gt;
&lt;br /&gt;
Der Rückgabewert wird nicht ausgewertet und ist daher irrelevant.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
use IO::File;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
sub X_Except ($)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	# Filehandle aus Filedescriptor erstellen&lt;br /&gt;
	my $filehandle = IO::File-&amp;gt;new_from_fd($hash-&amp;gt;{EXCEPT_FD}, &#039;r&#039;);&lt;br /&gt;
	seek($filehandle,0,0);	&lt;br /&gt;
&lt;br /&gt;
	# aktuellen Inhalt auslesen&lt;br /&gt;
	my $current_value = $filehandle-&amp;gt;getline;&lt;br /&gt;
&lt;br /&gt;
	if($current_value eq &amp;quot;1&amp;quot;)&lt;br /&gt;
	{&lt;br /&gt;
		...&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		...&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== X_Copy ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Copy ($)&lt;br /&gt;
{&lt;br /&gt;
	my ( $old_name, $new_name ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die X_Copy-Funktion wird durch das Modul [[copy]] aufgerufen nachdem ein Nutzer eine Gerätedefinition über den Befehl &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt; kopiert hat. Dazu werden als Funktionsparameter die Definitionsnamen der alten und neuen Gerätedefinition übergeben. Es dient dazu zusätzliche Daten aus der zu kopierenden Gerätedefinition in die neue Definition zu übernehmen. Der Befehl &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt; überträgt lediglich &amp;lt;code&amp;gt;$hash-&amp;gt;{DEF}&amp;lt;/code&amp;gt; in die neue Definition sowie sämtliche gesetzte Attribute. Weitere Daten müssen dann durch die X_Copy-Funktion übertragen werden. &lt;br /&gt;
&lt;br /&gt;
Die X_Copy-Funktion wird erst nach dem erfolgtem Kopiervorgang aufgerufen.&lt;br /&gt;
&lt;br /&gt;
Der Rückgabewert wird nicht ausgewertet und ist daher irrelevant.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sub X_Copy ($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $old_name, $new_name ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	my $old_hash = $defs{$old_name};&lt;br /&gt;
	my $new_hash = $defs{$new_name};&lt;br /&gt;
&lt;br /&gt;
	# copy also temporary session key&lt;br /&gt;
	$new_hash-&amp;gt;{helper}{SESSION_KEY} = $old_hash-&amp;gt;{helper}{SESSION_KEY};&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== X_AsyncOutput ====&lt;br /&gt;
TBD&lt;br /&gt;
&lt;br /&gt;
==== X_ActivateInform ====&lt;br /&gt;
TBD&lt;br /&gt;
==== X_State ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_State($)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $time, $readingName, $value ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
&lt;br /&gt;
	return $error;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die X_State-Funktion wird durch fhem.pl aufgerufen, sobald über den Befehl &amp;lt;code&amp;gt;setstate&amp;lt;/code&amp;gt; versucht wird ein Wert für ein Reading oder den Status (&amp;lt;code&amp;gt;$hash-&amp;gt;{STATE}&amp;lt;/code&amp;gt;) einer Gerätedefinition zu setzen. Dieser Befehl wird primär beim Starten von FHEM aufgerufen sobald das State-File eingelesen wird. Je nachdem, ob im gegebenen Fall ein Reading oder der Definitionsstatus gesetzt wird, haben die Übergabeparameter verschiedene Werte:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Funktionsparameter!! Wert beim Setzen eines Readings !! Wert beim Setzen eines Definitionsstatus&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash&amp;lt;/code&amp;gt; || colspan=2 align=center | Die Hashreferenz der betreffenden Gerätedefinition&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$time&amp;lt;/code&amp;gt;|| Der Zeitstempel auf welchen das Reading &amp;lt;code&amp;gt;$readingName&amp;lt;/code&amp;gt; gesetzt werden soll. Das Ergebnis entspricht dem Rückgabewert der Funktion || Der aktuelle Zeitstempel zum jetzigen diesem Zeitpunkt.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$readingName&amp;lt;/code&amp;gt;|| Der Name des Readings, welches auf einen neuen Wert gesetzt werden soll. || Statischer Wert &amp;quot;STATE&amp;quot; um anzuzeigen, dass es sich um den Definitionsstatus handelt, welcher gesetzt werden soll (&amp;lt;code&amp;gt;$hash-&amp;gt;{STATE}&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$value&amp;lt;/code&amp;gt; || Der Wert, welchen das Reading &amp;lt;code&amp;gt;$readingName&amp;lt;/code&amp;gt; annehmen soll. || Der Wert, welchen die Gerätedefinition als Status annehmen soll.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Wenn via &amp;lt;code&amp;gt;setstate&amp;lt;/code&amp;gt; ein Reading gesetzt wird, kann die X_State-Funktion das Setzen dieses Readings durch die Rückgabe einer aussagekräftigen Fehlermeldung unterbinden. Sofern &amp;lt;code&amp;gt;undef&amp;lt;/code&amp;gt; zurückgegeben wird, wird das entsprechende Reading auf den übergebenen Status gesetzt.&lt;br /&gt;
&lt;br /&gt;
Wenn via &amp;lt;code&amp;gt;setstate&amp;lt;/code&amp;gt; der Definitionsstatus gesetzt wird, wird die X_State-Funktion erst nach dem Setzen des Status aufgerufen. Man kann dabei zwar eine Fehlermeldung zurückgeben. Der Status wird aber dennoch übernommen. Die Fehlermeldung wird lediglich dem Nutzer angezeigt.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_State($)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $time, $readingName, $value ) = @_;&lt;br /&gt;
&lt;br /&gt;
	return undef if($readingName &amp;quot;STATE&amp;quot; || $value ne &amp;quot;inactive&amp;quot;);&lt;br /&gt;
	readingsSingleUpdate($hash, &amp;quot;state&amp;quot;, &amp;quot;inactive&amp;quot;, 1);&lt;br /&gt;
	return undef;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== X_Authorize ====&lt;br /&gt;
TBD&lt;br /&gt;
&lt;br /&gt;
==== X_Authenticate ====&lt;br /&gt;
TBD&lt;br /&gt;
&lt;br /&gt;
== Bereitstellen eines eigenen Befehls (Befehlsmodul) ==&lt;br /&gt;
&lt;br /&gt;
Ein Modul kann primär einen neuen FHEM-Befehl bereitstellen. Man spricht in so einem Fall nicht von einem Gerätemodul, sondern einem Befehlsmodul. Ein solches Befehlsmodul stellt nur einen einzelnen Befehl bereit, der dem Modulnamen entsprechen muss. Nur, wenn der Modulname dem Befehlsname entspricht, kann FHEM das Modul beim ersten Ausführen dieses unbekannten Befehls finden und nachladen.&lt;br /&gt;
&lt;br /&gt;
Der entsprechende Befehl wird dazu in der [[#X_Initialize|Initialize]]-Funktion im globalen Hash &amp;lt;code&amp;gt;[[DevelopmentModuleIntro#Wichtige_globale_Variablen_aus_fhem.pl|%cmds]]&amp;lt;/code&amp;gt; registriert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Initialize($$) {&lt;br /&gt;
&lt;br /&gt;
	$cmds{X} = { Fn           =&amp;gt; &amp;quot;CommandX&amp;quot;,&lt;br /&gt;
	             Hlp          =&amp;gt; &amp;quot;&amp;lt;argument1&amp;gt; [optional_argument2], print something very useful&amp;quot;,&lt;br /&gt;
 &lt;br /&gt;
                     # optional&lt;br /&gt;
		     ClientFilter =&amp;gt; &amp;quot;FHEMWEB&amp;quot;&lt;br /&gt;
	           };&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Damit wird der neue Befehl &amp;lt;code&amp;gt;X&amp;lt;/code&amp;gt; in FHEM registriert. Die Funktion mit dem Namen &amp;lt;code&amp;gt;CommandX&amp;lt;/code&amp;gt; setzt diesen Befehl innerhalb des Moduls um. Desweiteren wird eine kurze Aufrufsyntax mitgegeben, welche beim Aufruf des &amp;lt;code&amp;gt;help&amp;lt;/code&amp;gt;-Befehls dem Nutzer angezeigt wird um als Gedankenstütze zu dienen. Optional kann man mittels &amp;lt;code&amp;gt;ClientFilter&amp;lt;/code&amp;gt; die Ausführbarkeit nur auf bestimmte Client-Module (wie FHEMWEB oder telnet) beschränken. &lt;br /&gt;
&lt;br /&gt;
Nun muss noch die Funktion &amp;lt;code&amp;gt;CommandX&amp;lt;/code&amp;gt; im Rahmen des Moduls implementiert werden, welche den Befehl &amp;lt;code&amp;gt;X&amp;lt;/code&amp;gt; umsetzt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
sub CommandX($$)&lt;br /&gt;
{&lt;br /&gt;
 	my ($client_hash, $arguments) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
	&lt;br /&gt;
	return $output;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dabei werden der Befehlsfunktion zwei Parameter übergeben. Zuerst die Hash-Referenz des aufrufenden Clients (sofern manuell ausgeführt, ansonsten &amp;lt;code&amp;gt;undef&amp;lt;/code&amp;gt;) zwecks Rechteprüfung via [[allowed|allowed-Definitionen]]. Anschließend folgen die Aufrufparameter als zusammenhängende Zeichenkette. Die Trennung der einzelnen Argumente obligt der Funktion (bspw. via [[DevelopmentModuleAPI#parseParams|parseParams()]]). Als Funktionsrückgabewert wird eine Ausgabemeldung erwartet, die dem Nutzer angezeigt werden soll.&lt;br /&gt;
&lt;br /&gt;
== Pollen von Geräten ==&lt;br /&gt;
Wenn Geräte von sich aus keine Informationen senden sondern abgefragt werden müssen, kann man im Modul die Funktion [[DevelopmentModuleAPI#InternalTimer|InternalTimer()]] verwenden um einen Funktionsaufruf zu einem späteren Zeitpunkt durchführen zu können. Man übergibt dabei den Zeitpunkt für den nächsten Aufruf, den Namen der Funktion, die aufgerufen werden soll, sowie den zu übergebenden Parameter. Als zu übergebender Parameter wird üblicherweise der Hash der betroffenen Geräteinstanz verwendet. Damit hat die aufgerufene Funktion Zugriff auf alle wichtigen Daten der Geräteinstanz. Eventuell zusätzlich benötigte Werte können einfach als weitere Internals über den Hash zugänglich gemacht werden.&lt;br /&gt;
&lt;br /&gt;
Beispielsweise könnte man für das Abfragen eines Geräts in der [[#X_Define|Define]]-Funktion den Timer folgendermaßen setzen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
InternalTimer(gettimeofday()+2, &amp;quot;X_GetUpdate&amp;quot;, $hash);	&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternativ kann man auch in der [[#X_Notify|Notify]]-Funktion auf das Event &amp;lt;code&amp;gt;global:INITIALIZED&amp;lt;/code&amp;gt; bzw. &amp;lt;code&amp;gt;global:REREADCFG&amp;lt;/code&amp;gt; reagieren und erst dort, den Timer anstoßen, sobald die Konfiguration komplett eingelesen wurde. Dies ist insbesondere notwendig, wenn man sicherstellen will, dass alle Attribute aus der Konfiguration gesetzt sind, sobald man einen Status-Update initiiert.&lt;br /&gt;
&lt;br /&gt;
In der Funktion &amp;lt;code&amp;gt;X_GetUpdate&amp;lt;/code&amp;gt; selbst wird dann der Timer neu gesetzt, so dass nach einem Intervall die Funktion erneut aufgerufen wird:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_GetUpdate($)&lt;br /&gt;
{&lt;br /&gt;
	my ($hash) = @_;&lt;br /&gt;
	my $name = $hash-&amp;gt;{NAME};&lt;br /&gt;
	Log3 $name, 4, &amp;quot;X: GetUpdate called ...&amp;quot;;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
	&lt;br /&gt;
	# neuen Timer starten in einem konfigurierten Interval.&lt;br /&gt;
	InternalTimer(gettimeofday()+$hash-&amp;gt;{Interval}, &amp;quot;X_GetUpdate&amp;quot;, $hash);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Innerhalb der Funktion kann man nun das Gerät abfragen und die abgefragten Werte in Readings speichern. Falls das Abfragen der Werte jedoch zu einer Verzögerung und damit zu einer Blockade von FHEM führen kann, ist es möglich, in der GetUpdate-Funktion nur die Aufforderung zum Senden bestimmter Daten an das angeschlossene Gerät zu senden und dann das Lesen über die oben beschriebene [[#X_Read|Read]]-Funktion zu implementieren.&lt;br /&gt;
&lt;br /&gt;
Eine genaue Beschreibung der Timer-Funktion gibt es [[DevelopmentModuleAPI#Timer|hier im Wiki]]&lt;br /&gt;
&lt;br /&gt;
== Logging / Debugging ==&lt;br /&gt;
Um Innerhalb eines Moduls eine Log-Meldung in die FHEM-Logdatei zu schreiben, wird die Funktion [[DevelopmentModuleAPI#Log3|Log3()]] aufgerufen.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
Log3 $name, 3, &amp;quot;X ($name) - Problem erkannt ...&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Eine genaue Beschreibung zu der Funktion inkl. Aufrufparameter findet man [[DevelopmentModuleAPI#Log3|hier]]. Es ist generell ratsam in der Logmeldung sowohl den Namen des eigenen Moduls zu schreiben, sowie den Namen des Geräts, welche diese Logmeldung produziert, da die Meldung, so wie sie ist, direkt in das Logfile wandert und es für User ohne diese Informationen schwierig ist, die Meldungen korrekt zuzuordnen.&lt;br /&gt;
&lt;br /&gt;
Die Funktion Log3() verwendet den Namen der Geräteinstanz um das &amp;lt;code&amp;gt;verbose&amp;lt;/code&amp;gt;-Attribut zu prüfen. In der Regel wird bei Modulfunktionen jedoch immer nur der Gerätehash &amp;lt;code&amp;gt;$hash&amp;lt;/code&amp;gt; übergeben. Um den Namen der Definition zu ermitteln ist es daher notwendig sich diesen aus dem Hash extrahieren:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
my $name = $hash-&amp;gt;{NAME};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Um für ein neues Modul das Verbose-Level zu erhöhen, ohne gleich für das Gesamte FHEM alle Meldungen zu erzeugen kann man den Befehl &lt;br /&gt;
&amp;lt;code&amp;gt;attr gerätename verbose&amp;lt;/code&amp;gt; verwenden. Beispielsweise &amp;lt;code&amp;gt;attr PM verbose 5&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Logmeldungen sollten je nach Art und Wichtigkeit für den Nutzer in unterschiedlichen Loglevels erzeugt werden. Es gibt insgesamt 5 Stufen in denen geloggt werden kann. Standardmäßig steht der systemweite Loglevel (&amp;lt;code&amp;gt;global&amp;lt;/code&amp;gt;-Attribut &amp;lt;code&amp;gt;verbose&amp;lt;/code&amp;gt;) auf der Stufe 3. Die Bedeutung der jeweiligen Stufen ist in der [http://fhem.de/commandref_DE.html#verbose commandref] beschrieben.&lt;br /&gt;
&lt;br /&gt;
Während der Entwicklung eines Moduls kann man für eigene Debug-Zwecke auch die Funktion [[DevelopmentModuleAPI#Debug|Debug()]] verwenden um schnell und einfach Debug-Ausgaben in das Log zu schreiben. Diese sollten in der endgültigen Fassung jedoch nicht mehr vorhanden sein. Sie dienen ausschließlich zum Debugging während der Entwicklung.&lt;br /&gt;
&lt;br /&gt;
Eine genaue Beschreibung der Log-Funktion gibt es [[DevelopmentModuleAPI#Logging|hier im Wiki]].&lt;br /&gt;
&lt;br /&gt;
== Zweistufiges Modell für Module ==&lt;br /&gt;
[[Datei:Zweistufiges Modulkonzept.jpg|mini|rechts]]&lt;br /&gt;
Es gibt viele Geräte, welche die Kommunikation mit weiteren Geräten mit tlw. unterschiedlichen Protokollen ermöglichen. Das typischste Beispiel bietet hier der [[CUL]], welcher via Funk mit verschiedenen Protokollen weitere Geräte ansprechen kann (z.B. Aktoren, Sensoren, ...). Hier bildet ein Gerät eine Brücke durch die weitere Geräte in FHEM zugänglich gemacht werden können. Dabei werden über einen Kommunikationsweg (z.B. serielle Schnittstelle, TCP, ...) beliebig viele Geräte gesteuert. Typische Beispiele dazu sind:&lt;br /&gt;
&lt;br /&gt;
* [[CUL]]: stellt Geräte mit verschiedenen Kommunikationsprotokollen via Funk bereit (u.a. [[FS20]], [[HomeMatic]], [[Funk-Heizkörperregler_Kurz-Bedienungsanleitung_FHT|FHT]], [[MAX]], ...)&lt;br /&gt;
* [[HMLAN]]: stellt HomeMatic Geräte via Funk bereit&lt;br /&gt;
* [[MAX#MAXLAN|MAXLAN]]: stellt [[MAX|MAX!]] Geräte via Funk bereit&lt;br /&gt;
* [[PanStamp#panStick.2FShield|panStamp]]: stellt weitere panStamp Geräte via Funk bereit&lt;br /&gt;
&lt;br /&gt;
Dabei wird die Kommunikation in 2 Stufen unterteilt:&lt;br /&gt;
* physisches Modul - z.B. 00_CUL.pm - zuständig für die physikalische Kommunikation mit der Hardware. Empfangene Daten müssen einem logischen Modul zugeordnet werden.&lt;br /&gt;
* logische Modul(e) - z.B. 10_FS20.pm - interpretiert protokollspezifische Nachrichten. Sendet protokollspezifische Daten über das physische Modul an die Hardware.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;physisches Modul&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das physische Modul öffnet die Datenverbindung zum Gerät (z.B. CUL) und verarbeitet sämtliche Daten. Es kümmert sich um den Erhalt der Verbindung (bsp. durch Keep-Alives) und konfiguriert das Gerät so, dass eine Kommunikation mit allen weiteren Geräten möglich ist (bsp. Frequenz, Modulation, Kanal, etc.).&lt;br /&gt;
&lt;br /&gt;
Empfangene Nutzdaten werden über die Funktion [[DevelopmentModuleAPI#Dispatch|Dispatch()]] an logische Module weitergegeben.&lt;br /&gt;
&lt;br /&gt;
Das Modul stellt eine [[#Die_Match-Liste|Match-Liste]] bereit, anhand FHEM die Nachricht einem Modul zuordnen kann, sofern dieses noch nicht geladen sein sollte. FHEM lädt dann automatisch dieses Modul nach, zwecks Verarbeitung der Nachricht. Anhand einer bereitgestellten [[#Die_Client-Liste|Client-Liste]] kann FHEM feststellen, welche logischen Module mit diesem Modul kommunizieren können.&lt;br /&gt;
&lt;br /&gt;
Das Modul stellt eine [[#X_Write|Write]]-Funktion zur Verfügung, über die logische Module Daten an die Hardware übertragen können. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;logisches Modul&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das logische Modul interpretiert die Nachricht über eine bereitgestellte [[#X_Parse|Parse]]-Funktion und erzeugt entsprechende Readings/Events. Es stellt über &amp;lt;code&amp;gt;set&amp;lt;/code&amp;gt;-/&amp;lt;code&amp;gt;get&amp;lt;/code&amp;gt;-Kommandos Steuerungsmöglichkeiten dem Nutzer zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
Es stellt FHEM einen [[#Der_Match-Ausdruck|Match-Ausdruck]] zur Verfügung anhand FHEM ermitteln kann, ob die Nachricht durch das logische Modul verarbeitet werden kann.&lt;br /&gt;
&lt;br /&gt;
=== Die Client-Liste ===&lt;br /&gt;
&lt;br /&gt;
Die Client-Liste ist eine Auflistung von Modulnamen (genauer: regulären Ausdrücken die auf Modulnamen passen) die in einem physischen Modul gesetzt ist. Damit wird definiert, mit welche logischen Modulen das physikalische Modul  kommunizieren kann. &lt;br /&gt;
&lt;br /&gt;
Eine Client-Liste ist eine Zeichenkette, welche aus allen logischen Modulnamen besteht. Die einzelnen Namen werden durch einen Doppelpunkt getrennt. Anstatt kompletter Modulnamen können auch reguläre Ausdrücke verwendet werden, die auf mehrere Modulnamen passen.&lt;br /&gt;
&lt;br /&gt;
Bsp.: Die Client-Liste von dem Modul CUL lautet daher wie folgt:&lt;br /&gt;
&lt;br /&gt;
 FS20:FHT.*:KS300:USF1000:BS:HMS:CUL_EM:CUL_WS:CUL_FHTTK:CUL_HOERMANN:ESA2000:CUL_IR:CUL_TX:Revolt:IT:UNIRoll:SOMFY:STACKABLE_CC:CUL_RFR:CUL_TCM97001:CUL_REDIRECT&lt;br /&gt;
&lt;br /&gt;
Alle hier aufgelisteten Module können über das Modul CUL Daten empfangen bzw. senden.&lt;br /&gt;
&lt;br /&gt;
Die Client-Liste hat generell folgende Funktion:&lt;br /&gt;
* Die Funktion [[DevelopmentModuleAPI#Dispatch|Dispatch()]] prüft nur Module, welche in der Client-Liste enthalten sind, ob diese die Nachricht verarbeiten können.&lt;br /&gt;
* Die Funktion [[DevelopmentModuleAPI#AssignIoPort|AssignIoPort()]] prüft anhand sämtlicher Client-Listen in FHEM, welches IO-Gerät für ein logisches Gerät nutzbar ist.&lt;br /&gt;
&lt;br /&gt;
Üblicherweise wird die Client-Liste in der [[#X_Initialize|Initialize]]-Funktion im Modul-Hash gesetzt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Initialize($)&lt;br /&gt;
{&lt;br /&gt;
	my ($hash) = @_;&lt;br /&gt;
	...&lt;br /&gt;
	$hash-&amp;gt;{Clients} = &amp;quot;FS20:KS300:FHT.*&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man kann die Client-Liste jedoch auch pro physikalisches Gerät setzen. Eine gesetzte Client-Liste in einem Gerät hat immer Vorrang vor der Liste im Modul-Hash. Eine gerätespezifische Client-Liste wird dann verwendet, wenn bspw. ein Gerät je nach Konfiguration nur bestimmte logische Module bedienen kann. Bspw. kann ein CUL je nach RF-Einstellungen FS20, uvm. oder nur HomeMatic bedienen. In einem solchen Fall wird die Client-Liste im Geräte-Hash gesetzt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Define($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $def ) = @_;&lt;br /&gt;
	...&lt;br /&gt;
	$hash-&amp;gt;{Clients} = &amp;quot;CUL_HM&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In vielen Modulen, welche nach dem zweistufigem Konzept arbeiten, beginnt und endet die Client-Liste mit einem Doppelpunkt. Dies ist ein historisches Überbleibsel, da der Prüfmechanismus die Client-Liste früher auf das Vorhandensein von &amp;lt;code&amp;gt;&#039;&#039;&#039;&amp;lt;u&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;:&amp;lt;/font&amp;gt;&amp;lt;/u&amp;gt;&#039;&#039;&#039;&amp;amp;lt;Modulname&amp;amp;gt;&#039;&#039;&#039;&amp;lt;u&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;:&amp;lt;/font&amp;gt;&amp;lt;/u&amp;gt;&#039;&#039;&#039;&amp;lt;/code&amp;gt; prüfte. Dies ist nun nicht mehr notwendig. Die einzelnen Modulnamen müssen lediglich durch einen Doppelpunkt getrennt werden.&lt;br /&gt;
&lt;br /&gt;
=== Die Match-Liste ===&lt;br /&gt;
{{Randnotiz|RNTyp=Info|RNText=&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&amp;lt;u&amp;gt;&#039;&#039;&#039;ACHTUNG&#039;&#039;&#039;:&amp;lt;/u&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
Sämtliche regulären Ausdrücke in der Match-Liste werden &amp;quot;case insensitive&amp;quot; überprüft. Das bedeutet, dass Groß-/Kleinschreibung nicht berücksichtigt wird.&lt;br /&gt;
&lt;br /&gt;
Um dennoch in einem regulären Ausdruck auf Groß-/Kleinschreibung zu prüfen, kann man dieses mit dem Modifizierer &amp;lt;code&amp;gt;(?-i)&amp;lt;/code&amp;gt; wieder aktivieren:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
my %matchListFHEMduino = (&lt;br /&gt;
    ....&lt;br /&gt;
    &amp;quot;5:FHEMduino_PT2262&amp;quot;   =&amp;gt; &amp;quot;^(?-i)IR.*\$&amp;quot;,&lt;br /&gt;
    ....&lt;br /&gt;
    &amp;quot;13:IT&amp;quot;                =&amp;gt; &amp;quot;^(?-i)i......\$&amp;quot;,&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Siehe dazu Forumsbeitrag: {{Link2Forum|Topic=33422}}&lt;br /&gt;
}}&lt;br /&gt;
Die Match-Liste ordnet eine Nachrichtensyntax (regulärer Ausdruck) einem Modulnamen zu und wird in einem physikalischen Modul gesetzt. Sollte eine Nachricht vom physikalischen Gerät empfangen werden, die durch kein geladenes Modul verarbeitet werden kann, so wird über die Match-Liste geprüft, welches Modul diese Nachricht verarbeiten kann. Dieses Modul wird anschließend geladen und die Nachricht durch dieses verarbeitet. In dieser Liste findet mittels regulärem Ausdruck eine Zuordnung der Nachrichtenstruktur zum verarbeitenden logischen Modul statt.&lt;br /&gt;
&lt;br /&gt;
Diese Liste wird ausschließlich in der [[DevelopmentModuleAPI#Dispatch|Dispatch()]]-Funktion verwendet. Sollte keine passendes Modul, welches bereits geladen ist, zur Verarbeitung einer Nachricht gefunden werden, so wird mithilfe der Match-Liste aufgrund der vorliegenden Nachricht das entsprechende Modul ermittelt. Dieses Modul wird dann direkt geladen und die Nachricht wird via [[#X_Parse|Parse]]-Funktion verarbeitet.&lt;br /&gt;
&lt;br /&gt;
Die Match-Liste ist eine Zuordnung von einem Sortierpräfix + Modulname zu einem regulären Ausdruck:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;1:FS20&amp;quot;  =&amp;gt; &amp;quot;^81..(04|0c)..0101a001&amp;quot;,&lt;br /&gt;
    &amp;quot;2:KS300&amp;quot; =&amp;gt; &amp;quot;^810d04..4027a001&amp;quot;,&lt;br /&gt;
    &amp;quot;3:FHT&amp;quot;   =&amp;gt; &amp;quot;^81..(04|09|0d)..(0909a001|83098301|c409c401)..&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Sortierpräfix dient als Sortierhilfe um so die Reihenfolge der Prüfung festzulegen. Bei der Prüfung wird der Hash mittels sort() sortiert und die regulären Ausdrücke werden dann nacheinander getestet. Daher sollten die präzisesten Ausdrücke immer zuerst getestet werden, sofern es weniger präzise Ausdrücke in der Match-Liste gibt. Dabei ist zu beachten, dass der Sortierpräfix nicht nach numerischen Regeln sortiert wird, sondern basierend auf der Zeichenreihenfolge.&lt;br /&gt;
&lt;br /&gt;
Üblicherweise wird die Match-Liste in der [[#X_Initialize|Initialize]]-Funktion im Modul-Hash gesetzt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Initialize($)&lt;br /&gt;
{&lt;br /&gt;
	my ($hash) = @_;&lt;br /&gt;
&lt;br /&gt;
	...&lt;br /&gt;
&lt;br /&gt;
	$hash-&amp;gt;{MatchList} = { &amp;quot;1:FS20&amp;quot;      =&amp;gt; &amp;quot;^81..(04|0c)..0101a001&amp;quot;,&lt;br /&gt;
			       &amp;quot;2:KS300&amp;quot;     =&amp;gt; &amp;quot;^810d04..4027a001&amp;quot;,&lt;br /&gt;
			       &amp;quot;3:FHT&amp;quot;       =&amp;gt; &amp;quot;^81..(04|09|0d)..(0909a001|83098301|c409c401)..&amp;quot; };&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man kann die Match-Liste, ähnlich wie bei der Client-Liste, auch pro physikalisches Gerät setzen. Dabei hat auch hier die Match-Liste eines Gerätes immer Vorrang vor der Match-Liste aus dem Modul-Hash:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Define($$)&lt;br /&gt;
{&lt;br /&gt;
	my ($hash, $def) = @_;&lt;br /&gt;
&lt;br /&gt;
	...&lt;br /&gt;
&lt;br /&gt;
	$hash-&amp;gt;{MatchList} = { &amp;quot;1:CUL_HM&amp;quot; =&amp;gt; &amp;quot;^A....................&amp;quot; };&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Der Match-Ausdruck ===&lt;br /&gt;
&lt;br /&gt;
Ein Match-Ausdruck wird in einem logischen Modul gesetzt und dient der Prüfung, ob eine Nachricht durch das eigene Modul via [[#X_Parse|Parse]]-Funktion verarbeitet werden kann. Es handelt sich hierbei um einen einzelnen regulären Ausdruck, den FHEM innerhalb der [[DevelopmentModuleAPI#Dispatch|Dispatch()]]-Funktion prüft. Nur wenn eine Nachricht via Dispatch() auf diesen Audruck matcht, wird die Parse-Funktion aufgerufen um die Nachricht zu verarbeiten. &lt;br /&gt;
&lt;br /&gt;
Der Hintergrund, warum man den Aufruf mit einem solchen Ausdruck vorher abprüft, liegt in der Möglichkeit, dass ein physikalisches Modul mehrere unterschiedliche logische Module ansprechen kann. So kann FHEM jedes geladene Modul durch diesen Match-Ausdruck prüfen, ob es diese Nachricht verarbeiten kann. Erst, wenn alle geladenen Module, aufgrund einer Prüfung des Ausdrucks, die Nachricht nicht verarbeiten können, wird via [[#Die_Match-Liste|Match-Liste]] ermittelt, welches Modul geladen werden muss um die Nachricht zu verarbeiten. &lt;br /&gt;
&lt;br /&gt;
Der Match-Ausdruck wird in der [[#X_Initialize|Initialize]]-Funktion zur Verfügung gestellt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Initialize($)&lt;br /&gt;
{&lt;br /&gt;
	my ($hash) = @_;&lt;br /&gt;
&lt;br /&gt;
	...&lt;br /&gt;
	&lt;br /&gt;
	# Dieses Modul verarbeitet FS20 Nachrichten&lt;br /&gt;
	$hash-&amp;gt;{Match} = &amp;quot;^81..(04|0c)..0101a001&amp;quot;; &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Die vollständige Implementierung ===&lt;br /&gt;
&lt;br /&gt;
Hier nun eine Zusammenfassung beim zweistufigen Modulkonzept in der jeweiligen Stufe implementiert werden muss, damit die Kommunikation funktioniert.&lt;br /&gt;
&lt;br /&gt;
==== physisches Modul ====&lt;br /&gt;
&lt;br /&gt;
Das physische Modul, welches als Kommunikationsbrücke zwischen der Hardware und logischen Modulen fungieren wird, sollte mindestens folgende Funktionen implementieren:&lt;br /&gt;
&lt;br /&gt;
* [[#X_Initialize|Initialize]]-Funktion - Zum Registrieren des Moduls in FHEM.&lt;br /&gt;
* [[#X_Define|Define]]-Funktion - Zum öffnen der Datenverbindung zur Hardware (IP-Adresse/serielle Schnittstelle/...).&lt;br /&gt;
* [[#X_Read|Read]]-Funktion - Zum Lesen von Daten, welche die Hardware übermittelt.&lt;br /&gt;
* [[#X_Read|Ready]]-Funktion - Zum Wiederaufbau der Verbindung bei Verbindungsabbruch, bzw. Prüfung auf lesbare Daten bei serieller Schnittstelle unter Windows.&lt;br /&gt;
* [[#X_Write|Write]]-Funktion - Zum Senden von Daten, welche logische Module via [[DevelopmentModuleAPI#IOWrite|IOWrite()]] an die Hardware übertragen möchten.&lt;br /&gt;
* [[#X_Undef|Undef]]-Funktion - Schließen der Verbindung zur Hardware beim Löschen via &amp;lt;code&amp;gt;delete&amp;lt;/code&amp;gt; bzw. &amp;lt;code&amp;gt;rereadcfg&amp;lt;/code&amp;gt;.&lt;br /&gt;
* [[#X_Shutdown|Shutdown]]-Funktion - Schließen der Verbindung zur Hardware beim Stopp von FHEM via &amp;lt;code&amp;gt;shutdown&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Desweiteren müssen in der [[#X_Initialize|Initialize]]-Funktion folgende Daten bereitgestellt werden:&lt;br /&gt;
&lt;br /&gt;
* [[#Die_Client-Liste|Client-Liste]] - Auflistung aller logischen Module, die über dieses Modul kommunizieren können&lt;br /&gt;
* [[#Die_Match-Liste|Match-Liste]] - Zuordnung von Nachrichtensyntax zu Modul zwecks Autoload-Funktionalität.&lt;br /&gt;
&lt;br /&gt;
==== logisches Modul ====&lt;br /&gt;
&lt;br /&gt;
Das logische Modul, bildet ein einzelnes Gerät ab, über das mit einem physikalisches Modul kommuniziert werden kann. Es sollte mindestens folgende Funktionen implementieren:&lt;br /&gt;
&lt;br /&gt;
* [[#X_Initialize|Initialize]]-Funktion - Zum Registrieren des Moduls in FHEM.&lt;br /&gt;
* [[#X_Define|Define]]-Funktion - Speichern des Definition Pointers (siehe [[#X_Parse|Parse-Funktion]])&lt;br /&gt;
* [[#X_Parse|Parse]]-Funktion - Zum Lesen von Daten, welche die Hardware übermittelt.&lt;br /&gt;
* [[#X_Undef|Undef]]-Funktion - Löschen des Definition Pointers beim Löschen via &amp;lt;code&amp;gt;delete&amp;lt;/code&amp;gt; bzw. &amp;lt;code&amp;gt;rereadcfg&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Desweiteren müssen in der [[#X_Initialize|Initialize]]-Funktion folgende Daten bereitgestellt werden:&lt;br /&gt;
&lt;br /&gt;
* [[#Der_Match-Ausdruck|Match-Ausdruck]] - Prüfausdruck, ob eine Nachricht durch dieses Modul verarbeitet werden kann.&lt;br /&gt;
&lt;br /&gt;
=== Kommunikation von der Hardware bis zu den logischen Modulen ===&lt;br /&gt;
&lt;br /&gt;
Die Gerätedefinition eines physische Moduls öffnet eine Verbindung zur Hardware. Die [[#X_Read|Read]]-Funktion wird bei anstehenden Daten aus der Hauptschleife von fhem.pl aufgerufen.&lt;br /&gt;
&lt;br /&gt;
Die Read-Funktion stellt dabei sicher, dass die Daten&lt;br /&gt;
* komplett (in der Regel über einen internen Puffer in &amp;lt;code&amp;gt;$hash&amp;lt;/code&amp;gt;) und&lt;br /&gt;
* korrekt (z.B. via Prüfung mittels regulärem Ausdruck)&lt;br /&gt;
sind und ruft die globale Funktion [[DevelopmentModuleAPI#Dispatch|Dispatch()]] mit einer kompletten Nachricht auf.&lt;br /&gt;
&lt;br /&gt;
Die Funktion Dispatch() sucht nach einer passenden Definition via [[#Die_Client-Liste|Client-Liste]] in physischen Definitionen/Modulen nach möglichen logischen Modulen zur Verarbeitung. Alle zum Zeitpunkt geladenen Module, die in der Client-Liste aufgeführt sind, werden über den [[#Der_Match-Ausdruck|Match-Ausdruck]] geprüft, ob sie mit der Nachricht etwas anfangen können. Sollte bei einem Modul der Match-Ausdruck passen, so wird die entsprechende [[#X_Parse|Parse]]-Funktion des logischen Moduls aufgerufen. Sofern keine passendes Modul gefunden wurde, um die Nachricht zu verarbeiten, wird in der [[#Die_Match-Liste|Match-Liste]] im Geräte- bzw. Modul-Hash der physischen Gerätedefinition nach dem passenden Modul gesucht. Sollte es darin ein Modul geben, was diese Art von Nachricht verarbeiten kann, so wird versucht dieses Modul zu laden um nun die Nachricht via Parse-Funktion zu verarbeiten. Es erfolgt in diesem Fall keine Vorprüfung durch den Match-Ausdruck.&lt;br /&gt;
&lt;br /&gt;
Durch Dispatch() wird nun die [[#X_Parse|Parse]]-Funktion des gefundenen logischen Moduls aufgerufen. Diese&lt;br /&gt;
* interpretiert die übergebene Nachricht,&lt;br /&gt;
* versucht eine existierende Gerätedefinition in FHEM zu finden (z.B. mittels Definition Pointer), für welche die Nachricht addressiert ist,&lt;br /&gt;
* setzt alle [[#Readings|Readings]] für die gefundene Gerätedefinition via [[DevelopmentModuleAPI#Readings_.2F_Events|readings*update]]()-Funktionen,&lt;br /&gt;
* gibt den Namen der logischen Definition zurück, welche die Nachricht verarbeitet hat.&lt;br /&gt;
&lt;br /&gt;
Sollte keine passende Gerätedefinition für die entsprechende Nachricht existieren (Adresse/ID/Kanal/...), wird der Gerätename &amp;quot;UNDEFINED&amp;quot; inkl. einem passenden &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt;-Statement zurückgegeben, um die Definition durch [[autocreate]] erzeugen zu lassen.&lt;br /&gt;
&lt;br /&gt;
Es findet während der Verarbeitung einer Nachricht durch Dispatch()/Parse-Funktion keine sofortige Eventverarbeitung (via [[DevelopmentModuleAPI#Dispatch|DoTrigger()]]) statt, wenn die [[DevelopmentModuleAPI#Readings_.2F_Events|readings*update]]()-Funktionen verwendet werden.&lt;br /&gt;
(Im Gegensatz zum direkten Aufrufen der readings*update Funktionen ohne vorhergehendes Dispatch() )&lt;br /&gt;
&lt;br /&gt;
Die Funktion Dispatch() triggert das Event-Handling für das von der Parse-Funktion zurückgegebene logische Device selbstständig.&lt;br /&gt;
&lt;br /&gt;
Optional führt die Funktion Dispatch() eine Überprüfung auf Nachrichtenduplikate beim Einsatz von mehreren IO-Geräten durch. Dazu wird eine implementierte [[#X_Fingerprint|Fingerprint]]-Funktion im physischen oder logischen Modul benötigt.&lt;br /&gt;
&lt;br /&gt;
=== Kommunikation von den logischen Modulen bis zur Hardware ===&lt;br /&gt;
&lt;br /&gt;
Um von einem logischen Modul eine Nachricht an die Hardware senden zu können, muss zunächst im logischen Gerät ein passenden IO-Gerät ausgewählt sein. Dazu muss die Funktion [[DevelopmentModuleAPI#AssignIoPort|AssignIoPort()]] ein entsprechendes IO-Gerät auswählen und in &amp;lt;code&amp;gt;$hash-&amp;gt;{IODev}&amp;lt;/code&amp;gt; setzen. Dieser Aufruf wird üblicherweise in der [[#X_Define|Define]]-Funktion des logischen Moduls ausgeführt. Erst, wenn ein IO-Gerät ausgewählt wurde, können Daten über das physikalische Gerät an die Hardware übermittelt werden.&lt;br /&gt;
&lt;br /&gt;
Zum Senden von Daten ruft das logische Modul die Funktion [[DevelopmentModuleAPI#IOWrite|IOWrite()]] samt Daten auf. Diese ruft für das entsprechende IO-Gerät die [[#X_Write|Write]]-Funktion auf und übergibt die Daten zum Schreiben an das physikalische Modul. Die Write-Funktion kümmert sich nun um die Übertragung der Daten an die Hardware. &lt;br /&gt;
&lt;br /&gt;
Keine direkten Zugriffe zwischen dem logischen und dem physischen Gerät gibt (d.h. keine direkten Aufrufe von Funktionen, kein direktes Überprüfen von &amp;lt;code&amp;gt;$hash&amp;lt;/code&amp;gt;-Inhalten, ...), so können die Module hintereinander geschaltet werden (z.B. für Routerfunktionen wie bei der [[RFR_CUL|RFR]]-Funktionalität) oder mittels [[FHEM2FHEM]] im RAW-Modus zwei FHEM-Installationen verbunden werden und die logischen Geräte können dennoch kommunizieren.&lt;br /&gt;
&lt;br /&gt;
=== Automatisches Anlegen von logischen Gerätedefinitionen (autocreate) ===&lt;br /&gt;
&lt;br /&gt;
Das logische Modul kann im Rahmen der [[#X_Parse|Parse]]-Funktion eine neue Gerätedefinition anlegen, sofern eine passende Definition nicht existieren sollte. Die Parse-Funktion gibt generell den Namen der logischen Gerätedefinition zurück, für welche die Nachricht verarbeitet wurde. Sollte keine passende Definition gefunden werden, so muss die Parse-Funktion folgenden Rückgabewert liefern (zusammenhängende Zeichenkette):&lt;br /&gt;
&lt;br /&gt;
 UNDEFINED &#039;&#039;&amp;amp;lt;Namensvorschlag&amp;amp;gt;&#039;&#039; &#039;&#039;&amp;amp;lt;Modulname&amp;amp;gt;&#039;&#039; &#039;&#039;&amp;amp;lt;Define-Parameter&amp;amp;gt;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Sollte also bspw. im Rahmen der Parse-Funktion zu Modul X eine Nachricht nicht einer existierenden Gerätedefinition zugeordnet werden können, so muss ein Namensvorschlag erstellt werden der eine eindeutige Komponente wie bspw. eine Adresse/ID/Kanal-Nr enthält. In der Regel wird hier immer der Modulname zusammen mit der eindeutigen Komponente, durch einen Unterstrich getrennt, verwendet (Bsp: &amp;lt;code&amp;gt;X_4834&amp;lt;/code&amp;gt;). Der Modulname ist in der Regel immer der, des eigenen Moduls. In besonderen Fällen kann man hier auch einen abweichenden Modulnamen angeben. Dies wird bspw. bei den [[PanStamp#FHEM-Module.2FDevice_Definition_Files|SWAP-Modulen]] eingesetzt. Als Define-Parameter müssen alle notwendigen Parameter angegeben werden, die beim Aufruf des &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt;-Befehls notwendig sind, damit eine neu angelegte Gerätedefinition Nachrichten zu dieser eindeutigen Adresse Daten verarbeitet. Dazu muss mind. die eindeutige Adresse mitgegeben werden.&lt;br /&gt;
&lt;br /&gt;
Beispiel für FS20:&lt;br /&gt;
&lt;br /&gt;
 UNDEFINED FS20_0ae42f8 FS20 0ae42 f8&lt;br /&gt;
&lt;br /&gt;
Sobald [[DevelopmentModuleAPI#Dispatch|Dispatch()]] einen solchen Rückgabewert von einer [[#X_Parse|Parse]]-Funktion erhält, wird diese Zeichenkette so wie sie ist via [[DevelopmentModuleAPI#DoTrigger|DoTrigger()]] als Event für die Definition &amp;lt;code&amp;gt;global&amp;lt;/code&amp;gt; getriggert.&lt;br /&gt;
&lt;br /&gt;
Sofern der Nutzer das Modul [[autocreate]] verwendet (definiert hat), kümmert sich dieses nun um das Anlegen einer entsprechenden Gerätedefinition. Es lauscht dabei auf generierte Events der Definition &amp;lt;code&amp;gt;global&amp;lt;/code&amp;gt; via [[#X_Notify|Notify]]-Funktion. Der Nutzer kann dabei das Verhalten von autocreate durch entsprechende Parameter beeinflussen.&lt;br /&gt;
&lt;br /&gt;
Das Modul, für welches autocreate eine neue Definition anlegen möchte, kann das Verhalten durch entsprechende Parameter im Modul-Hash beeinflussen. Dabei gilt, dass gesetzte Attribute durch den Nutzer generell Vorrang haben. Die entsprechenden Parameter werden dabei im Rahmen der [[#X_Initialize|Initialize]]-Funktion im Modul-Hash gesetzt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Initialize($)&lt;br /&gt;
{&lt;br /&gt;
	my ($hash) = @_;&lt;br /&gt;
 &lt;br /&gt;
	...&lt;br /&gt;
 &lt;br /&gt;
	$hash-&amp;gt;{AutoCreate} = {&amp;quot;X_.*&amp;quot;  =&amp;gt; { ATTR   =&amp;gt; &amp;quot;event-on-change-reading:.* event-min-interval:.*:300&amp;quot;,&lt;br /&gt;
	                                    FILTER =&amp;gt; &amp;quot;%NAME&amp;quot;,&lt;br /&gt;
	                                    GPLOT  =&amp;gt; &amp;quot;temp4hum4:Temp/Hum,&amp;quot;,&lt;br /&gt;
	                                    autocreateThreshold =&amp;gt; &amp;quot;2:140&amp;quot;&lt;br /&gt;
					  }&lt;br /&gt;
	                      };&lt;br /&gt;
			    &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hierbei wird unterhalb von &amp;lt;code&amp;gt;$hash-&amp;gt;{AutoCreate}&amp;lt;/code&amp;gt; eine Liste angelegt, wo einem regulären Ausdruck für einen anzulegenden Definitionsnamen entsprechende Optionen zugeordnet werden. Sobald durch autocreate eine Gerätedefintion angelegt wird, auf den ein hier gelisteter Ausdruck matcht, so werden die zugeordneten Optionen berücksichtigt.&lt;br /&gt;
&lt;br /&gt;
Hier eine Auflistung aller möglichen Optionen und ihrer Bedeutung:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Optionsname !! Beispiel !! Bedeutung&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ATTR&amp;lt;/code&amp;gt;|| &amp;lt;code&amp;gt;&amp;quot;event-on-change-reading:.* event-min-interval:.*:300&amp;quot;&amp;lt;/code&amp;gt; || Eine Auflistung von Attributen, die nach dem Anlegen einer Definition zusätzlich gesetzt werden. Es handelt sich hierbei um eine Leerzeichen-separierte Liste von Doppelpunkt-getrennten Tupels mit Attributname und -wert.&lt;br /&gt;
&lt;br /&gt;
Für das dargestellte Beispiel bedeutet dies, dass nach dem Anlegen der Definition folgende FHEM-Befehle zusätzlich ausgeführt werden:&lt;br /&gt;
&lt;br /&gt;
 attr &#039;&#039;&amp;amp;lt;Name&amp;amp;gt;&#039;&#039; event-on-change-reading .*&lt;br /&gt;
 attr &#039;&#039;&amp;amp;lt;Name&amp;amp;gt;&#039;&#039; event-min-interval .*:300&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FILTER&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;%NAME&amp;lt;/code&amp;gt;|| Sofern in der autocreate-Definiton das Attribut &amp;lt;code&amp;gt;filelog&amp;lt;/code&amp;gt; entsprechend durch den Nutzer gesetzt ist, wird eine zugehörige FileLog-Definition angelegt. Diese Option setzt den dabei benutzten Filter-Regexp, der beim Anlegen der FileLog-Definition gesetzt wird. &lt;br /&gt;
&lt;br /&gt;
Dabei werden folgende Platzhalter durch die entsprechenden Werte der neu angelegten Gerätedefinition ersetzt:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;%NAME&amp;lt;/code&amp;gt; - wird ersetzt durch den Definitionsnamen&lt;br /&gt;
* &amp;lt;code&amp;gt;%TYPE&amp;lt;/code&amp;gt; - wird ersetzt durch den Modulnamen&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;GPLOT&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;temp4hum4:Temp/Hum,&amp;quot;&amp;lt;/code&amp;gt; || Sofern eine FileLog-Definition angelegt wurde, kann man weiterführend dazu eine passende SVG-Definition erzeugen um Daten aus dem erzeugten FileLog zu visualisieren. Ein typischer Fall sind hierbei Temperatursensoren, wo es sinnvoll sein kann, einen passenden SVG-Plot mit Temperatur/Luftfeuchtigkeit direkt anzulegen.&lt;br /&gt;
&lt;br /&gt;
Es handelt sich hierbei um eine kommaseparierte Auflistung von gplot-Dateinamen und optionalen Label-Texten durch einen Doppelpunkt getrennt. Im genannten Beispiel entspricht &amp;lt;code&amp;gt;temp4hum4&amp;lt;/code&amp;gt; der zu verwendenden GnuPlot-Datei und &amp;lt;code&amp;gt;Temp/Hum&amp;lt;/code&amp;gt; dem zu verwendenden Label ([[SVG]] Attribut &amp;lt;code&amp;gt;label&amp;lt;/code&amp;gt;). Das Label wird auch durch FileLog verwendet als Link-Text zum entsprechenden SVG Plot. Alternativ kann auch nur die entsprechende GnuPlot-Datei anegeben werden ohne Label. Für jede angegebene GnuPlot-Datei wird anschließend eine entsprechende SVG-Definition erzeugt mit der vorher erzeugten FileLog-Definition als Datenquelle.&lt;br /&gt;
&lt;br /&gt;
Der gesamte Inhalt der &amp;lt;code&amp;gt;GPLOT&amp;lt;/code&amp;gt;-Option wird beim Anlegen einer FileLog-Definition dem Attribut &amp;lt;code&amp;gt;logtype&amp;lt;/code&amp;gt; als Wert plus dem Text &amp;lt;code&amp;gt;text&amp;lt;/code&amp;gt; zugewiesen. Daher muss der Inhalt der Option &amp;lt;code&amp;gt;GPLOT&amp;lt;/code&amp;gt; immer mit einem Komma enden. &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;autocreateThreshold&amp;lt;/code&amp;gt;|| &amp;lt;code&amp;gt;&amp;quot;2:10&amp;quot;|| Definiert, wie viele Aufrufe (im Bsp: &amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt;) von autocreate innerhalb welcher Zeit (im Bsp: &amp;lt;code&amp;gt;10&amp;lt;/code&amp;gt; Sek.) stattfinden müssen, bevor die Gerätedefinition tatsächlich durch autocreate angelegt wird. Dadurch kann das ungewollte Anlegen von Geräten verhindert werden die tatsächlich nicht in Echt existieren. Aufgrund von Funkstörungen kann es durchaus zum ungewollten Anlegen einer Definition kommen. Diese Funktion lässt eine Definition erst zu wenn innerhalb einer vorgegeben Zeit eine Mindestzahl an Nachrichten eintrifft.&lt;br /&gt;
&lt;br /&gt;
Die erste Zahl stellt dabei die Mindestanzahl an Nachrichten dar. Die Zweite Zahl stellt die Zeit in Sekunden dar, in der die Mindestanzahl an Nachrichten erreicht werden muss um eine entsprechende Gerätedefinition anzulegen. &lt;br /&gt;
&lt;br /&gt;
Sofern diese Option nicht gesetzt ist, wird standardmäßig &amp;lt;code&amp;gt;2:60&amp;lt;/code&amp;gt; verwendet.&lt;br /&gt;
&lt;br /&gt;
Diese Option kann durch den Anwender über das Attribut &amp;lt;code&amp;gt;autocreateThreshold&amp;lt;/code&amp;gt; übersteuert werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sofern diese Option nicht gesetzt ist&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;noAutocreatedFilelog&amp;lt;/code&amp;gt;|| &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;|| Flag. Sofern gesetzt, wird keine FileLog- und ggf. SVG-Definition erzeugt. Selbst wenn der Nutzer durch entsprechende Attribute das Anlegen wünscht. Diese Option ist sinnvoll für Module bzw. Geräte die keine Readings erzeugen.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Ergänzende Hinweise ==&lt;br /&gt;
Die Wahl der vorangestellten Nummer für den Dateinamen eines neuen Moduls hat keine Bedeutung mehr, es sei denn die Nummer ist 99. Module, die mit 99_ beginnen, werden von FHEM automatisch geladen. Module mit einer anderen Nummer nur wenn ein &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt;-Befehl dafür sorgt, dass das Modul geladen wird.&lt;br /&gt;
&lt;br /&gt;
Wenn ein Modul Initialisierungsdaten benötigt, sollten diese im Modul selbst enthalten sein. Eine zusätzliche Datei oder sogar ein Unterverzeichnis mit mehreren Dateien ist bei FHEM nicht üblich und sollte bei Modulen, die mit FHEM ausgeliefert werden nur in Rücksprache mit Rudolf König angelegt werden, da sie sonst bei einem Update nicht verteilt werden.&lt;br /&gt;
&lt;br /&gt;
== Weitere Informationen ==&lt;br /&gt;
Wenn man weitere Details wissen möchte, ist ein erster sinnvoller Schritt ein Blick in die Datei fhem.pl. Dort sieht man im Perl-Code wie die Module aufgerufen werden, was vorher passiert und was danach. Am Anfang der Datei (ca. ab Zeile 130) findet man beispielsweise eine Liste der globalen Variablen, die den Modulen zur Verfügung stehen sowie Details zu den wichtigen Hashes %modules und %defs. Wer mit Perl noch nicht so gut klar kommt, dem hilft eventuell ein Blick auf die Perldoc Website[http://perldoc.perl.org/] oder in das Perl-Buch seiner Wahl. Auch die FHEM Commandref [http://fhem.de/commandref.html] sollte nicht unterschätzt werden. Es stehen oft mehr interessante Details auch für Modulentwickler darin als man zunächst vermuten könnte.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== &amp;quot;Hello World&amp;quot; Beispiel ==&lt;br /&gt;
&lt;br /&gt;
98_Hello.pm&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
package main;&lt;br /&gt;
use strict;&lt;br /&gt;
use warnings;&lt;br /&gt;
&lt;br /&gt;
my %Hello_gets = (&lt;br /&gt;
	&amp;quot;whatyouwant&amp;quot;	=&amp;gt; &amp;quot;can&#039;t&amp;quot;,&lt;br /&gt;
	&amp;quot;whatyouneed&amp;quot;	=&amp;gt; &amp;quot;try sometimes&amp;quot;,&lt;br /&gt;
	&amp;quot;satisfaction&amp;quot;  =&amp;gt; &amp;quot;no&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
sub Hello_Initialize($) {&lt;br /&gt;
    my ($hash) = @_;&lt;br /&gt;
&lt;br /&gt;
    $hash-&amp;gt;{DefFn}      = &#039;Hello_Define&#039;;&lt;br /&gt;
    $hash-&amp;gt;{UndefFn}    = &#039;Hello_Undef&#039;;&lt;br /&gt;
    $hash-&amp;gt;{SetFn}      = &#039;Hello_Set&#039;;&lt;br /&gt;
    $hash-&amp;gt;{GetFn}      = &#039;Hello_Get&#039;;&lt;br /&gt;
    $hash-&amp;gt;{AttrFn}     = &#039;Hello_Attr&#039;;&lt;br /&gt;
    $hash-&amp;gt;{ReadFn}     = &#039;Hello_Read&#039;;&lt;br /&gt;
&lt;br /&gt;
    $hash-&amp;gt;{AttrList} =&lt;br /&gt;
          &amp;quot;formal:yes,no &amp;quot;&lt;br /&gt;
        . $readingFnAttributes;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub Hello_Define($$) {&lt;br /&gt;
    my ($hash, $def) = @_;&lt;br /&gt;
    my @param = split(&#039;[ \t]+&#039;, $def);&lt;br /&gt;
    &lt;br /&gt;
    if(int(@param) &amp;lt; 3) {&lt;br /&gt;
        return &amp;quot;too few parameters: define &amp;lt;name&amp;gt; Hello &amp;lt;greet&amp;gt;&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    my $hash-&amp;gt;{name}  = $param[0];&lt;br /&gt;
    my $hash-&amp;gt;{greet} = $param[2];&lt;br /&gt;
    &lt;br /&gt;
    return undef;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub Hello_Undef($$) {&lt;br /&gt;
    my ($hash, $arg) = @_; &lt;br /&gt;
    # nothing to do&lt;br /&gt;
    return undef;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub Hello_Get($@) {&lt;br /&gt;
	my ($hash, @param) = @_;&lt;br /&gt;
	&lt;br /&gt;
	return &#039;&amp;quot;get Hello&amp;quot; needs at least one argument&#039; if (int(@param) &amp;lt; 2);&lt;br /&gt;
	&lt;br /&gt;
	my $name = shift @param;&lt;br /&gt;
	my $opt = shift @param;&lt;br /&gt;
	if(!$Hello_gets{$opt}) {&lt;br /&gt;
		my @cList = keys %Hello_gets;&lt;br /&gt;
		return &amp;quot;Unknown argument $opt, choose one of &amp;quot; . join(&amp;quot; &amp;quot;, @cList);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	if($attr{$name}{formal} eq &#039;yes&#039;) {&lt;br /&gt;
	    return $Hello_gets{$opt}.&#039;, sir&#039;;&lt;br /&gt;
    }&lt;br /&gt;
	return $Hello_gets{$opt};&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub Hello_Set($@) {&lt;br /&gt;
	my ($hash, @param) = @_;&lt;br /&gt;
	&lt;br /&gt;
	return &#039;&amp;quot;set Hello&amp;quot; needs at least one argument&#039; if (int(@param) &amp;lt; 2);&lt;br /&gt;
	&lt;br /&gt;
	my $name = shift @param;&lt;br /&gt;
	my $opt = shift @param;&lt;br /&gt;
	my $value = join(&amp;quot;&amp;quot;, @param);&lt;br /&gt;
	&lt;br /&gt;
	if(!defined($Hello_gets{$opt})) {&lt;br /&gt;
		my @cList = keys %Hello_gets;&lt;br /&gt;
		return &amp;quot;Unknown argument $opt, choose one of &amp;quot; . join(&amp;quot; &amp;quot;, @cList);&lt;br /&gt;
	}&lt;br /&gt;
    $hash-&amp;gt;{STATE} = $Hello_gets{$opt} = $value;&lt;br /&gt;
    &lt;br /&gt;
	return &amp;quot;$opt set to $value. Try to get it.&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
sub Hello_Attr(@) {&lt;br /&gt;
	my ($cmd,$name,$attr_name,$attr_value) = @_;&lt;br /&gt;
	if($cmd eq &amp;quot;set&amp;quot;) {&lt;br /&gt;
        if($attr_name eq &amp;quot;formal&amp;quot;) {&lt;br /&gt;
			if($attr_value !~ /^yes|no$/) {&lt;br /&gt;
			    my $err = &amp;quot;Invalid argument $attr_value to $attr_name. Must be yes or no.&amp;quot;;&lt;br /&gt;
			    Log 3, &amp;quot;Hello: &amp;quot;.$err;&lt;br /&gt;
			    return $err;&lt;br /&gt;
			}&lt;br /&gt;
		} else {&lt;br /&gt;
		    return &amp;quot;Unknown attr $attr_name&amp;quot;;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	return undef;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&lt;br /&gt;
=pod&lt;br /&gt;
=begin html&lt;br /&gt;
&lt;br /&gt;
&amp;lt;a name=&amp;quot;Hello&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Hello&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
    &amp;lt;i&amp;gt;Hello&amp;lt;/i&amp;gt; implements the classical &amp;quot;Hello World&amp;quot; as a starting point for module development. &lt;br /&gt;
    You may want to copy 98_Hello.pm to start implementing a module of your very own. See &lt;br /&gt;
    &amp;lt;a href=&amp;quot;http://wiki.fhem.de/wiki/DevelopmentModuleIntro&amp;quot;&amp;gt;DevelopmentModuleIntro&amp;lt;/a&amp;gt; for an &lt;br /&gt;
    in-depth instruction to your first module.&lt;br /&gt;
    &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
    &amp;lt;a name=&amp;quot;Hellodefine&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
    &amp;lt;b&amp;gt;Define&amp;lt;/b&amp;gt;&lt;br /&gt;
    &amp;lt;ul&amp;gt;&lt;br /&gt;
        &amp;lt;code&amp;gt;define &amp;amp;lt;name&amp;amp;gt; Hello &amp;amp;lt;greet&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
        &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
        Example: &amp;lt;code&amp;gt;define HELLO Hello TurnUrRadioOn&amp;lt;/code&amp;gt;&lt;br /&gt;
        &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
        The &amp;quot;greet&amp;quot; parameter has no further meaning, it just demonstrates&lt;br /&gt;
        how to set a so called &amp;quot;Internal&amp;quot; value. See &amp;lt;a href=&amp;quot;http://fhem.de/commandref.html#define&amp;quot;&amp;gt;commandref#define&amp;lt;/a&amp;gt; &lt;br /&gt;
        for more info about the define command.&lt;br /&gt;
    &amp;lt;/ul&amp;gt;&lt;br /&gt;
    &amp;lt;br&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
    &amp;lt;a name=&amp;quot;Helloset&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
    &amp;lt;b&amp;gt;Set&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
    &amp;lt;ul&amp;gt;&lt;br /&gt;
        &amp;lt;code&amp;gt;set &amp;amp;lt;name&amp;amp;gt; &amp;amp;lt;option&amp;amp;gt; &amp;amp;lt;value&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
        &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
        You can &amp;lt;i&amp;gt;set&amp;lt;/i&amp;gt; any value to any of the following options. They&#039;re just there to &lt;br /&gt;
        &amp;lt;i&amp;gt;get&amp;lt;/i&amp;gt; them. See &amp;lt;a href=&amp;quot;http://fhem.de/commandref.html#set&amp;quot;&amp;gt;commandref#set&amp;lt;/a&amp;gt; &lt;br /&gt;
        for more info about the set command.&lt;br /&gt;
        &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
        Options:&lt;br /&gt;
        &amp;lt;ul&amp;gt;&lt;br /&gt;
              &amp;lt;li&amp;gt;&amp;lt;i&amp;gt;satisfaction&amp;lt;/i&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
                  Defaults to &amp;quot;no&amp;quot;&amp;lt;/li&amp;gt;&lt;br /&gt;
              &amp;lt;li&amp;gt;&amp;lt;i&amp;gt;whatyouwant&amp;lt;/i&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
                  Defaults to &amp;quot;can&#039;t&amp;quot;&amp;lt;/li&amp;gt;&lt;br /&gt;
              &amp;lt;li&amp;gt;&amp;lt;i&amp;gt;whatyouneed&amp;lt;/i&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
                  Defaults to &amp;quot;try sometimes&amp;quot;&amp;lt;/li&amp;gt;&lt;br /&gt;
        &amp;lt;/ul&amp;gt;&lt;br /&gt;
    &amp;lt;/ul&amp;gt;&lt;br /&gt;
    &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;a name=&amp;quot;Helloget&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
    &amp;lt;b&amp;gt;Get&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
    &amp;lt;ul&amp;gt;&lt;br /&gt;
        &amp;lt;code&amp;gt;get &amp;amp;lt;name&amp;amp;gt; &amp;amp;lt;option&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
        &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
        You can &amp;lt;i&amp;gt;get&amp;lt;/i&amp;gt; the value of any of the options described in &lt;br /&gt;
        &amp;lt;a href=&amp;quot;#Helloset&amp;quot;&amp;gt;paragraph &amp;quot;Set&amp;quot; above&amp;lt;/a&amp;gt;. See &lt;br /&gt;
        &amp;lt;a href=&amp;quot;http://fhem.de/commandref.html#get&amp;quot;&amp;gt;commandref#get&amp;lt;/a&amp;gt; for more info about &lt;br /&gt;
        the get command.&lt;br /&gt;
    &amp;lt;/ul&amp;gt;&lt;br /&gt;
    &amp;lt;br&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
    &amp;lt;a name=&amp;quot;Helloattr&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
    &amp;lt;b&amp;gt;Attributes&amp;lt;/b&amp;gt;&lt;br /&gt;
    &amp;lt;ul&amp;gt;&lt;br /&gt;
        &amp;lt;code&amp;gt;attr &amp;amp;lt;name&amp;amp;gt; &amp;amp;lt;attribute&amp;amp;gt; &amp;amp;lt;value&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
        &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
        See &amp;lt;a href=&amp;quot;http://fhem.de/commandref.html#attr&amp;quot;&amp;gt;commandref#attr&amp;lt;/a&amp;gt; for more info about &lt;br /&gt;
        the attr command.&lt;br /&gt;
        &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
        Attributes:&lt;br /&gt;
        &amp;lt;ul&amp;gt;&lt;br /&gt;
            &amp;lt;li&amp;gt;&amp;lt;i&amp;gt;formal&amp;lt;/i&amp;gt; no|yes&amp;lt;br&amp;gt;&lt;br /&gt;
                When you set formal to &amp;quot;yes&amp;quot;, all output of &amp;lt;i&amp;gt;get&amp;lt;/i&amp;gt; will be in a&lt;br /&gt;
                more formal language. Default is &amp;quot;no&amp;quot;.&lt;br /&gt;
            &amp;lt;/li&amp;gt;&lt;br /&gt;
        &amp;lt;/ul&amp;gt;&lt;br /&gt;
    &amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=end html&lt;br /&gt;
&lt;br /&gt;
=cut&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der HTML-Code zwischen den Tags &amp;lt;code&amp;gt;=pod&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;=cut&amp;lt;/code&amp;gt; dient zur Generierung der commandref.html. Der HTML-Inhalt wird automatisch beim Verteilen des Moduls im Rahmen des Update-Mechanismus aus jedem Modul extrahiert und daraus die Commandref in verschiedenen Sprachen erstellt. Eine detaillierte Beschreibung wie ein Commandref-Abschnitt in einem Modul definiert wird, siehe: [[Guidelines zur Dokumentation]]&lt;br /&gt;
&lt;br /&gt;
== Noch zu beschreiben ==&lt;br /&gt;
* DevIO&lt;br /&gt;
* AsyncOutputFn / asyncOutput&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Development]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Arduino_Firmata&amp;diff=19486</id>
		<title>Arduino Firmata</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Arduino_Firmata&amp;diff=19486"/>
		<updated>2017-02-06T22:00:16Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: /* Arduino mit OneWireFirmata */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Arduino mit Firmata ==&lt;br /&gt;
Für den Arduino gibt es ein StandardProtokoll Firmata.[[http://firmata.org]]. Mit der perl-firmata[https://github.com/ntruchsess/perl-firmata [6]] ist das Protokoll in perl einfach nutzbar und mit dem Modul [[#FRM|FRM]] in FHEM eingebunden. Damit ist es möglich mit nur geringen Arduino-kenntnissen (Bedienung der Arduino-IDE ist und elektronische Kenntnisse zum Anschluss von Sensoren sind natürlich erforderlich) Messwerte aus eigenen Schaltungen über einen Arduino in FHEM einzulesen.&lt;br /&gt;
Die in der Arduino-IDE enthaltene StandardFirmata kommuniziert über USB. Ihre Weiterentwicklung (die ConfigurableFirmata) muss man noch [https://github.com/firmata/arduino/archive/configurable.zip separat herunterladen] und damit die in der IDE enthaltene Firmata-library (komplett) ersetzen.&lt;br /&gt;
&lt;br /&gt;
=== Arduino IDE ===&lt;br /&gt;
Zur Installation auf den Arduino wird natürlich erst mal die Arduino-IDE benötigt ([http://arduino.cc/en/Guide/HomePage http://arduino.cc/en/Guide/HomePage]). Die aktuelle Version der IDE enthält auch die StandardFirmata Firmware fertig zum Flashen auf den Arduino.&lt;br /&gt;
Diese findet man unter &#039;Datei&#039;-&amp;amp;gt;&#039;Beispiele&#039;-&amp;amp;gt;&#039;Firmata&#039;-&amp;amp;gt;&#039;StandardFirmata&#039;. Einfach öffnen, unter &#039;Tools&#039;-&amp;amp;gt;&#039;Board&#039; den eigenen Arduino auswählen und mit dem Upload-knopf (der Rechtspfeil im Kreis oben links) den geladenen Sketch compilieren und auf das Board hochladen. Falls man unter Windows Probleme hat, den Arduino über USB zu connecten, findet sich hier weitere Informatation: [http://arduino.cc/en/Guide/Windows#toc2 http://arduino.cc/en/Guide/Windows#toc2]&lt;br /&gt;
Wenn man die ConfigurableFirmata installiert hat, findet sich diese genauso bei den Beispielen für Firmata.&lt;br /&gt;
&lt;br /&gt;
=== Installation ConfigurableFirmata ===&lt;br /&gt;
Die ConfigurableFirmata &amp;lt;b&amp;gt;ersetzt&amp;lt;/b&amp;gt; die vorhandene Firmata-library &amp;lt;b&amp;gt;komplett&amp;lt;/b&amp;gt;. Die mitgelieferte Firmata befindet sich typischerweise:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
Arduino 1.0.x:&lt;br /&gt;
Mac OSX: /Applications/Arduino.app/Contents/Resources/Java/libraries/Firmata&lt;br /&gt;
Windows: c:/Program\ Files/arduino-1.x/libraries/Firmata&lt;br /&gt;
Linux: ~/arduino-1.x/libraries/Firmata&lt;br /&gt;
&lt;br /&gt;
Arduino 1.5.x:&lt;br /&gt;
Mac OSX:&lt;br /&gt;
/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/avr/libraries/Firmata&lt;br /&gt;
/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/sam/libraries/Firmata&lt;br /&gt;
&lt;br /&gt;
Windows:&lt;br /&gt;
/Program\ Files/arduino-1.5.x/hardware/arduino/avr/libraries/Firmata&lt;br /&gt;
/Program\ Files/arduino-1.5.x/hardware/arduino/sam/libraries/Firmata&lt;br /&gt;
&lt;br /&gt;
Linux:&lt;br /&gt;
~/arduino-1.5.x/hardware/arduino/avr/libraries/Firmata&lt;br /&gt;
~/arduino-1.5.x/hardware/arduino/sam/libraries/Firmata&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dieses Verzeichniss &#039;Firmata&#039; also &amp;lt;b&amp;gt;löschen oder umbenennen&amp;lt;/b&amp;gt; und die Configurable-firmata aus der [https://github.com/firmata/arduino/archive/configurable.zip zip-Datei] an die gleiche Stelle (also in ein neues Verzeichniss &#039;Firmata&#039;) entpacken. Nachher muss sich alles wie vorher im Verzeichniss Firmata befinden. Also so:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&lt;br /&gt;
&amp;lt;Arduino-Direktory&amp;gt;/libraries/Firmata/Firmata.h&lt;br /&gt;
&amp;lt;Arduino-Direktory&amp;gt;/libraries/Firmata/Firmata.cpp&lt;br /&gt;
&amp;lt;Arduino-Direktory&amp;gt;/libraries/Firmata/Boards.h&lt;br /&gt;
&amp;lt;Arduino-Direktory&amp;gt;/libraries/Firmata/utility/...usw...&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
alternativ zur Zip-datei kann man die Configurable-Firmata natürlich auch direkt aus Github heraus clonen. Dazu im Verzeichniss &amp;lt;Arduino-Direktory&amp;gt;/libraries/ folgendes eingeben:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&#039;git clone https://github.com/firmata/arduino.git Firmata&#039;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
anschließend ins von clone neu erstellte Verzeichnis wechseln und dort eingeben:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;&#039;git checkout configurable&#039;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ConfigurableFirmata und Ethernet ===&lt;br /&gt;
&lt;br /&gt;
Die Unterstützung für Ethernet ist mittlerweile [https://github.com/firmata/arduino/blob/configurable/examples/ConfigurableFirmata/ConfigurableFirmata.ino in der Configurable-Firmata] enthalten. &lt;br /&gt;
&lt;br /&gt;
Im Sketch muss man unbedingt die IP-konfiguration anpassen, d.h. die IP-addresse und Port des FHEM-servers eintragen (ggf. auch eine neue mac-addresse). Falls der Speicher des Arduinos nicht reicht (insbesonders bei Verwendung eines ENC28J60-shields passt die Configurable-firmata nicht mehr mit allen Features auf einen Uno oder Nano) einfach die includes der nicht benötigten Features im sketch auskommentieren. (Wenn man Servo oder I2C-unterstützung weglassen möchte bitte vorher einmalig den sketch mit allen Features compilieren, sonst treten Fehler beim compilieren der library-klassen wg. fehlendem Include von Servo.h oder Wire.h) auf. Das gleiche gilt, wenn man in der IDE irgendwas ändert, das einen kompletten Neubuild des sketches triggert (was z.B. beim Wechsel des gewählten Boards passiert).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;Getestet ist das ganze mit UNO R3 bzw. Mega 2560 + EthernetShield und zusätzlich mit UNO+Mega+Nano in Verbindung mit ENC28J60. Andere Arduinos als der Uno benötigen ggf. Anpassungen in der Setup/Reset Funktion.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Ein MEGA256 z.B. benutzt einen anderen Pin als SS (Slave select) zur Kommunikation mit dem Ethernetmodul. Man muss der Firmata im Setup mitteilen, welche Pins zu ignorieren sind, damit es keine Wechselwirkungen zwischen Firmata und Ethernetlibrary gibt. Das ist im Configurable.ino-sketch [https://github.com/firmata/arduino/blob/configurable/examples/ConfigurableFirmata/ConfigurableFirmata.ino#L231 ab Zeile 231 vorbereitet] und muss (wenn man etwas anderes als ein Standard-Ethernetshield am Uno verwendet) geeignet angepasst werden (Beim Mega muss man z.B. den Pin 10 ignorieren und Pin 53 als hardcodiert auf Output stellen). Das gleiche gilt, wenn man eine andere Hardware (z.B. mit ENC28J60 anstelle des WizNet W5100 des Ethernetshields) benutzen möchte, die einen anderen Pin als CS/SS benutzt.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Die für den ENC28J80 benötigte [https://github.com/ntruchsess/arduino_uip UIPEthernet-library findet sich hier].&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== FRM ==&lt;br /&gt;
Der Arduino wird in FHEM über das Modul 10_FRM.pm angesprochen.&lt;br /&gt;
10_FRM ist sozusagen die Basis (das IODev) für die anderen Module. Es lassen sich jeweils so viele Ein/Ausgabe Devices pro Arduino konfigurieren, wie dieser physikalisch besitzt (natürlich muss man darauf achten, dass nicht alle Arduino-pins alle Ein-/ausgabemöglichkeiten besitzen). Konfiguriert man einen Pin für einen nicht unterstützen Modus so gibt es mit der aktuellen Firmata-version (2.3) direkt einen Fehler - ältere Versionen schlucken so eine Fehlkonfiguration einfach so, der betreffende Pin funktioniert dann einfach nicht.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;define &amp;amp;lt;devicename&amp;amp;gt; FRM &amp;amp;lt;port&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hier mal ein kurzer Ausschnitt aus der fhem.cfg:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;hr /&amp;gt;&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;# definiere FRM als IO-Device - Baudrate 57600 ist default in der Standardfirmata&lt;br /&gt;
define FIRMATA FRM /dev/ttyUSB0@57600&lt;br /&gt;
attr FIRMATA loglevel 6&lt;br /&gt;
attr FIRMATA sampling-interval 1000 # Wert ist in ms und 14Bit breit, also nur bis 16384 setzbar (Beschränkung des Firmata-protokolls) - gilt für alle Pins&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Seit Anfang März 2013 unterstützt FRM auch über Ethernet angebundene Arduinos:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define FIRMATA FRM &amp;amp;lt;port&amp;amp;gt; [global]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
FRM macht FHEM-seitig einen Serverport auf (dieser wird in der define-zeile angegeben). &#039;global&#039; muss angegeben werden, damit der Serversocket an alle IP-addressen gebunden wird. (Sonst nur &#039;localhost&#039;, was hier wohl nicht funktionieren würde). Der Arduino verbindet aktiv zu diesem Port, sonst gilt im Prinzip alles was auch für den über USB angebunden Arduion gilt.&lt;br /&gt;
&lt;br /&gt;
siehe auch: [http://fhem.de/commandref.html#FRM CommandRef FRM]&lt;br /&gt;
=== 20_FRM_IN.pm ===&lt;br /&gt;
Macht einen Arduino-pin als digitalen Eingang nutzbar.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define Firmata_IN FRM_IN 12 # definiert Arduino Pin 12 als digitalen Eingang&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
siehe auch: [http://fhem.de/commandref.html#FRM_IN CommandRef FRM_IN]&lt;br /&gt;
=== 20_FRM_OUT.pm ===&lt;br /&gt;
Macht einen Arduino-pin als digitalen Ausgang nutzbar.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define Firmata_OUT FRM_OUT 11 # definiert Arduino Pin 11 als digitalen Ausgang&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
siehe auch: [http://fhem.de/commandref.html#FRM_OUT CommandRef FRM_OUT]&lt;br /&gt;
=== 20_FRM_AD.pm ===&lt;br /&gt;
Macht einen Arduino-pin als analogen Eingang nutzbar.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define Firmata_ANALOG FRM_AD 17 # definiert Arduino Pin 17 als analogen Eingang&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
siehe auch: [http://fhem.de/commandref.html#FRM_AD CommandRef FRM_AD]&lt;br /&gt;
=== 20_FRM_PWM.pm ===&lt;br /&gt;
Macht einen Arduino-pin als analogen Ausgang nutzbar. Es wird ein pulsweitenmoduliertes Signal ausgegeben.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define Firmata_ANALOG FRM_PWM 10 # definiert Arduino Pin 10 als analogen Ausgang&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
siehe auch: [http://fhem.de/commandref.html#FRM_PWM CommandRef FRM_PWM]&lt;br /&gt;
=== 20_FRM_SERVO.pm ===&lt;br /&gt;
Erlaubt die Ansteuerung von analogen Modelbauservos (Ansteuerung über PWM) am Arduino.&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;define Firmata_ANALOG FRM_AD 9 # definiert Arduino Pin 9 als analogen Eingang&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
siehe auch: [http://fhem.de/commandref.html#FRM_SERVO CommandRef FRM_SERVO]&lt;br /&gt;
=== 20_FRM_I2C.pm ===&lt;br /&gt;
&amp;lt;p&amp;gt;Erlaubt das Auslesen von über I2C angeschlossenen ICs&amp;lt;/p&amp;gt;&lt;br /&gt;
siehe auch: [http://fhem.de/commandref.html#FRM_I2C CommandRef FRM_I2C]&lt;br /&gt;
=== Arduino mit OneWireFirmata ===&lt;br /&gt;
&amp;lt;p&amp;gt;die Seite [[Arduino mit OneWireFirmata]] beschreibt, wie es möglich ist, mit einer um OneWire erweiterten Version der Standard Firmata an den Arduino angeschlossene 1-Wire Devices in FHEM einzubinden.&amp;lt;/p&amp;gt;&lt;br /&gt;
siehe auch: [http://fhem.de/commandref.html#OWX CommandRef OWX]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Other_Components]]&lt;br /&gt;
[[Kategorie:Arduino]]&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Anwesenheitserkennung&amp;diff=18578</id>
		<title>Anwesenheitserkennung</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Anwesenheitserkennung&amp;diff=18578"/>
		<updated>2017-01-18T20:43:59Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: /* Bluetooth-Überwachung von Geräten durch verteilte Agenten in der Wohnung (presencd/collectord) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Viele Benutzer führen bereits eine eigene &#039;&#039;&#039;Anwesenheitserkennung&#039;&#039;&#039; durch. Diese basiert in den meisten Fällen auf Ping Checks oder bei [[AVM Fritz!Box|FritzBoxen]] auf dem Befehl &#039;&#039;ctlmgr_ctl&#039;&#039;. Diese Lösungen können aber je nach Aufbau und Funktion FHEM massiv beeinträchtigen. Aufgrund des Aufbaus vom FHEM kann dieses dadurch für mehrere Sekunden zum völligen Stillstand gebracht werden.&lt;br /&gt;
&lt;br /&gt;
In FHEM gibt es mittlerweile mehrere Module, die eine zuverlässige Anwesenheitserkennung bieten, ohne dabei FHEM bei der Ausführung zu beeinträchtigen.&lt;br /&gt;
&lt;br /&gt;
Eine erweiterte Funktion der Anwesenheitserkennung ist die Standortverfolgung, die sich nicht nur auf ein oder sehr wenige mit (eigenem) WLAN versorgte Gebiete beschränkt.&lt;br /&gt;
&lt;br /&gt;
== Vorüberlegungen ==&lt;br /&gt;
Generell gibt es mehrere Ansätze um Anwesenheitserkennung mit Handys/Smartphones durchzuführen.&lt;br /&gt;
&lt;br /&gt;
* via PING Checks im gesamten WLAN&lt;br /&gt;
* Aktivitätsprüfung auf einer FritzBox&lt;br /&gt;
* Bluetooth Checks in der gesamten Wohnung&lt;br /&gt;
* eigene Perl-Funktion&lt;br /&gt;
* aktive Benachrichtigung des Smartphones, ausgelöst z.B. über Geo-Lokation/Geofence&lt;br /&gt;
&lt;br /&gt;
Dabei gilt bei der Auswahl der Art darauf zu achten wie sich das jeweilige Device verhält. Aufgrund der Vielfältigkeit kann man hier keine allgemeine Vorgehensweise empfehlen. Als einfacher Start (zumindest für Nicht-Apfel Telefone) eignet sich die Ping-Überprüfung und die FritzBox-Abfrage sehr gut.&lt;br /&gt;
&lt;br /&gt;
=== Randbedingungen ===&lt;br /&gt;
Es gibt Geräte, die ihr WLAN/Bluetooth auch im Standby ständig aktiv haben und auf Anfragen antworten können (fast alle Android-Geräte). Gerade bei Tests über WLAN kann sich das aber signifikant auf die Akku Leistung auswirken.&lt;br /&gt;
&lt;br /&gt;
Andere Geräte wiederum schalten WLAN im Standby Betrieb aus, um Akkukapazität zu sparen. Bluetooth hingegen bleibt weiterhin aktiviert und kann auf Anfragen reagieren. (iPhone)&lt;br /&gt;
&lt;br /&gt;
Wenn man bei einem iPhone die Funktion &amp;quot;über WLAN synchronisieren&amp;quot; aktiviert hat, so ist dies auch im Standby jederzeit pingbar, wenn der Recher auf dem iTunes zum synchroniseren läuft auch an ist. Ansonsten ist bei iPhone Geräten nur die Aktivitätsprüfung mit einer FritzBox oder das überwachen der DHCP Lease auf einer Airport Basestation wirklich zuverlässig.&lt;br /&gt;
&lt;br /&gt;
Auch wenn Bluetooth aktiviert ist, so bleiben einige Mobiltelefone erst dann empfangsbereit, wenn sie bereits zu irgend einem Bluetoothgerät gekoppelt wurden. Sind diese Geräte noch nie gekoppelt worden, deaktivieren diese ihren Bluetooth Empfänger beim verlassen des Bluetooth-Menüs im Gerät (iPhone).&lt;br /&gt;
&lt;br /&gt;
Hier gilt es vor allem auszuprobieren, wie stark der Akku durch eine Anwesenheitserkennung belastet wird. Entscheidend ist hier, in welchem Abstand man eine Anwesenheitserkennung durchführt. Viele Abfragen wirken sich stärker auf den Akku aus als wenige. Wenige Abfragen bieten aber keine zuverlässige und zeitnahe Erkennung.&lt;br /&gt;
&lt;br /&gt;
Als Alternative, unabhängig vom WLAN und der Erkennung, ob ein Gerät dort eingebucht ist oder nicht, bzw. unabhängig von Bluetooth kann zumindest bei einem iPhone die seit iOS 7 nochmals stark verbesserte Geo-Lokation (Geofencing) genutzt werden. Die iPhone Apps [http://geofency.com/ Geofency] oder [http://geofancy.com/ Geofancy] werden über das FHEM-Modul GEOFANCY angebunden und übertragen ihren Status immer dann, wenn ein definierter Standort betreten oder verlassen wird. Gekoppelt mit entsprechenden Notify und/oder Watchdog Kommandos ist so ebenfalls eine sehr zuverlässige Anwesenheitserkennung möglich (und das nicht nur für das eigene Zuhause).&lt;br /&gt;
&lt;br /&gt;
== Das PRESENCE Modul ==&lt;br /&gt;
Das [[PRESENCE]] Modul bietet für die Anwesenheitserkennung mehrere Varianten an. Diese sind aktuell folgende:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;lan-ping&#039;&#039;&#039; - Das Überwachen via PING Checks, die durch den FHEM Server versandt werden.&lt;br /&gt;
* &#039;&#039;&#039;fritzbox&#039;&#039;&#039; - Das Überwachen von Geräten auf einer FritzBox via ctlmgr_ctl (Nur auf einer FritzBox möglich)&lt;br /&gt;
* &#039;&#039;&#039;local-bluetooth&#039;&#039;&#039; - Das Überwachen via Bluetooth Checks, die vom FHEM Server direkt durchgeführt werden (angeschlossener Bluetooth-Stick und die Software bluez voraussgesetzt)&lt;br /&gt;
* &#039;&#039;&#039;lan-bluetooth&#039;&#039;&#039; - Das Überwachen von Bluetoothgeräte, über Netzwerk. Auf einer oder mehreren Maschinen im Netzwerk (z.B. [[:Kategorie:Raspberry Pi|Raspberry Pi]]) läuft ein Presence-Daemon, der nach Bluetooth-Geräten sucht. Um mehrere Presence-Daemon mit FHEM zu verbinden, gibt es den Collector-Daemon, der sich zu allen Presence-Damons im Netzwerk verbindet und das Ergebnis von allen zusammenfasst.&lt;br /&gt;
* &#039;&#039;&#039;function&#039;&#039;&#039; - Das Überwachen mithilfe einer selbst geschrieben Perl-Funktion, die den Anwesenheitsstatus zurückgibt (0 oder 1)&lt;br /&gt;
* &#039;&#039;&#039;shell-script&#039;&#039;&#039; - Das Überwachen mithilfe eines selbst geschriebenen Shell-Programms/Skript, das eine 0 oder 1 ausgibt, um den Anwesenheitsstatus mitzuteilen.&lt;br /&gt;
&lt;br /&gt;
=== Ping-Überwachung von Geräten im WLAN/LAN ===&lt;br /&gt;
{{Randnotiz|RNText=Um diese Methode auf einer FritzBox nutzen zu können, muss FHEM mit root-Rechten laufen. Dies ist standardmäßig nicht der Fall. Bitte dazu den Wiki Artikel [[FritzBox: fhem unter root starten]] beachten.}}&lt;br /&gt;
Um ein Gerät via Ping zu überwachen, muss folgende Definition durchgeführt werden:&lt;br /&gt;
:&amp;lt;code&amp;gt;define Handy PRESENCE lan-ping 192.168.0.30&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dadurch wird die IP-Addresse 192.168.0.30 alle 30&amp;amp;nbsp;Sekunden geprüft, ob sie erreichbar ist. Wenn sie erreichbar ist, ist der Status &amp;quot;present&amp;quot; (anwesend), ansonsten &amp;quot;absent&amp;quot; (abwesend).&lt;br /&gt;
&lt;br /&gt;
Der Timeout kann verändert werden, indem ein Wert (in Sekunden) an das Define anhängt wird:&lt;br /&gt;
:&amp;lt;code&amp;gt;define Handy PRESENCE lan-ping 192.168.0.30 &#039;&#039;&#039;60&#039;&#039;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nun würde das Handy alle 60 Sekunden geprüft werden.&lt;br /&gt;
&lt;br /&gt;
Nur wenn bei einem iPhone/iPad die Funktion &amp;quot;über WLAN synchronisieren&amp;quot; aktiviert ist, ist es auch im Standby zuverlässig pingbar. Standardmäßig deaktivieren Apple-Geräte ihr WLAN im Standby-Betrieb um die Akkulaufzeit zu verlängern.&lt;br /&gt;
&lt;br /&gt;
Sollte die Fehlermeldung &lt;br /&gt;
:&amp;lt;code&amp;gt; PRESENCE (Handy) - ping command returned with output: ping: icmp open socket: Operation not permitted &amp;lt;/code&amp;gt; &lt;br /&gt;
im Log auftauchen und lan-ping dadurch nicht funktionieren, liegt ein Berechtigungsproblem vor. Kein Grund den User fhem zu root zu machen!&lt;br /&gt;
So sollten die Berechtigungen aussehen&lt;br /&gt;
:&amp;lt;code&amp;gt;sudo ls -la /bin/ping&amp;lt;/code&amp;gt;&lt;br /&gt;
unter Jessie&lt;br /&gt;
:&amp;lt;code&amp;gt;-rwxr-xr-x 1 root root 38844 Feb 12  2014 /bin/ping&amp;lt;/code&amp;gt;&lt;br /&gt;
unter Wheezy&lt;br /&gt;
:&amp;lt;code&amp;gt;-rwsr-xr-x 1 root root 33220 Mär 30  2012 /bin/ping&amp;lt;/code&amp;gt;&lt;br /&gt;
Sollte es trotzdem unter Jessie nicht funktionieren kann man auch dort die Berechtigung analog wheezy setzen:&lt;br /&gt;
:&amp;lt;code&amp;gt;sudo chmod u+s /bin/ping&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== FritzBox: direktes Abfragen der Aktivität via ctlmgr_ctl ===&lt;br /&gt;
{{Randnotiz|RNText=Um diese Methode auf einer FritzBox nutzen zu können, muss FHEM mit root-Rechten laufen. Dies ist standardmäßig nicht der Fall. Bitte dazu den Wiki Artikel [[FritzBox: fhem unter root starten]] beachten.}}&lt;br /&gt;
Eine sehr häufige und auch zuverlässige Methode ist auf einer FritzBox die Abfrage mittels ctlmgr_ctl Befehl. Über diesen lassen sich alle Geräte abfragen ob sie aktiv sind. Ist ein Gerät aktiv, so gilt es als anwesend.&lt;br /&gt;
&lt;br /&gt;
Dieser Modus kann allerdings nur in FHEM Installationen direkt auf einer FritzBox verwendet werden. Des weiteren muss FHEM unter dem User root laufen. Um ein Gerät zu überwachen, wird lediglich der Gerätename benötigt, so wie er unter dem Menüpunkt &amp;quot;Heimnetz&amp;quot; auftaucht. &lt;br /&gt;
&lt;br /&gt;
Die erforderliche Definition:&lt;br /&gt;
:&amp;lt;code&amp;gt;define Handy PRESENCE fritzbox iPhone-4S&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bluetooth-Überwachung von Geräten durch den FHEM Server ===&lt;br /&gt;
[[Datei:Bluetooth-Adresse-iPhone.png|thumb|Bluetooth-Adresse eines iPhones]]&lt;br /&gt;
Jenach Aufstellungsort des FHEM Servers kann es sinnvoll sein, eine Bluetooth-Überwachung direkt durch den FHEM Server durchzuführen. Hierbei gilt allerdings zu beachten, dass Bluetooth nicht für große Reichweiten gedacht ist und in den meisten Fällen keine Wände überwinden kann. Das heisst, dass in den meisten Fällen damit nur ein Raum überwacht werden kann.&lt;br /&gt;
&lt;br /&gt;
Je nach Einsatzzweck kann das auch so gewollt sein. Bluetooth USB Sticks, die bereits Bluetooth 4.0 unterstützen, können höhere Reichweiten über Zimmerwände hinaus erreichen. Vorausgesetzt, das Mobilgerät unterstützt Bluetooth 4.0.&lt;br /&gt;
&lt;br /&gt;
Um eine Überwachung per Bluetooth durchführen zu können, benötigt man die Bluetooth-Adresse eines Gerätes. Diese ähnelt vom Aufbau einer MAC-Adresse. Generell wird die Adresse in den Telefon-Informationen bei Smartphones angezeigt.&lt;br /&gt;
&lt;br /&gt;
Um eine Anwesenheitserkennung via Bluetooth durchzuführen, wird folgende Definition in der [[Konfiguration]] benötigt:&lt;br /&gt;
:&amp;lt;code&amp;gt;define Handy PRESENCE local-bluetooth XX:XX:XX:XX:XX:XX&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bluetooth-Überwachung von Geräten durch verteilte Agenten in der Wohnung (presenced/collectord) ===&lt;br /&gt;
[[Datei:Raspberry-Pi-mit-WLAN-und-Bluetooth-Stick.jpg|thumb|left|Raspberry Pi mit Bluetooth- und WLAN-USB-Stick]]&lt;br /&gt;
Um eine zuverlässige und flächendeckende Bluetooth-Anwesenheitserkennung durchzuführen, ist es unerlässlich, mehrere Bluetooth-Empfänger zu verwenden, die auf mehrere oder alle Räume verteilt sind.&lt;br /&gt;
&lt;br /&gt;
Hierfür bietet sich zum Beispiel ein [[Raspberry Pi]] mit einem Mini-Bluetooth-USB-Stick und evtl. einem WLAN-USB-Stick an. Jeder Raum wird mit solch einem Raspberry ausgestattet und ist im WLAN Netz verfügbar.&lt;br /&gt;
&lt;br /&gt;
Dieses Netz aus Raspberrys wird mit dem presenced (Download-Link ist in der [http://fhem.de/commandref_DE.html#PRESENCE Commandref] zum Modul enthalten) ausgestattet. Es stehen bereits entsprechende Pakete für den Raspberry zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
Beide Programme (presenced/collectord) sind Perl-Skripte, die als Daemon im Hintergrund laufen und auf Anfragen via Netzwerk warten. Es wird lediglich eine vollständige Perl-Grundinstallation mit Standardmodulen benötigt. Nach Installation der *.deb Pakete sollten diese noch angewiesen werden, automatisch beim Rechner-Neustart gestartet zu werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo update-rc.d presenced defaults&lt;br /&gt;
sudo update-rc.d collectord defaults&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Eine detaillierte Benutzung von presenced ist in der [http://fhem.de/commandref_DE.html#PRESENCE Commandref] Beschreibung zum PRESENCE Modul enthalten.&lt;br /&gt;
&lt;br /&gt;
==== Jeden Raum einzeln ansprechen (presenced) ====&lt;br /&gt;
Nun kann zuallererst jeder Raum einzeln angesprochen werden. Dabei ist zu beachten, dass pro Definition in der Konfiguration nur ein Gerät in einem Raum spezifisch überwacht werden kann.&lt;br /&gt;
&lt;br /&gt;
Eine Definition sieht dabei folgendermaßen aus:&lt;br /&gt;
:&amp;lt;code&amp;gt;define Handy_Wohnzimmer PRESENCE lan-bluetooth XX:XX:XX:XX:XX:XX 192.168.0.10:5111&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Damit wird nun das Gerät nur im Wohnzimmer (Raspberry mit IP 192.168.0.10) überwacht.&lt;br /&gt;
&lt;br /&gt;
==== Alle Räume gemeinsam ansprechen (collectord) ====&lt;br /&gt;
Um jedoch alle Räume gemeinsam zu verwenden, gibt es den Collector-Daemon. Dieser kennt alle presenced-Installationen im Netzwerk und führt eine koordinierte Suche nach den gewünschten Geräten durch. Sobald ein Gerät in einem Raum erkannt wurde, meldet der collectord den Status einschließlich der Angabe des Raumes, in dem das Gerät erkannt wurde.&lt;br /&gt;
&lt;br /&gt;
Um alle Räume zu kennen, müssen diese mit einem Config-File dem collectord mitgeteilt werden. Dieses sieht folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[Schlafzimmer]           # Name des Raumes (wird in FHEM als Reading angezeigt)&lt;br /&gt;
address=192.168.179.31   # IP-Adresse oder Hostname des presenced&lt;br /&gt;
port=5111                # TCP Port, der verwendet werden soll (standardmäßig Port 5111)&lt;br /&gt;
presence_timeout=120     # Prüfinterval, das verwendet werden soll, wenn ein Gerät anwesend ist&lt;br /&gt;
absence_timeout=20       # Prüfinterval, das verwendet werden soll, wenn ein Gerät abwesend ist&lt;br /&gt;
&lt;br /&gt;
[Wohnzimmer]&lt;br /&gt;
address=192.168.179.34&lt;br /&gt;
port=5111&lt;br /&gt;
presence_timeout=180&lt;br /&gt;
absence_timeout=20&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Standardmäßig ist dieses Config-File unter /etc/collectord.conf zu finden. Mit dieser Konfiguration kann der Collectord gestartet werden. Es empfiehlt sich diesen mit auf dem FHEM Server zu betreiben. Die erforderliche Definition in der Fhem-Konfiguration:&lt;br /&gt;
:&amp;lt;code&amp;gt;define Handy PRESENCE lan-bluetooth XX:XX:XX:XX:XX:XX 127.0.0.1:5222&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sobald das Handy irgendwo in der Wohnung erkannt wurde, meldet der Collectord dies sofort an FHEM und teilt den Raum mit.&lt;br /&gt;
&lt;br /&gt;
Eine detaillierte Benutzung von collectord findet man in der [http://fhem.de/commandref.html#PRESENCE Commandref zum PRESENCE Modul].&lt;br /&gt;
&lt;br /&gt;
=== Überwachung von Geräten mit Perl-Code ===&lt;br /&gt;
Es ist möglich zum Überwachen von Geräten eine eigene Perl-Funktion zu verwenden die dann vom PRESENCE Modul im Hintergrund aufgerufen wird.&lt;br /&gt;
&lt;br /&gt;
 define &amp;lt;name&amp;gt; PRESENCE function {...} [ &amp;lt;check-interval&amp;gt; [ &amp;lt;present-check-interval&amp;gt; ] ]&lt;br /&gt;
&lt;br /&gt;
Sobald die Funktion den Rückgabewert 1 hat, ist das Gerät anwesend, bei 0 abwesend.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel DHCP Überwachung auf Airport Basestation ====&lt;br /&gt;
Die hier vorgestellte Überwachung der DHCP Lease auf Airport Basestations per SNMP ist absolut robust gegenüber dem Ruhezustand von iOS und setzt keine weitere Konfiguration auf dem iPhone voraus. Das Abmelden beim Verlassen des Empfangsbereiches der Basestation geschieht mit etwa 5-10 Minuten Verzögerung und ist somit auch vor kurzzeitigen Empfangsproblemen sicher. Das nebenstehende Bild (???) verdeutlicht noch mal die Unterschiede zwischen einer IP-Basierten Ping-Überwachung und der Überwachung auf Ebene der Basestation oder FritzBox.&lt;br /&gt;
&lt;br /&gt;
Bevor der folgende Code verwendet werden kann ist das Perl Modul Net:SNMP zu installieren (z.&amp;amp;nbsp;B. mit: &amp;lt;code&amp;gt;cpan install use Net::SNMP&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Zuerst ist folgender Code in 99_myUtils.pl einzufügen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
use Net::SNMP;&lt;br /&gt;
sub&lt;br /&gt;
snmpCheck($$)&lt;br /&gt;
{&lt;br /&gt;
  my ($airport,$client)= @_;&lt;br /&gt;
&lt;br /&gt;
  my $community = &amp;quot;public&amp;quot;;&lt;br /&gt;
  my $host = $airport;&lt;br /&gt;
  my $oid = &amp;quot;.1.3.6.1.2.1.3.1.1.2&amp;quot;;&lt;br /&gt;
  #my $oid = &amp;quot;.1.3.6.1.2.1.3.1.1.2.25.1.10.0.1&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  my ( $session, $error ) = Net::SNMP-&amp;gt;session(&lt;br /&gt;
    -hostname =&amp;gt; $host,&lt;br /&gt;
    -community =&amp;gt; $community,&lt;br /&gt;
    -port =&amp;gt; 161,&lt;br /&gt;
    -version =&amp;gt; 1&lt;br /&gt;
  );&lt;br /&gt;
&lt;br /&gt;
  if( !defined($session) ) {&lt;br /&gt;
    return 0;&lt;br /&gt;
    return &amp;quot;Can&#039;t connect to host $host.&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  my @snmpoids = ();&lt;br /&gt;
&lt;br /&gt;
  my $response = $session-&amp;gt;get_next_request($oid);&lt;br /&gt;
  my @nextid = keys %$response;&lt;br /&gt;
  while ( @nextid &amp;amp;&amp;amp; $nextid[0] &amp;amp;&amp;amp; $nextid[0] =~ m/^$oid/ ) {&lt;br /&gt;
    push( @snmpoids, $nextid[0] );&lt;br /&gt;
&lt;br /&gt;
    $response = $session-&amp;gt;get_next_request( $nextid[0] );&lt;br /&gt;
    @nextid = keys %$response;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if( !defined($response = $session-&amp;gt;get_request( @snmpoids ) ) ) {&lt;br /&gt;
    return 0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  foreach my $value (values %$response) {&lt;br /&gt;
    return 1 if( $value eq $client )&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Danach lässt sich das Mobilgerät so überwachen:&lt;br /&gt;
:&amp;lt;code&amp;gt;define iPhone PRESENCE function {snmpCheck(&amp;quot;10.0.1.1&amp;quot;,&amp;quot;0x44d77429f35c&amp;quot;)} 30 30&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
wobei 10.0.1.1 durch die IP-Adresse der Basestation und 0x44d77429f35c durch die MAC Adresse des Geräts als HEX-Zahl ersetzt werden muss.&lt;br /&gt;
&lt;br /&gt;
==== Beispiel Anwesenheitserkennung mittels UniFi Controller ====&lt;br /&gt;
&lt;br /&gt;
Die Anwesenheitserkennung bei Geräten in Verbindung mit UniFi-Produkten funktioniert selbst dann, wenn sich die Geräte im PowerSave-Modus befinden. &lt;br /&gt;
&lt;br /&gt;
Beachte: Die Geräte werden erst ungefähr nach 5 Minuten, nachdem das Gerät das WLAN verlassen hat als disconnected angezeigt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;define &amp;lt;NAME&amp;gt; PRESENCE function {ReadingsVal(&amp;quot;&amp;lt;UniFi&amp;gt;&amp;quot;,&amp;quot;&amp;lt;NamedDevice&amp;gt;&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;connected&amp;quot; ? 1:0}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Eventbasierte Anwesenheitserkennung am Beispiel mittels UniFi Controller ===&lt;br /&gt;
Der Vorteil gegenüber der Function-Variante ist, dass diese Variante ohne Blocking.pm-Overhead direkt ausgeführt werden kann und in &amp;quot;Echtzeit&amp;quot; abläuft (siehe {{Link2Forum|Topic=40287|Message=562823}}).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;define &amp;lt;NAME&amp;gt; PRESENCE event UniFi:NamedDevice:.disconnected UniFi:NamedDevice:.connected&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Das GEOFANCY Modul ==&lt;br /&gt;
Das Modul ermöglicht über einen sogenannten Webhook Mechanismus (umgangssprachlich oft auch als &amp;quot;Push&amp;quot; benannt) das aktive Melden des aktuellen Standortes. Die iPhone Apps  [http://geofency.com/ Geofency] und [http://geofancy.com/ Geofancy] können dann aktiv und quasi in dem Moment, wo man den Wohnbereich betritt oder verlässt, benachrichtigen. Android Nutzern können [https://play.google.com/store/apps/details?id=de.egi.geofence.geozone&amp;amp;hl=de EgiGeoZone Geofence] nutzen. Das geht nochmals um einiges schneller, als die Erkennung im WLAN, bei der die Anwesenheit nur in (engen) Zyklen aktiv geprüft werden muss. Gleichzeitig werden Ressourcen in FHEM geschont. Die aktuelle Implementierung im iPhone 5S mit dediziert für das Tracking zuständigem Chip ist so gut, dass der Akku ebenfalls sehr geschont wird.&lt;br /&gt;
&lt;br /&gt;
=== Modul in FHEM einrichten ===&lt;br /&gt;
Das Modul ist mit einer einfachen Definition sofort betriebsbereit:&lt;br /&gt;
:&amp;lt;code&amp;gt;define geofancy GEOFANCY geo&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Damit nimmt FHEM unter &amp;lt;nowiki&amp;gt;http://192.168.178.1:8083/fhem/geo&amp;lt;/nowiki&amp;gt; entsprechende Meldungen des iPhones entgegen. Damit das nicht nur über das lokale WLAN funktioniert, bedarf es allerdings noch einiger zusätzlicher Maßnahmen. FHEM muss vom Internet erreichbar gemacht werden, dabei sollte unbedingt an die Absicherung des Zugriffs gedacht werden.&lt;br /&gt;
&lt;br /&gt;
Zunächst einmal habe ich bei mir eine eigene FHEMWEB Instanz dafür angelegt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define WEBhook FHEMWEB 8088 global&lt;br /&gt;
attr WEBhook column Alarms: Apartment: Living: Bedroom: Kitchen: Sonos: Residents: Weather: Bathroom: Logs: Statistics: DashboardRoom: System: hidden: all:&lt;br /&gt;
attr WEBhook hiddenroom input,detail,save,Unsorted,Everything,CUL_HM,FS20,Commandref,style,Edit files,Select style,Logfile,Floorplans,Remote doc,FileLogs,Apartment,Bathroom,Bedroom,Kitchen,Living,Residents,System,Weather,Event monitor,NEW&lt;br /&gt;
attr WEBhook room hidden&lt;br /&gt;
attr WEBhook webname webhook&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Damit ist unter der URL &amp;lt;nowiki&amp;gt;http://192.168.178.1:8088/webhook/geo&amp;lt;/nowiki&amp;gt; das GEOFANCY Modul erreichbar. Ich verstecke in dieser Ansicht noch alle Räume, die ich so habe. Wer die Raumnamen allerdings kennt, kann sie trotzdem aufrufen. Die Anzeige in den Räumen kann man mit dem Attribut column und entsprechend leeren Definitionen verstecken. Nun muss man explizit den Devicenamen kennen, um noch etwas über die Konfiguration in Erfahrung bringen zu können.&lt;br /&gt;
Auch wenn das Security-by-Obscurity ist - ich fühle mich wohler damit.&lt;br /&gt;
&lt;br /&gt;
=== Webhook weiter absichern ===&lt;br /&gt;
Mit Hilfe eines [http://fhem.de/commandref.html#allowed allowed]-Devices lässt sich die FHEMWEB Instanz noch weiter absichern indem nur die tatsächlich benötigten Kommandos erlaubt werden (in diesem Fall keine) und damit alle anderen nicht erlaubten (attr,define,get,set,...) automatisch nicht mehr zur Verfügung stehen: &lt;br /&gt;
 &amp;lt;pre&amp;gt;&lt;br /&gt;
define allowedWEBhook allowed&lt;br /&gt;
attr allowedWEBhook allowedCommands ,&lt;br /&gt;
attr allowedWEBhook allowedDevices ,&lt;br /&gt;
attr allowedWEBhook validFor WEBhook&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Außerdem ist dringend zu empfehlen, den Zugriff über TLS/SSL und HTTP Basic-Authentication weiter abzusichern. Läuft FHEM auf einem Raspberry&amp;amp;nbsp;Pi, dann empfehle ich dazu die Konfiguration eines ReverseProxy (vorzugsweise HAproxy, Pound oder Varnish, notfalls auch Nginx oder Apache); damit ist man am flexibelsten und kann auch alle FHEMWEB Instanzen direkt über einen einzigen Port (meist 443, der HTTPS Standard Port) zusammenfassen. Ich möchte hier allerdings beschreiben, wie weit man mit FHEM Bordmitteln kommt und nehme das Beispiel einer Installation auf einer Fritzbox.&lt;br /&gt;
&lt;br /&gt;
Wie TLS aktiviert wird, steht in der Commandref für [[FHEMWEB]]. Um die Kommandos auf der Fritzbox ausführen zu können, muss zuerst Telnet aktiviert werden (bitte Google benutzen). Anschließend wechselt man auf der Fritzbox ins Verzeichnis /var/media/ftp/fhem und kann dann den Hinweisen aus der [http://fhem.de/commandref.html#FHEMWEB Commandref] unter dem Punkt HTTPS folgen. Letztlich fehlt noch das entsprechende Attribut:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr WEBhook HTTPS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Als nächstes aktivieren wir Benutzername+Passwort für den Zugriff. Die commandref für allowed gibt auch hier unter dem Punkt basicAuth entsprechende Hinweise. Wir fügen hier einfach mal einen Benutzer &amp;quot;webhook&amp;quot; mit dem Passwort &amp;quot;Geofancy&amp;quot; hinzu, das sieht dann so aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr allowedWEBhook basicAuth { &amp;quot;$user:$password&amp;quot; eq &amp;quot;webhook:Geofancy&amp;quot; }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Weitere Infos zur Absicherung gibt auch [[FritzBox Webzugriff absichern]].&lt;br /&gt;
&lt;br /&gt;
Um zu testen, ob unsere Absicherung erfolgreich war, kann man die URL &amp;lt;nowiki&amp;gt;https://192.168.178.1:8088/webhook/geo&amp;lt;/nowiki&amp;gt; aufrufen (wichtig ist, dass man jetzt https und nicht mehr http eingibt; ansonsten bekommt man keine Antwort). Eine Zertifikatswarnung kann getrost ignoriert werden, verschlüsselt wird trotzdem. Es sollte auch eine Passwort Abfrage kommen und die Eingabe der entsprechenden Daten sollte dann zu einer entsprechenden Meldung vom GEOFANCY Modul führen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
NOK No data received, see API information on http://wiki.geofancy.com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das ist ok, schließlich sind wir keine App, sondern der Mensch, der nur mal eben prüfen will :-)&lt;br /&gt;
&lt;br /&gt;
=== Zugriff vom Internet ermöglichen ===&lt;br /&gt;
Das ist je nach Fritzbox und Software Version unterschiedlich. Grundsätzlich gilt: Eine Weiterleitung des ports 8088 vom Internet auf das laufende FHEM auf Port 8088 intern ist von AVM so nicht vorgesehen.&lt;br /&gt;
Bei mir führte folgendes zum Erfolg:&lt;br /&gt;
&lt;br /&gt;
* Einloggen per Telnet auf der Fritzbox (ich habe FritzOS 6 installiert)&lt;br /&gt;
* Konfiguration editieren mittels &amp;quot;nvi /var/flash/ar7.cfg&amp;quot;&lt;br /&gt;
* Suchen nach richtiger Zeile durch Eingabe von &amp;quot;/internet_forwardrules&amp;quot; und Enter&lt;br /&gt;
* Hinzufügen einer weiteren Zeile (Vorsicht, die bestehende Zeile endet mit ; und das muss in , umgeändert werden, so dass das ; schließlich am Ende der Zeile steht.&lt;br /&gt;
&lt;br /&gt;
So sieht es bei mir vorher aus:&lt;br /&gt;
:&amp;lt;code&amp;gt;internet_forwardrules = &amp;quot;tcp 0.0.0.0:488 0.0.0.0:488 0&amp;quot;;&amp;lt;/code&amp;gt;&lt;br /&gt;
Hinterher:&lt;br /&gt;
:&amp;lt;code&amp;gt;internet_forwardrules = &amp;quot;tcp 0.0.0.0:488 0.0.0.0:488 0&amp;quot;, &amp;quot;tcp 0.0.0.0:8088 0.0.0.0:8088 0&amp;quot;;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Danach mittels &amp;quot;:x&amp;quot; abspeichern und sofort per &amp;quot;reboot&amp;quot; die Box neu starten, um diese Änderungen zu aktivieren. Das ist wichtig; ansonsten zeigt die Erfahrung, dass die Änderung nicht dauerhaft erhalten bleibt und die gerade gemachten Änderungen verloren gehen.&lt;br /&gt;
&lt;br /&gt;
Wer die Einstellungen zu &amp;quot;internet_forwardrules&amp;quot; bei sich nicht finden kann, hat womöglich eine andere Version als ich oder ein leicht anderes Gerät und bemüht am besten Google, was er tun kann, um das Gleiche zu erreichen. Möglicherweise tauchen die Einträge auch erst auf, wenn man mal über das Webinterface ein Forwarding eingerichtet hatte.&lt;br /&gt;
&lt;br /&gt;
Hat man einen DynDNS Dienst oder myFritz auf der Fritzbox aktiviert, so kann man jetzt auch von draußen auf den Webhook zugreifen. Das kann man prüfen, indem man das iPhone aus dem WLAN ausbucht und einmal die externe Adresse eingibt, also z.B. https://meindyndns.org:8088/webhook/geo.&lt;br /&gt;
&lt;br /&gt;
=== Weitere Alternativen für den Zugriff aus dem Internet ===&lt;br /&gt;
Als Alternative zum Port Forwarding kann man sich auch per VPN in das lokale Netzwerk einwählen. iOS bietet dazu auch eine automatische Aktivierung des VPN (VPN on Demand), wie z.B. [http://forum.loxone.com/dede/netzwerk-firewall-and-security/8121-vpn-demand-ios-8-1-1-fritz-box-kleine-how.html hier] beschrieben wird.&lt;br /&gt;
&lt;br /&gt;
Auch eine Alternative ist, das Portforwarding nicht direkt an FHEM einzurichten, sondern an einem im Netzwerk laufenden Reverse-Proxy, der dann seinerseits die Anfragen an FHEM weiterleitet. Dies kann z.B. Apache, Nginx oder am besten HAproxy sein.&lt;br /&gt;
Letzterer ist dabei sehr flexibel, allerdings nicht unbedingt einfach zu konfigurieren. Ein paar Inspirationen diesbezüglich gibt es z.B. [https://github.com/Hoanoho/HSE/tree/develop/lib/cfg/any/stat/etc/haproxy hier] und [https://github.com/Hoanoho/HSE/tree/develop/lib/cfg/any/dyn/etc/haproxy hier]. Wer pfSense nutzt, findet [http://loredo.me/post/116633549315/geeking-out-with-haproxy-on-pfsense-the-ultimate diesen Artikel] womöglich auch interessant. Er zeigt auch, dass mit HAproxy noch weit mehr möglich ist.&lt;br /&gt;
Der Reverse-Proxy sollte dabei auch unbedingt der TLS Termination Point sein (TLS Offloading). Nicht nur spart man sich dann die Aktivierung von TLS in FHEM, sondern man hat auch mehr Einfluss darauf, wie TLS arbeitet (z.B. Deaktivierung von SSLv3, forcieren von TLSv1.2, nur als sicher eingestufte Cipher Suite... siehe auch Infos auf der [https://wiki.mozilla.org/Security/Server_Side_TLS Mozilla Website]).&lt;br /&gt;
&lt;br /&gt;
=== Einrichten in der Geof[e|a]ncy.app ===&lt;br /&gt;
Hat das alles soweit geklappt, können endlich in der Geofency.app bzw. Geofancy.app am iPhone die gewünschten Bereiche definiert werden. Am Besten zuvor in den Global Settings die folgenden Einstellungen hinterlegen:&lt;br /&gt;
&lt;br /&gt;
* URL: https://meindyndns.org:8088/webhook/geo&lt;br /&gt;
* POST (oder GET, ist egal - das FHEM Modul kann beides)&lt;br /&gt;
* HTTP Basic Authentication: EIN (entsprechend Username und Password eintragen)&lt;br /&gt;
&lt;br /&gt;
Anfänglich ist es empfehlenswert noch &amp;quot;Notification on success&amp;quot; und &amp;quot;Notification on Failure&amp;quot; einzuschalten. Ersteres kann man ausmachen wenn man weiß, dass es soweit funktioniert. Über &amp;quot;Send Test-Request&amp;quot; kann man einmal einen Test schicken und erhält das Ergebnis entsprechend dargestellt. Es sollte sowas kommen wie&lt;br /&gt;
:&amp;lt;code&amp;gt;POST Success: test OK&amp;lt;/code&amp;gt;. In Geofancy.app gibt es keine Rückmeldung über den Erfolg des Testrequests. In FHEM sollten sich durch den Testrequest jedoch die Readings sofort aktualisieren (Ggf. ist ein Reload der FHEMWEB-Seite nötig da zusätzliche Tabellenzeilen nicht via Longpoll ergänzt werden). &lt;br /&gt;
&lt;br /&gt;
Funktioniert das soweit, kann man eine neue Lokation als sein Zuhause anlegen. Es empfiehlt sich einen ID-Namen zu setzen; dieser ist dann in FHEM als Name für die Lokation sichtbar. Für die eigene Wohnung empfiehlt sich hier &amp;quot;home&amp;quot; (da dies auch direkt vom RESIDENTS Modul so verwendet werden kann). Man kann auch Trigger für andere Standorte anlegen. FHEM weiß dann sogar, wenn ihr im Büro seid und könnte sich dabei auch unterschiedlich verhalten, als wenn ihr &amp;quot;auf Achse&amp;quot; seid. Bei letzterem ist der Status im GEOFANCY Modul &amp;quot;underway&amp;quot;, was so viel heißt wie &amp;quot;unbekannter Aufenthaltsort&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Hinweis: Zumindest für Geofancy.app liefert ein Testrequest wohl zufällige Locations zurück. Die eigenen Location-IDs werden also nicht übergeben, selbst wenn man sich in einem Geofence befindet. Um zu testen muss man sich wohl oder übel selbst bewegen ;-).&lt;br /&gt;
&lt;br /&gt;
=== GEOFANCY Modul individualisieren ===&lt;br /&gt;
Die im GEOFANCY Modul dargestellten Readings sind nun in etwa so, wenn ihr euch bewegt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Readings:&lt;br /&gt;
     2014-01-18 14:37:42   lastDevice      -&lt;br /&gt;
     2014-01-18 14:37:42   lastDeviceUUID      51F23894-AAAA-BBBB-CCCC-0123456789AB&lt;br /&gt;
     2014-01-18 14:37:42   state           dev:51F23894-AAAA-BBBB-CCCC-0123456789AB trig:test id:home lat:48.9999 long:11.9999&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wer genauer hinschaut sieht: Mein iPhone heißt wohl 51F23894-AAAA-BBBB-CCCC-0123456789AB.&lt;br /&gt;
Damit nun die Readings für mein iPhone richtig angelegt werden, muss ein Device Alias gesetzt werden. Sinnvoll erscheint mir der Vorname des Besitzers:&lt;br /&gt;
:&amp;lt;code&amp;gt;attr geofancy devAlias 51F23894-AAAA-BBBB-CCCC-0123456789AB:Julian&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Weitere Alias-Namen können mit Leerzeichen einfach angehängt werden.&lt;br /&gt;
Jetzt werden weitere Readings angelegt, sobald GEOFANCY entsprechende Daten vom Mobilgerät empfängt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Readings:&lt;br /&gt;
     2014-01-18 14:37:42   Julian          arrived home&lt;br /&gt;
     2014-01-18 14:37:42   currLocLat_Julian 48.9999&lt;br /&gt;
     2014-01-18 14:37:42   currLocLong_Julian 11.9999&lt;br /&gt;
     2014-01-18 14:37:42   currLocTime_Julian 2014-01-18 14:37:42&lt;br /&gt;
     2014-01-18 14:37:42   currLoc_Julian  home&lt;br /&gt;
     2014-01-17 19:18:23   lastArr         Julian home&lt;br /&gt;
     2014-01-17 18:41:46   lastDep         Julian Office&lt;br /&gt;
     2014-01-18 14:37:42   lastDevice      Julian&lt;br /&gt;
     2014-01-18 14:37:42   lastDeviceUUID      51F23894-AAAA-BBBB-CCCC-0123456789AB&lt;br /&gt;
     2014-01-17 18:41:46   lastLocArr_Julian 2014-01-17 08:58:37&lt;br /&gt;
     2014-01-17 18:41:46   lastLocDep_Julian 2014-01-17 18:41:46&lt;br /&gt;
     2014-01-17 18:41:46   lastLocLat_Julian 48.1111&lt;br /&gt;
     2014-01-17 18:41:46   lastLocLong_Julian 11.1111&lt;br /&gt;
     2014-01-17 18:41:46   lastLoc_Julian  Office&lt;br /&gt;
     2014-01-18 14:37:42   state           dev:Julian trig:test id:home lat:48.9999 long:11.9999&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Möchte man nun etwas bestimmtes tun, wenn man nach Hause kommt oder das Heim verlässt, kann man am Besten ein entsprechendes Notify auf das Reading currLoc_Name setzen. Ich aktualisiere lediglich zwei Dummies, durch die dann alle weiteren Notifies ausgelöst werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define n_Julian.Presence notify geofancy:currLoc_Julian:.home set Julian.homestatus:FILTER=STATE!=home home&lt;br /&gt;
attr n_Julian.Presence room Residents&lt;br /&gt;
define n_Julian.absence notify geofancy:currLoc_Julian:.underway {\&lt;br /&gt;
if (Value(&amp;quot;Julian.homestatus&amp;quot;) ne &amp;quot;gone&amp;quot;) {\&lt;br /&gt;
  fhem(&amp;quot;set Julian.homestatus:FILTER=STATE!=absent absent&amp;quot;);;\&lt;br /&gt;
}\&lt;br /&gt;
}&lt;br /&gt;
define n_Julian.whereabout notify geofancy:currLoc_Julian:.* set Julian.whereabout:FILTER=STATE!=$EVTPART1 $EVTPART1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wer es noch einfacher möchte (bzw. auch noch mehr Features) schaut sich einmal die neue Modulfamilie aus RESIDENTS[http://fhem.de/commandref_DE.html#RESIDENTS], ROOMMATE[http://fhem.de/commandref_DE.html#ROOMMATE] und GUEST[http://fhem.de/commandref_DE.html#GUEST] an. Diese sind direkt auf GEOFANCY abgestimmt. Dabei kann das devAlias Attribut entfallen und man hinterlegt die UUID stattdessen direkt im ROOMMATE oder GUEST Device (Attribut r*_geofenceUUIDs). Das erspart es für jeden Bewohner und jedes Device zig unterschiedliche Devices der Typen Notify, DOIF oder Watchdog anlegen und pflegen zu müssen.&lt;br /&gt;
&lt;br /&gt;
Wer mehr Kontrolle möchte kann natürlich bei notify, DOIF und Co. bleiben: &amp;lt;code&amp;gt;define n_rr_Julian.location notify geofancy:currLoc_Julian:.* set rr_Julian:FILTER=location!=$EVTPART1 location $EVTPART1&amp;lt;/code&amp;gt;. Wobei &amp;quot;Julian&amp;quot; dabei als devAlias in GEOFANCY eingtragen wurde, rr_Julian der Name des ROOMMATE aus RESIDENTS ist. Außerdem wurden die Location-IDs in der Geofency.app bzw. Geofancy.app so gewählt, dass diese direkt einem ROOMMATE-Status entsprechen (also z.B. home, wayhome...).&lt;br /&gt;
&lt;br /&gt;
== Beispiele für die Nutzung der Anwesenheitserkennung ==&lt;br /&gt;
Hier sollen Beispiele für den Nutzen von Anwesenheitserkennung aufgezeigt werden.&lt;br /&gt;
&lt;br /&gt;
=== Abschalten aller Verbraucher (Licht, Musikanlage) beim Verlassen der Wohnung ===&lt;br /&gt;
Typisches Szenario: Man geht ausser Haus, aber hat vergessen im Bad das Licht aus zu machen. Allerdings geht man heutzutage fast garnicht mehr ohne Handy aus dem Haus.&lt;br /&gt;
&lt;br /&gt;
Nun soll FHEM in der gesamten Wohnung das Licht, sowie sonstige Verbraucher ausschalten, wenn ich länger als 15 Minuten ausser Haus bin. Dazu benötigt man zuerst eine structure, die alle Verbraucher und sonstigen Devices, die das betrifft, zusammenfasst.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Gesamte_Wohnung structure Gesamtes_Licht Licht_Wohnzimmer Licht_Kueche LED_Kueche Licht_Bad Licht_Schlafzimmer AV_Receiver TV_Steckdose&lt;br /&gt;
attr Gesamte_Wohnung room Wohnung&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nun kann man mittels eines watchdogs eine Überwachung für sein Handy anlegen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Überwachen der gesamten Wohnung mittels collectord sowie presenced in jedem Raum&lt;br /&gt;
define Handy PRESENCE lan-bluetooth XX:XX:XX:XX:XX:XX 127.0.0.1:5222&lt;br /&gt;
attr Handy event-on-change-reading state  # Ein Event soll nur bei der Änderung des Anwesenheitsstatus (Reading: status) erfolgen. Wichtig für den watchdog!!!&lt;br /&gt;
&lt;br /&gt;
# Nach 15 Minuten Abwesenheit (Handy im Status &amp;quot;absent&amp;quot;) soll die gesamte Wohnung ausgeschaltet werden.&lt;br /&gt;
define watchdog_Anwesenheit watchdog Handy:absent 00:15 Handy:present set Gesamte_Wohnung off ; trigger watchdog_Anwesenheit .&lt;br /&gt;
attr watchdog_Anwesenheit regexp1WontReactivate 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Benachrichtigung bei Batteriewechsel ===&lt;br /&gt;
Mit Hilfe des PRESENCE-Moduls kann man auch bei batteriebetriebenen Geräten eine Meldung ausgeben, sobald ein Batteriewechsel ansteht. Hier im Beispiel wird der Eve-Room-Sensor von Elgato eingebunden und anschließend mit einer DOIF-Nachricht ausgestattet.&lt;br /&gt;
Die Bluetooth-Adresse des Sensors kann mittels eines BLE-Scanners ermittelt werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# PRESENCE-Modul für Elgato Eve Room Sensor mit Aktualisierung aller 6 Minuten&lt;br /&gt;
define Eve_Room_BLE lan-bluetooth &amp;lt;Bluetooth-Adresse&amp;gt; 127.0.0.1:5333 360&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Anschließend wird eine DOIF-Regel definiert, die eine Nachricht an die installiere [[FHEM_APP|FHEM App]] absendet:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Eve_Room_BLE_Battery_Msg DOIF ([Eve_Room_BLE] eq &amp;quot;absent&amp;quot;) (set Msg_iPhone message &#039;Batteriewechsel beim Eve Room Sensor im Wohnzimmer.&#039;)&lt;br /&gt;
attr Eve_Room_BLE_Battery_Msg wait 600&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Aktualisierung des PRESENCE-Eintrages sollte nicht größer sein als das WAIT-Attribut der DOIF-Regel. Ansonsten könnte eine kurze Systemstörung zum Fehlalarm führen.&lt;br /&gt;
&lt;br /&gt;
== Anwesenheitserkennung Bluetooth PebbleBee mit PRESENCE Modul ==&lt;br /&gt;
Im Forum gibt es einen {{Link2Forum|Topic=28753|LinkText=langen Beitrag}} über die Einrichtung eines BT-Tag an einem RaspberryPI mit FHEM. Dabei werden Skripte wie blescan.pl und lepresenced genannt.&lt;br /&gt;
Da mittlerweile viele neue Informationen zusammen gekommen sind wurde der Wiki Eintrag erstellt.&lt;br /&gt;
&lt;br /&gt;
Im Folgenden wird die Konfiguration für &#039;&#039;&#039;LE Deviced (z.B. Gtags,Pebbles etc.)&#039;&#039;&#039; und &#039;&#039;&#039;NICHT LE Device (z.B. IPhone)&#039;&#039;&#039; beschreiben.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Wo finde ich denn lepresenced?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
lepresenced kann über Github heruntergeladen werden (Link weiter unten)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Was ist der Vorteil gegenüber blescan.pl?&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{{Randnotiz|RNText=Beide hier beschriebenen Wege (presenced/lepresenced) können parallel auf dem selben BT-Dongle laufen, da sich die Ports unterscheiden!}}&lt;br /&gt;
blescan.pl hat u. a. das Problem, dass dank der wundervollen Bluetooth-Implementierung unter Linux ab und zu der Scan fehlschlägt und das Interface resettet werden muss. Das tut blescan.pl auch mit aller Gewalt. Dazu kommt, dass bei längeren Scanzeiten und vielen Tags sich die Prozesse anstauen, weil immer nur auf einen Tag &amp;quot;gewartet&amp;quot; wird. Außerdem wurden mit der Einführung von lepresenced sämtliche Supportverträge gekündigt lepresenced läuft dauerhaft und merkt sich bei allen sendenden Tags den Zeitstempel des letzten Empfangs. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Getestete Hardware/Software===&lt;br /&gt;
* &#039;&#039;&#039;Raspbian System&#039;&#039;&#039; - wheezy, Jessie&lt;br /&gt;
* &#039;&#039;&#039;BT-Dongle&#039;&#039;&#039; - CSL NET BT USB2.0 Stick, Bluetooth V4.0, Nano &amp;lt;br /&amp;gt;&#039;&#039;&#039;Achtung&#039;&#039;&#039;: Es muss ein BT V4.0 oder höher verwendet werden. Nur dieser unterstützt &#039;&#039;LowEnergy&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;BT-TAG&#039;&#039;&#039; - Gtag von Gigaset, TrackR, UDOO Neo, PebbleBee, iTag von Unitec, X4-LIFE Multifunkti BL-Anhänger, iTag Wireless Anti, Trackr bravo&lt;br /&gt;
&lt;br /&gt;
===  BT Dongel am PI installieren ===&lt;br /&gt;
&lt;br /&gt;
Um den BT Dongle &#039;&#039;(hier: CSL NET BT USB2.0)&#039;&#039; am PI verwenden zu können, müssen die notwendigen Pakete über die Paketverwaltung von debain nachinstalliert werden.&lt;br /&gt;
Wer bereits ein BT-Dongle installiert hat, kann diesen Schritt überspringen.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt-get install bluetooth&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Nach erfolgreicher Installation der Pakete sollte der RaspberryPI neu gestartet werden.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo reboot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nach dem erfolgten Reboot bitte das Log des Raspberry auf folgende Einträge prüfen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Feb 12 19:52:55 fhem kernel: [    4.773600] Bluetooth: Core ver 2.20&lt;br /&gt;
Feb 12 19:52:55 fhem kernel: [    4.773748] NET: Registered protocol family 31&lt;br /&gt;
Feb 12 19:52:55 fhem kernel: [    4.773765] Bluetooth: HCI device and connection manager initialized&lt;br /&gt;
Feb 12 19:52:55 fhem kernel: [    4.773797] Bluetooth: HCI socket layer initialized&lt;br /&gt;
Feb 12 19:52:55 fhem kernel: [    4.773821] Bluetooth: L2CAP socket layer initialized&lt;br /&gt;
Feb 12 19:52:55 fhem kernel: [    4.773890] Bluetooth: SCO socket layer initialized&lt;br /&gt;
Feb 12 19:52:55 fhem kernel: [    4.797531] usbcore: registered new interface driver btusb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sobald der BT-Dongle erkannt wurde &#039;&#039;leuchtet&#039;&#039; (wenn vorhanden) auch die &#039;&#039;blaue/gelbe&#039;&#039; LED am Dongle auf.&lt;br /&gt;
&lt;br /&gt;
=== BT-Tags aktivieren ===&lt;br /&gt;
Jetzt kann der BT-Tag aktiviert werden. Bei einigen Tags muss dafür die &#039;&#039;&#039;Batteriesicherung&#039;&#039;&#039; gezogen werden.&lt;br /&gt;
&lt;br /&gt;
Einen Tag wird mit folgendem Befehl auf der Konsole gesucht:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo hcitool lescan&lt;br /&gt;
&lt;br /&gt;
Ausgabe z.B.:&lt;br /&gt;
LE Scan ...&lt;br /&gt;
7C:2F:80:A1:XA:XD (unknown)&lt;br /&gt;
7C:2F:80:A1:XA:XD Gigaset G-tag&lt;br /&gt;
7C:2F:80:A1:X4:X1 (unknown)&amp;lt;/source&amp;gt;&lt;br /&gt;
Eine Übersicht über die möglichen Befehle von hcitool gibt es mit der Eingabe von:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo hcitool&lt;br /&gt;
&lt;br /&gt;
Ausgabe z.B.:&lt;br /&gt;
hcitool - HCI Tool ver 5.23&lt;br /&gt;
Usage:&lt;br /&gt;
        hcitool [options] &amp;lt;command&amp;gt; [command parameters]&lt;br /&gt;
Options:&lt;br /&gt;
        --help  Display help&lt;br /&gt;
        -i dev  HCI device&lt;br /&gt;
Commands:&lt;br /&gt;
        dev     Display local devices&lt;br /&gt;
        inq     Inquire remote devices&lt;br /&gt;
        scan    Scan for remote devices&lt;br /&gt;
        name    Get name from remote device&lt;br /&gt;
        info    Get information from remote device&lt;br /&gt;
        spinq   Start periodic inquiry&lt;br /&gt;
        epinq   Exit periodic inquiry&lt;br /&gt;
        cmd     Submit arbitrary HCI commands&lt;br /&gt;
        con     Display active connections&lt;br /&gt;
        cc      Create connection to remote device&lt;br /&gt;
        dc      Disconnect from remote device&lt;br /&gt;
        sr      Switch master/slave role&lt;br /&gt;
        cpt     Change connection packet type&lt;br /&gt;
        rssi    Display connection RSSI&lt;br /&gt;
        lq      Display link quality&lt;br /&gt;
        tpl     Display transmit power level&lt;br /&gt;
        afh     Display AFH channel map&lt;br /&gt;
        lp      Set/display link policy settings&lt;br /&gt;
        lst     Set/display link supervision timeout&lt;br /&gt;
        auth    Request authentication&lt;br /&gt;
        enc     Set connection encryption&lt;br /&gt;
        key     Change connection link key&lt;br /&gt;
        clkoff  Read clock offset&lt;br /&gt;
        clock   Read local or remote clock&lt;br /&gt;
        lescan  Start LE scan&lt;br /&gt;
        lewladd Add device to LE White List&lt;br /&gt;
        lewlrm  Remove device from LE White List&lt;br /&gt;
        lewlsz  Read size of LE White List&lt;br /&gt;
        lewlclr Clear LE White list&lt;br /&gt;
        lecc    Create a LE Connection&lt;br /&gt;
        ledc    Disconnect a LE Connection&lt;br /&gt;
        lecup   LE Connection Update &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Falls beim SCAN kein Tag gefunden wird, sollte das BT Interface neu gestartet werden. Dazu ist kein Reboot des PI notwendig.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo hciconfig hci0 down&lt;br /&gt;
sudo hciconfig hci0 up&lt;br /&gt;
sudo hcitool dev&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Anleitung für ein  LE Device (z.B. Gtags,Pebbles etc.) ===&lt;br /&gt;
&lt;br /&gt;
Herunterladen des Skripts lepresenced.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
https://github.com/mhop/fhem-mirror/blob/master/fhem/contrib/PRESENCE/lepresenced&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zur &amp;quot;Installation&amp;quot; des Skripts folgendermaßen vorgehen:&lt;br /&gt;
Unter /fhem manuell den Ordner „script“ anlegen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir script&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Datei lepresenced reinkopieren und ausführbar machen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo chmod +x /opt/fhem/script/lepresenced&lt;br /&gt;
sudo chgrp -cR dialout lepresenced&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Skript erstmalig starten:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo ./lepresenced --loglevel LOG_EMERG -d&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Kommt beim Starten des Skript eine Fehlermeldung, müssen die Abhängigkeiten aufgelöst werden.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Can&#039;t locate Net/Server/Daemonize.pm in @INC (@INC contains: /etc/perl /usr/local/lib/perl/5.14.2 /usr/local/share/perl/5.14.2 /usr/lib/perl5 /usr/share/perl5 / usr/lib/perl/5.14 /usr/share/perl/5.14 /usr/local/lib/site_perl .) at /opt/fhem/lepresenced line 17.&lt;br /&gt;
BEGIN failed--compilation aborted at /opt/fhem/lepresenced line 17.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Um die Abhängigkeiten aufzulösen muss folgendes nachinstalliert werden und anschließend ein Reboot durchgeführt werden.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt-get install libnet-server-*&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nach dem letzten Schritt sind alle Bedingungen für eine abschließende Konfiguration der BT-Tags in FHEM abgeschlossen worden.&lt;br /&gt;
Jetzt kann der Tag dem FHEM-Server bekannt gemacht werden.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   --   Name       Modul    Modus         MAC vom Gtag  IP vom PI Port    Abfragezeit in Sekunden&lt;br /&gt;
define MeinGtAG PRESENCE lan-bluetooth xx:xx:xx:xx:xx:xx 127.0.0.1:5333    120&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Den absent und present Mode kann man einfach testen, in dem man den Gtag mit Alufolie einwickelt.&lt;br /&gt;
&lt;br /&gt;
=== Anleitung für ein NICHT LE Device (z.B. IPhone) ===&lt;br /&gt;
Die Installation kann (wie in der commanref beschrieben) über Debian Pakete erfolgen.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
.deb package for Debian (noarch): presenced-1.3.deb http://svn.code.sf.net/p/fhem/code/trunk/fhem/contrib/PRESENCE/deb/presenced-1.3.deb&lt;br /&gt;
&lt;br /&gt;
.deb package for Raspberry Pi (raspbian): presenced-rpi-1.3.deb http://svn.code.sf.net/p/fhem/code/trunk/fhem/contrib/PRESENCE/deb/presenced-rpi-1.3.deb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo dpkg -i presenced-rpi-1.3.de&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Installation perl script file (Auszug commanref)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
direct perl script file: presenced http://svn.code.sf.net/p/fhem/code/trunk/fhem/contrib/PRESENCE/presenced&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
Nach dem letzten Schritt sind alle Bedingungen für eine abschließende Konfiguration der BT-Tags in FHEM abgeschlossen worden.&lt;br /&gt;
Jetzt kann der Tag dem FHEM-Server bekannt gemacht werden.&lt;br /&gt;
{{Randnotiz|RNText=Wenn man mit collectord arbeitet muß man die Erkennung bei allen Devices auf port 5222 setzen.&lt;br /&gt;
  lan-bluetooth xx:xx:80:xx:xx:AC 127.0.0.1:5222 20 120}}&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    --   Name       Modul    Modus         MAC vom Gtag  IP vom PI Port    Abfragezeit in Sekunden&lt;br /&gt;
define MeinGtAG PRESENCE lan-bluetooth xx:xx:xx:xx:xx:xx 127.0.0.1:5333    120&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Automatischer Start ===&lt;br /&gt;
&lt;br /&gt;
Damit das leprecend Skript beim Systemstart mitgestartet wird, sollte eine Crontab Eintrag gesetzt werden. Alternativ die rc.local anpassen.&lt;br /&gt;
Ersteres würde so aussehen:&lt;br /&gt;
&lt;br /&gt;
Ein sh-Skript mit dem Inhalt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo start-stop-daemon -d /opt/fhem/script -S -x /opt/fhem/script/lepresenced&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
unter dem Verzeichnis /home/pi ablegen, welches sich init_start.sh nennt.&lt;br /&gt;
&lt;br /&gt;
Das Skript dann unter: sudo crontab -e einhängen mit folgender Folge:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
@reboot        /home/pi/init_start.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zweiteres so:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo nano /etc/rc.local&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Datei rc.local, freie Stelle suchen, vor &amp;quot;exit 0&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Start lepresenced&lt;br /&gt;
/opt/fhem/script/lepresenced --loglevel LOG_EMERG -d&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Batterieüberwachung (aktuell nur G-Tags) ===&lt;br /&gt;
&lt;br /&gt;
Leider überträgt der G-Tag nach der Einrichtung als Device in FHEM kein Reading mit seinem aktuellen Batteriestatus.&lt;br /&gt;
Dem wurde mit Hilfe des Forum Abhilfe geschaffen.&lt;br /&gt;
Im Folgenden wird erläutert wie die Batterieüberwachung eingerichtet werden kann.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Voraussetzung:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
bc - Basiscalculator [https://packages.debian.org/de/sid/bc Bc-Paket]&lt;br /&gt;
&amp;lt;pre&amp;gt; sudo apt-get install bc &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Anlegen eines Shellskript auf dem Raspberry System. &lt;br /&gt;
Die Parameter &amp;lt;&amp;lt;MAC-Adresse&amp;gt;&amp;gt; und &amp;lt;&amp;lt;TagName&amp;gt;&amp;gt; müssen durch die Werte des auszulesenden G-Tags ersetzt werden.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
stringZ=$(sudo gatttool -b 5C:2B:80:C1:14:41 --char-read --handle=0x001b)&lt;br /&gt;
stringZ=${stringZ:33:2}&lt;br /&gt;
stringZ=$(echo &amp;quot;$stringZ&amp;quot; | tr a-f A-F)&lt;br /&gt;
decimal=$(echo &amp;quot;ibase=16; $stringZ&amp;quot; | bc)&lt;br /&gt;
perl /opt/fhem/fhem.pl 7072 &amp;quot;setreading MeinGtag Batterie $decimal&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dem Device in FHEM (hier MeinGtag) ein userReading mit dem Namen &#039;&#039;&#039;Batterie&#039;&#039;&#039; hinzufügen.&lt;br /&gt;
Das Shellskript mit folgendem Befehl starten:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./GtagBatterie.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wichtig ist hierbei,&#039;&#039;&#039; dass Skript mit &amp;quot;./&amp;quot; und nicht mit &amp;quot;sh&amp;quot; aufzurufen. Beim Aufruf mit &amp;quot;sh GtagBatterie.sh&amp;quot; produziert es einen Fehler&lt;br /&gt;
&amp;lt;pre&amp;gt;GtagBatterie.sh: 3: GtagBatterie.sh: Bad substitution &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Reading wird auf den ausgelesenen Wert der Batterie gesetzt. &lt;br /&gt;
&lt;br /&gt;
Hinweis: Es sollte für jeden G-Tag ein eigenes Skript abgelegt werden. Das Skript kann per crontab oder fhem Kommando (system) regelmäßig aufgerufen werden.&lt;br /&gt;
&lt;br /&gt;
=== Batterieüberwachung (alle Devices vom Typ &amp;quot;MODE=lan-bluetooth&amp;quot;) ===&lt;br /&gt;
&lt;br /&gt;
Es gibt eine weitere Möglichkeit um den Batteriestatus von LE Devices abzurufen und in FHEM als Reading darzustellen.&lt;br /&gt;
Dabei wird der Batteriezustand für alle LE Devices, die bereits in FHEM konfiguriert sind und per lepresenced überwacht werden, automatisch in einem shell-Script ermittelt.&lt;br /&gt;
Näheres dazu im Forumartikel [https://forum.fhem.de/index.php/topic,56960.0.html [Erweiterung]: Anwesenheitserkennung/Batterieüberwachung].&lt;br /&gt;
&lt;br /&gt;
Vorteile:&lt;br /&gt;
* Automatische Ermittlung aller in FHEM konfigurierten LE Devices&lt;br /&gt;
* Möglichkeit, diese Devices alternativ manuell im Script einzutragen&lt;br /&gt;
* Es werden nur Devices abgefragt, die im Status &amp;quot;present&amp;quot; sind, also mit ziemlicher Sicherheit auch verfügbar sind&lt;br /&gt;
* Ein eventuell auf dem FHEM telnet-Port gesetztes Passwort kann im Script hinterlegt werden&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Voraussetzung:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Funktionierendes lepresenced&#039;&#039;&#039; - siehe [[Anwesenheitserkennung#Anleitung_f.C3.BCr_ein_LE_Device_.28z.B._Gtags.2CPebbles_etc..29|Anleitung für ein LE Device (z.B. Gtags,Pebbles etc.)]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;socat&#039;&#039;&#039; - TCP port forwarder&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo apt-get update &amp;amp;&amp;amp; sudo apt-get install socat&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;gatttool&#039;&#039;&#039; - Bestandteil von bluez &lt;br /&gt;
&lt;br /&gt;
gatttool ist auf den meisten Distributionen im bluez-Paket, allerdings nicht bei Opensuse. Dort muss man das Sourcepaket von bluez installieren und selbst kompilieren.&lt;br /&gt;
gatttool sollte dann nach /usr/bin oder /usr/local/bin kopiert werden,&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zusätzlich zu den notwendigen Erweiterungen werden für die Ausführung von gatttool &#039;&#039;&#039;Root-Rechte benötigt&#039;&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
Das Script selbst gibt es hier: [https://raw.githubusercontent.com/micky0867/lebattery/master/lebattery lebattery]&lt;br /&gt;
&lt;br /&gt;
Am Besten unter /opt/fhem/script/lebattery speichern und ausführbar machen:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo su -&lt;br /&gt;
mkdir /opt/fhem/script&lt;br /&gt;
cd /opt/fhem/script&lt;br /&gt;
wget https://raw.githubusercontent.com/micky0867/lebattery/master/lebattery&lt;br /&gt;
chmod 755 lebattery&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Je nach Bedarf können im Script noch die folgenden 3 Parameter angepasst werden:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# If allowed_telnetPort is protected by a password, add the password here&lt;br /&gt;
TELNETPASSWORD=&amp;quot;&amp;quot;&lt;br /&gt;
# Attribute for batterylevel in FHEM&lt;br /&gt;
ATTRIBUT=&amp;quot;batterylevel&amp;quot;&lt;br /&gt;
# Use this, if you dont want the script to determine the tags on its own&lt;br /&gt;
LETAGS=&amp;quot;&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Skript wird dann unter root folgendermaßen gestartet:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/opt/fhem/script/lebattery -v&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ausgabe des Skripts, wenn es mit dem Verbose Parameter -v gestartet wird.&lt;br /&gt;
&lt;br /&gt;
Beide Devices sind vom Typ NUT mini, das Device mit dem FHEM-Namen &#039;&#039;&#039;nut_Micky&#039;&#039;&#039; ist im Status &#039;&#039;&#039;absent&#039;&#039;&#039;. Das zweite Device ist im Status &#039;&#039;&#039;present&#039;&#039;&#039;.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Determining address for nut_Micky ...&lt;br /&gt;
nut_Micky is in state absent, no further action required&lt;br /&gt;
&lt;br /&gt;
Determining address for nut_Test ...&lt;br /&gt;
Fetching batterylevel for nut_Test (F3:44:04:81:54:89) ...&lt;br /&gt;
Setting batterylevel for nut_Test to 100%&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mein crontab-Eintrag (User root) sieht so aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
3 3  * * * /opt/fhem/script/lebattery -v &amp;gt;/opt/fhem/script/lebattery.log 2&amp;gt;&amp;amp;1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Damit wird jeden Morgen um 3 Minuten nach 3 Uhr der Zustand der Batterien aller Devices ermittelt und in FHEM abgespeichert.&amp;lt;br&amp;gt; &lt;br /&gt;
Bevor man das mit crontab macht, sollte man allerdings zunächst sicher stellen, dass es auch ohne crontab funktioniert....&lt;br /&gt;
&lt;br /&gt;
Bei Problemen kann man auch erstmal schauen, ob das mit dem gattool überhaupt funktioniert:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gatttool -t random -b &amp;lt;MAC-Adresse&amp;gt; --char-read --uuid 0x2a19&lt;br /&gt;
&lt;br /&gt;
handle: 0x0017 	 value: 64&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
In diesem Fall hat die Batterie noch 100% (hex 64).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===  Anwesenheitserkennung / Anwesenheitsbenachrichtigung mit G-Tags ===&lt;br /&gt;
&lt;br /&gt;
Ein Skript zur Nutzung der Gigaset G-TAGs zur Alarmierung bei öffnen und schließen von Türen und zur Anwesenheitserkennung, um die Alarmierung zu aktivieren bzw. deaktivieren. &lt;br /&gt;
Es kann verwendet werden um die Anwesenheit von mehrern Personen im Haushalt zu erkennen. Dabei wird eingeschränkt, dass nur bestimmte Personen die Alarmierung aktivieren können ( Eltern/Kind -Beziehung ).&lt;br /&gt;
Des Weiteren werden im Beispiel die Eltern benachrichtigt wenn eins der Kinder das Haus verlässt und die Eltern nicht anwesend sind.&lt;br /&gt;
&lt;br /&gt;
{{Randnotiz|RNText= Namen der G-Tags in den Skripten bitte Anpassen!}}&lt;br /&gt;
&lt;br /&gt;
Für die &#039;&#039;Notify&#039;&#039; und die &#039;&#039;RESIDENTS-Erweiterung&#039;&#039; wird ein Dummy benötigt.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Alarm dummy&lt;br /&gt;
attr Alarm devStateIcon aktiv:secur_locked@red inaktiv:secur_open@lightgreen&lt;br /&gt;
attr Alarm eventMap on:aktiv off:inaktiv&lt;br /&gt;
attr Alarm setList on off&lt;br /&gt;
attr Alarm webCmd aktiv:inaktiv&lt;br /&gt;
attr Alarm room Alarm&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Mit Notify ====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gtag.*.presence:.* {Anwesenheit_check(&amp;quot;$EVTPART1&amp;quot;, &amp;quot;$NAME&amp;quot;)}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Code für die 99_myUtils.pm&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
### GTAG ANWESENHEITS CHECK&lt;br /&gt;
sub Anwesenheit_check($$) {&lt;br /&gt;
my ($EVENT, $NAME) = @_;&lt;br /&gt;
my $ALIASNAME = AttrVal($NAME,&#039;alias&#039;,$NAME); # ALIAS des GTAGs auslesen&lt;br /&gt;
my $GTAG1 = Value(&#039;gtag_rot&#039;); # ELTERN&lt;br /&gt;
my $GTAG2 = Value(&#039;gtag_schwarz&#039;); # ELTERN&lt;br /&gt;
&lt;br /&gt;
Log 1, &amp;quot;$ALIASNAME ist $EVENT.&amp;quot;; # LOG Eintrag erzeugen&lt;br /&gt;
&lt;br /&gt;
if (($EVENT eq &amp;quot;anwesend&amp;quot; &amp;amp;&amp;amp; Value(&amp;quot;Alarm&amp;quot;) eq &amp;quot;aktiv&amp;quot;) &amp;amp;&amp;amp; ($NAME eq &amp;quot;gtag_gruen&amp;quot; xor $NAME eq &amp;quot;gtag_orange&amp;quot;)) {&lt;br /&gt;
fhem(&amp;quot;set Infopush msg &#039;ALARMIERUNG BLEIBT AKTIV&#039; &#039;$ALIASNAME ist da...&#039;&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
elsif (($EVENT eq &amp;quot;anwesend&amp;quot; &amp;amp;&amp;amp; Value(&amp;quot;Alarm&amp;quot;) eq &amp;quot;aktiv&amp;quot;) &amp;amp;&amp;amp; ($NAME eq &amp;quot;gtag_rot&amp;quot; xor $NAME eq &amp;quot;gtag_schwarz&amp;quot;)) {&lt;br /&gt;
fhem(&amp;quot;set Infopush msg &#039;ALARMIERUNG INAKTIV&#039; &#039;$ALIASNAME ist da...&#039;; set Alarm inaktiv&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
elsif (($EVENT eq &amp;quot;unterwegs&amp;quot; &amp;amp;&amp;amp; Value(&amp;quot;Alarm&amp;quot;) eq &amp;quot;aktiv&amp;quot;) &amp;amp;&amp;amp; ($NAME eq &amp;quot;gtag_gruen&amp;quot; xor $NAME eq &amp;quot;gtag_orange&amp;quot;)) {&lt;br /&gt;
fhem(&amp;quot;set Infopush msg &#039;ALARMIERUNG BLEIBT AKTIV&#039; &#039;$ALIASNAME hat das Haus verlassen.&#039;&amp;quot;);&lt;br /&gt;
}       &lt;br /&gt;
elsif (($EVENT eq &amp;quot;unterwegs&amp;quot; &amp;amp;&amp;amp; Value(&amp;quot;Alarm&amp;quot;) eq &amp;quot;inaktiv&amp;quot;) &amp;amp;&amp;amp; ($GTAG1 eq &amp;quot;unterwegs&amp;quot; &amp;amp;&amp;amp; $GTAG2 eq &amp;quot;unterwegs&amp;quot;)) {&lt;br /&gt;
fhem(&amp;quot;set Alarm aktiv; set Infopush msg &#039;ALARMIERUNG AKTIV&#039; &#039;$ALIASNAME hat als letztes das Haus verlassen.&#039; &#039;&#039; 0 &#039;&#039;&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
====Mit Notify und Integration des RESIDENTS-MODUL====&lt;br /&gt;
&lt;br /&gt;
Der hier beschriebene Code erweitert die Funktionen unter dem Punkt 5.93.&lt;br /&gt;
Das Notify muss daher mit der folgenden Zeile erweitert werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Alarm_AnwesenheitCheck notify gtag.*.presence:.* { Anwesenheit_check(&amp;quot;$EVTPART1&amp;quot;, &amp;quot;$NAME&amp;quot;), Anwesenheit_check_resi(&amp;quot;$NAME&amp;quot;) }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zusätzlicher Code für die 99_myUtils.pm um die RESIDENTS Funktion nutzen zu können:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
### RESIDENTS&lt;br /&gt;
sub Anwesenheit_check_resi($) {&lt;br /&gt;
my ($NAME) = @_;&lt;br /&gt;
my $ALIASNAME = AttrVal($NAME,&#039;alias&#039;,$NAME); # ALIASNAME des GTAGs auslesen&lt;br /&gt;
my $RESIUSER = &amp;quot;rr_&amp;quot;; # rr_ Residents Roommate rg_ für Residents Guest&lt;br /&gt;
my $ROOMMATE = (&amp;quot;$RESIUSER&amp;quot; . &amp;quot;$ALIASNAME&amp;quot;); # Residentsname zusammenbauen&lt;br /&gt;
&lt;br /&gt;
if (ReadingsVal($NAME,&#039;presence&#039;,$NAME) eq &amp;quot;absent&amp;quot;) {&lt;br /&gt;
 fhem(&amp;quot;set $ROOMMATE absent&amp;quot;); # Resisents Status von Roommates setzen&lt;br /&gt;
 }&lt;br /&gt;
 elsif(ReadingsVal($NAME,&#039;presence&#039;,$NAME) eq &amp;quot;present&amp;quot;) {&lt;br /&gt;
 fhem(&amp;quot;set $ROOMMATE home&amp;quot;); # Resisents Status von Roommates setzen&lt;br /&gt;
 }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Da bei Residents die Benutzernamen unterschiedlich sind für Bewohner (beginnend mit &amp;quot;rr_&amp;quot;) und Gäste (beginnend mit &amp;quot;rg_&amp;quot;) wurden nur die  Bewohner berücksichtigt.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Mit Notify und Fenster/Tür. -Kontakt Überwachung====&lt;br /&gt;
&lt;br /&gt;
Erweiterung für die Überwachung von  Fenster/Tür. -Kontakten. Dazu sind zwei weitere Notifys notwendig die auf die Trigger der Kontakte regagieren&lt;br /&gt;
und so eine weitere Funktion in der 99_myUtils.pm ansprechen. Die Notifys triggern auf Kontakte die mit dem Namen Kontakt* beginnen.&lt;br /&gt;
Sollten die eigenen Fenster/Tür. -Kontakt anderen Namen besitzen, müssen die Skripte dementsprechend angepasst werden.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Alarm_Kontaktmeldung notify Kontakt.*:contact:.* {Kontakt_Meldung(&amp;quot;$EVTPART1&amp;quot;, &amp;quot;$NAME&amp;quot;)}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Alarm_Sabotagealarm notify Kontakt.*.sabotageError:.on {Kontakt_Sabotage(&amp;quot;$EVTPART1&amp;quot;, &amp;quot;$NAME&amp;quot;)}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zusätzlicher Code für die 99_myUtils.pm um die TÜRKONTAKTE-Meldung nutzen zu können:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
### TÜRKONTAKTE-Meldung/Zustand&lt;br /&gt;
sub Kontakt_Meldung($$) {&lt;br /&gt;
my ($EVENT, $NAME) = @_;&lt;br /&gt;
my $ALIASNAME = AttrVal($NAME,&#039;alias&#039;,$NAME);&lt;br /&gt;
Log 1, &amp;quot;$ALIASNAME wurde $EVENT&amp;quot;;&lt;br /&gt;
if (ReadingsVal(&amp;quot;Alarm&amp;quot;, &amp;quot;state&amp;quot;, &amp;quot;on&amp;quot;) eq &amp;quot;on&amp;quot;) {&lt;br /&gt;
fhem(&amp;quot;set teleBot send $ALIASNAME wurde $EVENT&amp;quot;); # Nachricht über Telegram&lt;br /&gt;
# fhem(&amp;quot;set Infopush msg &#039;$ALIASNAME&#039; &#039;$ALIASNAME wurde $EVENT&#039;&amp;quot;); # Nachricht über Pushover&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
### TÜRKONTAKTE-Sabotagealarm&lt;br /&gt;
&lt;br /&gt;
sub Kontakt_Sabotage($$) {&lt;br /&gt;
my ($EVENT, $NAME) = @_;&lt;br /&gt;
my $ALIASNAME = AttrVal($NAME,&#039;alias&#039;,$NAME);&lt;br /&gt;
Log 1, &amp;quot;$ALIASNAME meldet Sabotagealarm&amp;quot;;&lt;br /&gt;
fhem(&amp;quot;set teleBot send Alarm: $ALIASNAME meldet Sabotagealarm&amp;quot;); # Nachricht über Telegram&lt;br /&gt;
# fhem(&amp;quot;set Infopush msg &#039;Alarmanlage&#039; &#039;$ALIASNAME meldet Sabotagealarm&#039; &#039;&#039; 2 &#039; &#039; 60 600 &amp;quot;); # Nachricht über Pushover&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Hinweis zur Benutzung / Fehlerhandling ====&lt;br /&gt;
&lt;br /&gt;
Der Alarm dummy hat den Zustand on:off.  Die Bezeichnungen und Namen müssen 1:1 übernommen werden damit das Script funktioniert.&lt;br /&gt;
Andernfalls müssen die Bezeichnungen für z.B. absent:unterwegs und present:anwesend - angepasst werden.&lt;br /&gt;
Die Benachrichtigung kann aktuell per &#039;&#039;Telegram&#039;&#039; sowie &#039;&#039;Pushover&#039;&#039; (&#039;&#039;&#039;Achtung mit zweiterem sind Abokosten verbunden!&#039;&#039;&#039;) realisiert werden.&lt;br /&gt;
Diskussion zum Thema im Forum unter: [[https://forum.fhem.de/index.php/topic,64080.0.html]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Problemlösungen ===&lt;br /&gt;
Falls es Probleme beim Starten des Skripts gibt bzw. man das Skript ohne Reboot des Systems neustarten möchte, kann man dies per kill Befehl erledigen.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ps -ef | grep lepresenced&lt;br /&gt;
sudo kill &amp;lt;pid&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Debuglevel lepresenced setzen:&lt;br /&gt;
{{Randnotiz|RNText=Um Debug-Meldungen zu bekommen (Vorsicht bei SD-Karten-Systemen wie dem RPi) - Hierbei werden die Schreibzyklen auf die SD-Karte erhöht.}}&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lepresenced --loglevel LOG_DEBUG&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Nur das wichtigste Loggen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lepresenced --loglevel LOG_WARNING&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Keinerlei LOG-Einträge&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
lepresenced --loglevel LOG_EMERG&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Ansprechpartner ====&lt;br /&gt;
# {{Link2FU|5068|PatrikR}} (Patrick) für lepresenced &lt;br /&gt;
# [[Benutzer Diskussion:Devender|Devender]] ({{Link2FU|20043|Dirk}}) für Wiki und Doku&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Code Snippets]]&lt;br /&gt;
[[Kategorie:Glossary]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=DevelopmentModuleIntro&amp;diff=18493</id>
		<title>DevelopmentModuleIntro</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=DevelopmentModuleIntro&amp;diff=18493"/>
		<updated>2017-01-15T18:49:08Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: /* X_Read */  Codebeispiel korrigiert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Dieser Text ist in Arbeit und muss noch an einigen Stellen ergänzt werden. }}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Um neue Geräte, Dienste, o.ä. in FHEM verfügbar zu machen, kann man ein eigenes Modul in Perl schreiben. Ein Modul wird in FHEM automatisch geladen, wenn ein entsprechendes Device in FHEM definiert wird. Das Modul ermöglicht eine spezifische Kommunikation mit einem physikalischen Gerät, stellt Ergebnisse (&amp;quot;Readings&amp;quot;) und Events innerhalb von FHEM zur Verfügung und erlaubt es, das Gerät mit &amp;quot;Set&amp;quot;-/&amp;quot;Get&amp;quot;-Befehlen zu beeinflussen. Dieser Artikel soll den Einstieg in die Entwicklung eigener Module erleichtern.&lt;br /&gt;
&lt;br /&gt;
Mit dem FHEM-Befehl &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt; werden Devices in FHEM basierend auf einem Modul definiert. Dieser Befehl sorgt dafür, dass ein neues Modul bei Bedarf geladen und initialisiert wird. Ein gutes Beispiel ist hierbei die zentrale Konfigurationsdatei &amp;quot;fhem.cfg&amp;quot; in der sämtliche Devices in Form von &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt;-Statements gespeichert sind.&lt;br /&gt;
&lt;br /&gt;
Damit das funktioniert müssen der Name des Moduls und der Name der [[#X_Initialize|Initialisierungsfunktion]]  identisch sein. Das folgende Beispiel soll dies verdeutlichen:&lt;br /&gt;
&lt;br /&gt;
Ein Jeelink USB-Stick könnte beispielsweise mit dem Befehl &amp;lt;code&amp;gt;define JeeLink1 &#039;&#039;JeeLink&#039;&#039; /dev/ttyUSB0@57600&amp;lt;/code&amp;gt; definiert werden.&lt;br /&gt;
&lt;br /&gt;
In fhem.pl wird der define-Befehl verarbeitet und geprüft, ob ein Modul mit dem Namen &amp;quot;JeeLink&amp;quot; schon geladen ist und falls nicht ein Modul mit Namen XY_JeeLink.pm im Modulverzeichnis (z.B. /opt/fhem/FHEM) gesucht und dann geladen. &lt;br /&gt;
Danach wird die Funktion &amp;lt;code&amp;gt;&#039;&#039;JeeLink&#039;&#039;_Initialize()&amp;lt;/code&amp;gt; aufgerufen um das Modul in FHEM zu registrieren. Eine Moduldatei muss dazu eine Funktion &amp;lt;code&amp;gt;&#039;&#039;&amp;amp;lt;Modulname&amp;amp;gt;&#039;&#039;_Initialize()&amp;lt;/code&amp;gt; enthalten. Durch den Aufruf dieser Funktion wird FHEM mitgeteilt, welche Funktionalitäten dieses Modul unterstützt.&lt;br /&gt;
&lt;br /&gt;
In der Initialisierungsfunktion des Moduls werden die Namen aller weiteren Perl-Funktionen des Moduls, die von fhem.pl aus aufgerufen werden, bekannt gemacht. Dazu wird für jedes Modul ein eigener Hash (genauer &amp;quot;Modul-Hash&amp;quot;) mit entsprechenden Werten gefüllt, der in fhem.pl für jedes Modul entsprechend abgelegt wird. Dadurch weiß FHEM wie dieses Modul anzusprechen ist.&lt;br /&gt;
&lt;br /&gt;
== Grundlegender Aufbau eines Moduls ==&lt;br /&gt;
&lt;br /&gt;
=== Dateiname ===&lt;br /&gt;
&lt;br /&gt;
Ein FHEM-Modul wird als Perl-Modul mit der Dateiendung *.pm abgespeichert. Der Dateiname folgt dabei folgendem Schema:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;code&amp;gt;&#039;&#039;[&#039;&#039;&#039;Schlüsselnummer&#039;&#039;&#039;]&#039;&#039;&amp;lt;font color=&amp;quot;grey&amp;quot;&amp;gt;_&amp;lt;/font&amp;gt;&#039;&#039;[&#039;&#039;&#039;Modulname&#039;&#039;&#039;]&#039;&#039;&amp;lt;font color=&amp;quot;grey&amp;quot;&amp;gt;.pm&amp;lt;/font&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Schlüsselnummer&#039;&#039;&#039; - Eine zweistellige Zahl zwischen 00 - 99. Die Schlüsselnummer hat aktuell keine technische Relevanz mehr. In früheren FHEM-Versionen ist sie relevant für [[#Zweistufiges_Modell_f.C3.BCr_Module|zweistufige Module]] (Reihenfolge für [[DevelopmentModuleAPI#Dispatch|Dispatch()]] um logische Module zu prüfen). Die allgemeine Empfehlung ist hierbei eine Schlüsselnummer eines Moduls zu verwenden, welches eine ähnliche Funktionalität bietet. Die Schlüsselnummer 99 hat hierbei eine besondere Bedeutung, da alle Module mit dieser Schlüsselnummer beim Start von FHEM automatisch geladen werden, selbst, wenn sie in der Konfiguration nicht verwendet werden. Daher wird für myUtils 99 als Schlüsselnummer verwendet (99_myUtils.pm). Module mit der Schlüsselnummer 99 werden im SVN nicht akzeptiert (siehe [[SVN Nutzungsregeln]])&lt;br /&gt;
* &#039;&#039;&#039;Modulname&#039;&#039;&#039; - Der Name des Moduls wie er in FHEM bei dem Anlegen einer Gerätedefinition zu verwenden ist. Der Modulname sollte nur aus den folgenden möglichen Zeichen bestehen: Groß-/Kleinbuchstaben, Zahlen sowie Unterstrich (_)&lt;br /&gt;
&lt;br /&gt;
=== Inhaltlicher Aufbau ===&lt;br /&gt;
&lt;br /&gt;
Ein Modul ist inhaltlich in folgende Abschnitte unterteilt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
#&lt;br /&gt;
#  72_MYMODULE.pm &lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
package main;&lt;br /&gt;
&lt;br /&gt;
# Laden evtl. abhängiger Perl- bzw. FHEM-Module&lt;br /&gt;
use HttpUtils;&lt;br /&gt;
use [...]&lt;br /&gt;
&lt;br /&gt;
# FHEM Modulfunktionen&lt;br /&gt;
&lt;br /&gt;
sub MYMODULE_Initialize() {&lt;br /&gt;
   ...&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub MYMODULE_Define() {&lt;br /&gt;
   ...&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
# Eval-Rückgabewert für erfolgreiches&lt;br /&gt;
# Laden des Moduls&lt;br /&gt;
1;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Beginn der Commandref&lt;br /&gt;
&lt;br /&gt;
=pod&lt;br /&gt;
=item [helper|device|command]&lt;br /&gt;
=item summary Kurzbeschreibung in Englisch was MYMODULE steuert/unterstützt&lt;br /&gt;
=item summary_DE Kurzbeschreibung in Deutsch was MYMODULE steuert/unterstützt&lt;br /&gt;
&lt;br /&gt;
=begin html&lt;br /&gt;
 Englische Commandref in HTML&lt;br /&gt;
=end html&lt;br /&gt;
&lt;br /&gt;
=begin html_DE&lt;br /&gt;
 Deustche Commandref in HTML&lt;br /&gt;
=end html&lt;br /&gt;
&lt;br /&gt;
# Ende der Commandref&lt;br /&gt;
=cut&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man kann hierbei von folgender Reihenfolge sprechen:&lt;br /&gt;
&lt;br /&gt;
# Perl-Code, welcher das Modul implementiert&lt;br /&gt;
# Die Zeile &amp;lt;code&amp;gt;1;&amp;lt;/code&amp;gt; nachdem der Perl-Code abgeschlossen ist. Dies dient FHEM der Erkennung, dass das Modul erfolgreich und vollständig geladen wurde. Sollte diese Zeile nicht enthalten sein, wird FHEM beim Laden des Moduls die Fehlermeldung &amp;lt;code&amp;gt;Error:Modul 72_MYMODULE deactivated&amp;lt;/code&amp;gt; in das Logfile schreiben.&lt;br /&gt;
# Commandref zur Dokumentation des Moduls. Diese Dokumentation soll dem User die möglichen Befehle/Attribute/Readings/Events vermitteln. Weitere Informationen und Hinweise findet man in den [[Guidelines zur Dokumentation]].&lt;br /&gt;
&lt;br /&gt;
== Der Hash einer Geräteinstanz ==&lt;br /&gt;
Eine Besonderheit in Perl sind [http://de.wikipedia.org/wiki/Assoziatives_Array#Perl assoziative Arrays], (nicht ganz richtig als &amp;quot;Hash&amp;quot; bezeichnet) in denen die Adressierung nicht über eine Zählvariable erfolgt, sondern über einen beliebigen String. Die internen Abläufe bei der Adressierung führen dazu, dass die Speicherung in und der Abruf aus Hashes relativ langsam ist.&lt;br /&gt;
&lt;br /&gt;
Der zentrale Speicherort für Informationen einer Geräteinstanz bei FHEM ist ein solcher Hash, der seinerseits in fhem.pl von einem globalen Hash referenziert wird. &lt;br /&gt;
&lt;br /&gt;
In fhem.pl werden alle Gerätedefinitionen in dem globalen Hash &amp;lt;code&amp;gt;%defs&amp;lt;/code&amp;gt; abgelegt. Der Inhalt von &amp;lt;code&amp;gt;$defs{&#039;&#039;&amp;amp;lt;Name&amp;amp;gt;&#039;&#039;}&amp;lt;/code&amp;gt; in fhem.pl verweist dabei auf den Hash der Geräteinstanz in Form einer Hashreferenz. Diesen Verweis (also nur die Adresse) bekommen die Funktionen eines Moduls übergeben (i.d.R. als &amp;lt;code&amp;gt;$hash&amp;lt;/code&amp;gt; bezeichnet), welche direkt von fhem.pl aufgerufen werden. In dem Hash stehen beispielsweise die internen Werte des Geräts, die im Frontend als &amp;quot;Internals&amp;quot; angezeigt werden, sowie die Readings des Geräts. &lt;br /&gt;
&lt;br /&gt;
Beispiele:&lt;br /&gt;
*&amp;lt;code&amp;gt;$hash-&amp;gt;{NAME}&amp;lt;/code&amp;gt; enthält den Namen der Geräteinstanz, &lt;br /&gt;
*&amp;lt;code&amp;gt;$hash-&amp;gt;{TYPE}&amp;lt;/code&amp;gt; enthält die Typbezeichnung des Geräts (Modulname)&lt;br /&gt;
&lt;br /&gt;
==Ausführung von Modulen==&lt;br /&gt;
FHEM arbeitet intern nicht parallel, sondern arbeitet alle Aufgaben seriell nacheinander kontinuierlich ab. Daher wäre es ungünstig, wenn Module Daten von einem physikalischen Gerät abfragen wollen und dabei innerhalb der selben Funktion auf die Antwort des Geräts warten. In dieser Zeit, in der FHEM auf die Antwort des Gerätes warten muss, wäre der Rest von FHEM blockiert. Da immer nur eine Aufgabe zur selben Zeit bearbeitet wird, müssen alle weiteren Aufgaben solange warten. Eine Datenkommunikation innerhalb eines Moduls sollte daher immer ohne Blockierung erfolgen. Dadurch kann FHEM die Wartezeit effizient für andere Aufgaben nutzen um bspw. anstehende Daten für andere Module zu verarbeiten. Es gibt in FHEM entsprechende Mechanismen, welche eine &amp;quot;Non-Blocking&amp;quot;-Kommunikation über verschiedene Wege (z.B. seriell, HTTP, TCP, ...) ermöglichen.&lt;br /&gt;
&lt;br /&gt;
Dafür werden in FHEM zwei zentrale Listen gepflegt, in der die Filedeskriptoren der geöffneten Kommunikatonsverbindungen gespeichert sind. Auf Linux- bzw. Unix-basierten Plattformen wird der select-Befehl des Betriebssystems verwendet um Filedeskriptoren auf lesbare Daten zu überprüfen. In FHEM gibt es dazu eine Liste (&amp;lt;code&amp;gt;%selectlist&amp;lt;/code&amp;gt;), in der die Filedeskriptoren sämtlicher Geräte (z.B. serielle Verbindung, TCP-Verbindung, etc.) gespeichert sind. &lt;br /&gt;
&lt;br /&gt;
In der zentralen Schleife (Main-Loop) von fhem.pl wird mit &amp;lt;code&amp;gt;select()&amp;lt;/code&amp;gt; überwacht, ob über eine der geöffneten Schnittstellen Daten zum Lesen anstehen. Wenn dies der Fall ist, dann wird die Lesefunktion ([[#X_Read|X_Read]]) des zuständigen Moduls aufgerufen, damit es die Daten entgegennimmt und verarbeitet. Anschließend wird die Schleife weiter ausgeführt.&lt;br /&gt;
&lt;br /&gt;
Auf Windows-Systemen funktioniert dies anders. Hier können USB/Seriell-Geräte nicht per &amp;lt;code&amp;gt;select()&amp;lt;/code&amp;gt; überwacht werden. In FHEM unter Windows werden daher diese Schnittstellen kontinuierlich abgefragt ob Daten bereitstehen. Dafür müssen Module zusätzlich zur Lesefunktion eine Abfragefunktion ([[#X_Ready|X_Ready]]) implementieren, welche prüft, ob Daten zum Lesen anstehen. Auch auf Linux/Unix-Plattformen hat diese Funktion eine Aufgabe. Falls nämlich eine Schnittstelle ausfällt, beziehungsweise ein CUL oder USB-zu-Seriell Adapter ausgesteckt wird, dann wird über diese Funktion regelmäßig geprüft ob die Schnittstelle wieder verfügbar wird.&lt;br /&gt;
&lt;br /&gt;
Innerhalb der eigentlichen Lesefunktion (X_Read) werden dann die Daten vom zugehörigen Gerät gelesen, das nötige Protokoll implementiert um die Daten zu interpretieren und Werte in Readings geschrieben.&lt;br /&gt;
&lt;br /&gt;
Auch wenn von einem Anwender über einen Get-Befehl Daten aktiv von einem Gerät angefordert werden, sollte nicht blockierend gewartet werden. Eine asynchrone Ausgabe, sobald das Ergebnis vorliegt, ist über [[DevelopmentModuleAPI#asyncOutput|asyncOutput()]] möglich. Siehe {{Link2Forum|Topic=43771|Message=357870|LinkText=Beschreibung}} und {{Link2Forum|Topic=43771|Message=360935|LinkText=Beispiel}}. Weitere Anwendungsbeispiele finden sich im  {{Link2Forum|Topic=43052|Message=353477|LinkText=PLEX Modul}} und im überarbeiteten und nicht-blockierenden {{Link2Forum|Topic=42771|Message=348498|LinkText=SYSSTAT Modul}}.&lt;br /&gt;
&lt;br /&gt;
== Wichtige globale Variablen aus fhem.pl ==&lt;br /&gt;
&lt;br /&gt;
FHEM arbeitet mit einer Vielzahl an internen Variablen. Die nun folgenden aufgelisteten Variablen sind die wichtigsten, welche man im Rahmen der Modulprogrammierung kennen sollte:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Variable !! Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$init_done&amp;lt;/code&amp;gt; || Dient der Erkennung für fhem.pl sowie den Modulen, ob FHEM den Initialisierungsvorgang abgeschlossen hat. Beim Starten von FHEM ist &amp;lt;code&amp;gt;$init_done&amp;lt;/code&amp;gt; gleich &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;. Erst, wenn das Einlesen der Konfiguration, sowie des State-Files (Readings) abgeschlossen ist, wird &amp;lt;code&amp;gt;$init_done&amp;lt;/code&amp;gt; auf &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; gesetzt.&lt;br /&gt;
Das gleiche Verfahren wird auch bei dem Befehl &amp;lt;code&amp;gt;rereadcfg&amp;lt;/code&amp;gt; angewandt. Während &amp;lt;code&amp;gt;rereadcfg&amp;lt;/code&amp;gt; ausgeführt wird (Konfiguration löschen, neu einlesen), ist &amp;lt;code&amp;gt;$init_done&amp;lt;/code&amp;gt; gleich &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Dies ist insbesondere in der [[#X_Define|Define]]-Funktion eines Moduls relevant.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;%attr&amp;lt;/code&amp;gt; || In &amp;lt;code&amp;gt;%attr&amp;lt;/code&amp;gt; werden sämtliche gesetzten Attribute aller Geräte gespeichert. Diese Datenstruktur wird generell durch den &amp;lt;code&amp;gt;attr&amp;lt;/code&amp;gt;-Befehl verwaltet. Hierbei wird einem Gerätenamen eine Mehrzahl an Attributnamen mit einem Wert zugeordnet. Attribut-Inhalte können über die Funktion [[DevelopmentModuleAPI#AttrVal|AttrVal()]] ausgelesen werden.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;%cmds&amp;lt;/code&amp;gt; || In &amp;lt;code&amp;gt;%cmds&amp;lt;/code&amp;gt; wird jedem in FHEM existierendem Befehl die entsprechende Funktion zugewiesen, welche diesen Befehl umsetzt. Module können durch das Eintragen eines Befehlsnamen samt Funktion in &amp;lt;code&amp;gt;%cmds&amp;lt;/code&amp;gt; über die [[#X_Initialize|Initialize]]-Funktion eines Moduls einen (oder mehrere) eigene Befehle in FHEM registrieren.&lt;br /&gt;
&lt;br /&gt;
Die Struktur ist dabei wiefolgt:&lt;br /&gt;
&lt;br /&gt;
  $cmds{&#039;&#039;&amp;amp;lt;Befehlsname&amp;amp;gt;&#039;&#039;} = {  Fn  =&amp;gt; &amp;quot;&#039;&#039;&amp;amp;lt;Funktionsname&amp;amp;gt;&#039;&#039;&amp;quot;,&lt;br /&gt;
                            Hlp =&amp;gt; &amp;quot;&#039;&#039;&amp;amp;lt;Aufrufsyntax&amp;amp;gt;&#039;&#039;&amp;quot;};&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;%data&amp;lt;/code&amp;gt;|| Der eigentliche Zweck von &amp;lt;code&amp;gt;%data&amp;lt;/code&amp;gt; ist dem Nutzer eine Möglichkeit zum Speichern von temporären Daten im globalen Kontext zu ermöglichen. Einige Module verwenden &amp;lt;code&amp;gt;%data&amp;lt;/code&amp;gt; jedoch auch um modul- &amp;amp; geräteübergreifend Daten auszutauschen.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;%defs&amp;lt;/code&amp;gt;|| In &amp;lt;code&amp;gt;%defs&amp;lt;/code&amp;gt; werden sämtliche Gerätedefinitionen, bzw. die Hash-Referenzen auf diese, gespeichert. Hier ist jedem Gerätenamen eine Hash-Referenz zugeordnet.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;%modules&amp;lt;/code&amp;gt;|| In &amp;lt;code&amp;gt;%modules&amp;lt;/code&amp;gt; sind alle geladenen Module gelistet mit ihren entsprechenden Initialisierungsdaten (Funktionsnamen, Attribut-Listen, spezielle Einstellungen, ...). Hier wird für jeden Modulname der Modul-Hash aus der [[#X_Initialize|Initialize]]-Funktion gespeichert. &lt;br /&gt;
Desweiteren legen viele Module, welche nach dem [[DevelopmentModuleIntro#Zweistufiges_Modell_f.C3.BCr_Module|zweistufigen Modulkonzept]] hier eine Rückwärtszuordnung von Geräteadressen zu Geräte-Hash an.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;%readyfnlist&amp;lt;/code&amp;gt;|| In &amp;lt;code&amp;gt;%readyfnlist&amp;lt;/code&amp;gt; sind alle zu prüfenden Verbindungen mit ihrer entsprechendem Geräte-Hash gelistet. FHEM prüft alle hier gelisteten Geräte regelmäßig über eine Aufruf der entsprechenden [[#X_Ready|Ready]]-Funktion.&lt;br /&gt;
&lt;br /&gt;
Bei einer Nutzung von dem Hilfsmodul DevIo.pm zum Aufbau einer Kommunikationsverbindung, kümmert sich DevIo selbständig um den entsprechenden Eintrag in &amp;lt;code&amp;gt;%readyfnlist&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;%selectlist&amp;lt;/code&amp;gt;|| In &amp;lt;code&amp;gt;%selectlist&amp;lt;/code&amp;gt; sind alle geöffneten Verbindungen mit ihrer entsprechendem Geräte-Hash gelistet. FHEM prüft alle hier gelisteten Geräte, ob der geöffnete Filedeskriptor unter &amp;lt;code&amp;gt;$hash-&amp;gt;{FD}&amp;lt;/code&amp;gt; Daten zum Lesen bereitgestellt hat. Ist dass der Fall, wird die entsprechende [[#X_Read|Read]]-Funktion aufgerufen, um anstehende Daten durch das Modul zu verarbeiten.&lt;br /&gt;
Bei einer Nutzung von dem Hilfsmodul DevIo.pm zum Aufbau einer Kommunikationsverbindung, kümmert sich DevIo selbständig um den entsprechenden Eintrag in &amp;lt;code&amp;gt;%selectlist&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Es gibt durchaus viele weitere globale Variablen, die jedoch für sehr spezielle Anwendungsfälle und z.T. nur einzelne Module gedacht sind und daher hier nicht aufgeführt werden.&lt;br /&gt;
&lt;br /&gt;
== Internals ==&lt;br /&gt;
Daten, die ein Modul im Geräte-Hash speichert nennt man Internals. Sie werden als Unterstruktur des Hashes der jeweiligen Geräteinstanz gespeichert, beispielswiese &amp;lt;code&amp;gt;$hash-&amp;gt;{NAME}&amp;lt;/code&amp;gt; für den Gerätenamen, welcher beim Define-Befehl übergeben wurde und als Internal gespeichert wird. Diese Daten spielen für FHEM eine sehr wichtige Rolle, da sämtliche gerätespezifischen Daten als Internal im Gerätehash gespeichert werden.&lt;br /&gt;
&lt;br /&gt;
Falls Werte wie z.B. ein Intervall nicht über den Define-Befehl gesetzt werden sollen und im Betrieb einfach änderbar sein sollten, ist eine alternative Möglichkeit die Speicherung in so genannten Attributen. Dann würde man den Define-Befehl so implementieren, dass er kein Intervall übergeben bekommt und statt dessen das Interval als Attribut über den Befehl &amp;lt;code&amp;gt;attr&amp;lt;/code&amp;gt; gesetzt wird.&lt;br /&gt;
&lt;br /&gt;
Generell werden alle Werte, welche direkt in der ersten Ebene von &amp;lt;code&amp;gt;$hash&amp;lt;/code&amp;gt; (Gerätehash) gespeichert werden auf der Detail-Seite einer Definition in der FHEMWEB Oberfläche angezeigt. Es gibt jedoch Ausnahmen:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;$hash-&amp;gt;{helper}{URL]&amp;lt;/code&amp;gt; - Alle Elemente, welche als Unterelement wieder einen Hash besitzen werden nicht in FHEMWEB dargestellt. Typischerweise speichern Module Daten unter &amp;lt;code&amp;gt;$hash-&amp;gt;{helper}&amp;lt;/code&amp;gt; interne Daten zwischen, die für den User nicht relevant sind, sondern nur der internen Verarbeitung dienen.&lt;br /&gt;
* &amp;lt;code&amp;gt;$hash-&amp;gt;{&#039;&#039;&#039;.&#039;&#039;&#039;&amp;lt;font color=&amp;quot;grey&amp;quot;&amp;gt;ELEMENT&amp;lt;/font&amp;gt;}&amp;lt;/code&amp;gt; - Alle Knoten, welche mit einem Punkt beginnen werden in der FHEMWEB Oberfläche nicht angezeigt. Man kann diese Daten jedoch beim Aufruf des [[List|list-Kommandos]] einsehen.&lt;br /&gt;
&lt;br /&gt;
Es gibt bereits vorbelegte Internals welche in FHEM dazu dienen definitionsbezogene Informationen wie bspw. Namen und Readings zu speichern. Dies sind im besonderen:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;min-width: 13em;&amp;quot; | Internal !!  Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash-&amp;gt;{NAME}&amp;lt;/code&amp;gt;  || Der Definitionsname, mit dem das Gerät angelegt wurde.  &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash-&amp;gt;{READINGS}&amp;lt;/code&amp;gt;  || Enthält alle aktuell vorhandenen Readings. Daten unterhalb dieses Knotens sollte man nicht direkt manipulieren. Um Readings zu Erzeugen gibt es entsprechende [[DevelopmentModuleAPI#Readings_.2F_Events|Reading-Funktionen]].&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash-&amp;gt;{NR}&amp;lt;/code&amp;gt;  || Die Positions-Nr. der Definition innerhalb der Konfiguration. Diese dient dazu die Konfiguration in der gleichen Reihenfolge zu speichern, wie die einzelnen Geräte angelegt wurden.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash-&amp;gt;{TYPE}&amp;lt;/code&amp;gt;  || Der Modulname, mit welchem die Definition angelegt wurde.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash-&amp;gt;{DEF}&amp;lt;/code&amp;gt;  || Sämtliche Argumente, welche beim &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt;-Befehl nach dem Modulnamen übergeben wurden.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash-&amp;gt;{CFGFN}&amp;lt;/code&amp;gt;  || Der Dateiname der Konfigurationsdatei in der diese Definition enthalten ist (sofern nicht in fhem.cfg). Dieser Wert ist nur gefüllt, wenn man mit mehreren Konfigurationsdateien arbeitet, welche dann in fhem.cfg via include-Befehl eingebunden werden.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash-&amp;gt;{NTFY_ORDER}&amp;lt;/code&amp;gt;  || Sofern das Modul Events via [[DevelopmentModuleIntro#X_Notify|Notify-Funktion]] verarbeitet enthält jede Definition eine Notify-Order als Zeichenkette bestehend aus dem Notify Order Prefix und dem Definitionsnamen. Details zur Funktionsweise gibt es in der Beschreibung zur [[DevelopmentModuleIntro#X_Notify|Notify-Funktion]] im Abschnitt &amp;quot;Reihenfolge für den Aufruf der Notify-Funktion beeinflussen&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash-&amp;gt;{NOTIFYDEV}&amp;lt;/code&amp;gt;  || Sofern das Modul Events via NotifyFn verarbeitet kann man damit die Definitionen, von denen man Events erhalten will begrenzen. Details zur Funktionsweise gibt es in der Beschreibung zur [[DevelopmentModuleIntro#X_Notify|Notify-Funktion]] im Abschnitt &amp;quot;Begrenzung der Aufrufe auf bestimmte Geräte&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash-&amp;gt;{IODev}&amp;lt;/code&amp;gt;  || Hier wird das zugeordnete IO-Gerät durch [[DevelopmentModuleAPI#AssignIoPort|AssignIoPort()]] gespeichert, welches für den Datentransport und -empfang dieses logischen Gerätes zuständig ist. Dieser Wert existiert nur bei Modulen die nach dem [[DevelopmentModuleIntro#Zweistufiges_Modell_f.C3.BCr_Module|zweistufigen Modulkonzept]] arbeiten. &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash-&amp;gt;{CHANGED}&amp;lt;/code&amp;gt;  || Hier werden alle Events kurzzeitig gesammelt, welche für die Eventverarbeitung anstehen. Insbesondere die [[DevelopmentModuleAPI#Readings_.2F_Events|Reading-Funktionen]] speichern hier alle Events zwischen um sie nach Abschluss via [[DevelopmentModuleAPI#DoTrigger|DoTrigger()]] zu verarbeiten. &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash-&amp;gt;{FD}&amp;lt;/code&amp;gt;  || Wenn die Definition eine Netzwerkverbindung oder serielle Schnittstelle geöffnet hat (z.B. via DevIo), so wird der entsprechende File-Deskriptor in diesem Internal gespeichert. Damit kann FHEM alle geöffneten Filedeskriptoren der entsprechenden Definition zuordnen um bei ankommenden Daten die Definition via [[DevelopmentModuleIntro#X_Read|Read-Funktion]] damit zu versorgen.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash-&amp;gt;{EXCEPT_FD}&amp;lt;/code&amp;gt;  || Ähnlich wie &amp;lt;code&amp;gt;$hash-&amp;gt;{FD}&amp;lt;/code&amp;gt;. Sofern die Definition in &amp;lt;code&amp;gt;[[#Wichtige_globale_Variablen_aus_fhem.pl|%selectlist]]&amp;lt;/code&amp;gt; eingetragen ist und ein Fildeskriptor in diesem Internal gesetzt ist, wird bei einer auftretenden Exception bzw. Interrupt die [[DevelopmentModuleIntro#X_Except|Except]]-Funktion des entsprechenden Moduls aufgerufen um darauf zu reagieren.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Generell sollte man die meisten der hier genannten systemweiten Internals nicht modifizieren, da ansonsten die korrekte Funktionsweise von FHEM nicht mehr garantiert werden kann.&lt;br /&gt;
&lt;br /&gt;
== Readings ==&lt;br /&gt;
Daten, welche von einem Gerät gelesen werden und in FHEM in einer für Menschen verständlichen Form zur Verfügung gestellt werden können, werden Readings genannt. Sie geben den Status des Gerätes wieder und erzeugen Events innerhalb von FHEM auf die andere Geräte reagieren können. Sie werden als Unterstruktur des Hashes der jeweiligen Geräteinstanz gespeichert, beispielsweise &lt;br /&gt;
*&amp;lt;code&amp;gt;$hash-&amp;gt;{READINGS}{temperature}{VAL}&amp;lt;/code&amp;gt; für die Temperatur eines Fühlers&lt;br /&gt;
*&amp;lt;code&amp;gt;$hash-&amp;gt;{READINGS}{temperature}{TIME}&amp;lt;/code&amp;gt; für den Zeitstempel der Messung&lt;br /&gt;
&lt;br /&gt;
Für den lesenden Zugriff auf Readings steht die Funktion &amp;lt;code&amp;gt;[[DevelopmentModuleAPI#ReadingsVal|ReadingsVal()]]&amp;lt;/code&amp;gt; zur Verfügung. Ein direkter Zugriff auf die Datenstruktur sollte nicht vorgenommen werden.&lt;br /&gt;
&lt;br /&gt;
Readings werden im Statefile von FHEM automatisch auf der Festplatte zwischengespeichert, damit sie nach einem Neustart sofort wieder zur Verfügung stehen. Dadurch ist der letzte Status eines Gerätes vor einem Neustart nachvollziehbar.&lt;br /&gt;
&lt;br /&gt;
Readings, die mit einem Punkt im Namen beginnen, haben eine funktionale Besonderheit. Sie werden im FHEMWEB nicht angezeigt und können somit als &amp;quot;Permanentspeicher&amp;quot; für kleinere Daten innerhalb des Moduls genutzt werden. Um größere Datenmengen permanent zu speichern sollte man jedoch die Funktion &amp;lt;code&amp;gt;[[DevelopmentModuleAPI#setKeyValue|setKeyValue()]]&amp;lt;/code&amp;gt; verwenden.&lt;br /&gt;
&lt;br /&gt;
Zum Setzen von Readings sollen &lt;br /&gt;
*bei Gruppen von Readings der Funktionsblock &amp;lt;code&amp;gt;[[DevelopmentModuleAPI#readingsBeginUpdate|readingsBeginUpdate()]]&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;[[DevelopmentModuleAPI#readingsBulkUpdate|readingsBulkUpdate()]]&amp;lt;/code&amp;gt; (mehrfach wiederholt), &amp;lt;code&amp;gt;[[DevelopmentModuleAPI#readingsEndUpdate|readingsEndUpdate()]]&amp;lt;/code&amp;gt;&lt;br /&gt;
*bei einzelnen Updates die Funktion &amp;lt;code&amp;gt;[[DevelopmentModuleAPI#readingsSingleUpdate|readingsSingleUpdate()]]&amp;lt;/code&amp;gt; &lt;br /&gt;
aufgerufen werden. Dabei kann man auch angeben, ob dabei ein Event ausgelöst werden soll oder nicht. Events erzeugen, je nach Hardwareperformance, spürbare Last auf dem System (siehe [[DevelopmentModuleIntro#X_Notify|NotifyFn]]), das Ändern von Readings ohne dass dabei Events erzeugt werden jedoch nicht.&lt;br /&gt;
&lt;br /&gt;
Eine Sequenz zum Setzen von Readings könnte folgendermaßen aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
readingsBeginUpdate($hash);&lt;br /&gt;
readingsBulkUpdate($hash, $readingName1, $wert1 );&lt;br /&gt;
readingsBulkUpdate($hash, $readingName2, $wert2 );&lt;br /&gt;
readingsEndUpdate($hash, 1);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Attribute ==&lt;br /&gt;
Damit der Nutzer das Verhalten einer einzelnen Gerätedefinition zur Laufzeit individuell anpassen kann, gibt es in FHEM für jede Definition sogenannte Attribute, welche mit dem Befehl &amp;lt;code&amp;gt;attr&amp;lt;/code&amp;gt; gesetzt werden können.&lt;br /&gt;
Diese stehen dann dem Modul unmittelbar zur Verfügung um das Verhalten während der Ausführung zu beeinflussen. Attribute werden zusammen mit dem &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt;-Befehl der jeweiligen Definition beim Speichern der aktuellen Konfiguration von FHEM in die Konfigurationsdatei geschrieben. Beim Neustart werden die entsprechenden Befehle ausgeführt um alle Definition inkl. Attribute wieder anzulegen. Zur Laufzeit werden Attribute in dem globalen Hash &amp;lt;code&amp;gt;%attr&amp;lt;/code&amp;gt; mit dem Definitionsnamen als Index (&amp;lt;code&amp;gt;$attr{$name} = $value&amp;lt;/code&amp;gt;) gespeichert. Ein Attribut mit dem Namen &amp;lt;code&amp;gt;header&amp;lt;/code&amp;gt; würde beispielsweise mit &amp;lt;code&amp;gt;$attr{$name}{header}&amp;lt;/code&amp;gt; adressiert. Generell sollte &amp;lt;code&amp;gt;%attr&amp;lt;/code&amp;gt; nicht durch direkten Zugriff manipuliert/benutzt werden.&lt;br /&gt;
&lt;br /&gt;
Zum Auslesen von Attributen sollte die Funktion [[DevelopmentModuleAPI#AttrVal|AttrVal()]] verwendet werden.&lt;br /&gt;
&lt;br /&gt;
Welche Attribute ein Modul unterstützt muss in der Funktion &amp;lt;code&amp;gt;[[#X_Initialize|X_Initialize]]&amp;lt;/code&amp;gt; durch Setzen von &amp;lt;code&amp;gt;$hash-&amp;gt;{AttrList}&amp;lt;/code&amp;gt; bekannt gemacht werden (siehe unten).&lt;br /&gt;
&lt;br /&gt;
Wenn beim Setzen von Attributen in einer Gerätedefinition entsprechende Werte geprüft werden sollen oder zusätzliche Funktionalitäten implementiert werden müssen, dann muss dies in der Funktion &amp;lt;code&amp;gt;[[#X_Attr|X_Attr]]&amp;lt;/code&amp;gt; (siehe unten) implementiert werden. Hier kann man bspw. einen Syntaxcheck für Attribut-Werte implementieren um ungültige Werte zurückzuweisen.&lt;br /&gt;
&lt;br /&gt;
== Modulfunktionen ==&lt;br /&gt;
&lt;br /&gt;
Damit fhem.pl ein Modul nutzen kann, muss dieses entsprechende Funktionen mit einer vorgegebenen Aufrufsyntax implementieren. Durch die Bekanntgabe dieser modulspezifischen Funktionen können Daten zwischen fhem.pl und einem Modul entsprechend ausgetauscht werden. Es gibt verschiedene Arten von Funktionen die ein Modul anbieten muss bzw. kann, je nach Funktionsumfang.&lt;br /&gt;
&lt;br /&gt;
=== Die wichtigsten Funktionen in einem Modul ===&lt;br /&gt;
&lt;br /&gt;
Folgende Funktion muss ein Modul mit dem beispielhaften Namen &amp;quot;X&amp;quot; mindestens bereitstellen:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;text-align:left&amp;quot; | Funktionsname !! style=&amp;quot;text-align:left&amp;quot; | Kurzbeschreibung&lt;br /&gt;
|-&lt;br /&gt;
|  [[#X_Initialize|X_Initialize]] || Initialisiert das Modul und gibt den Namen zusätzlicher Modulfunktionen bekannt, sowie modulspezifische Einstellungen. Wird direkt nach dem erfolgreichen Laden des Moduls durch fhem.pl aufgerufen.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Die folgenden Funktionen sind die wichtigsten Funktionen, welche je nach Anwendungsfall zu implementieren sind. Es handelt sich hierbei um die wichtigsten Vertreter, welche in den meisten Modulen Verwendung finden. Nicht alle Funktionen machen jedoch in jedem Modul Sinn. Generell sollte auch hier bei jeder Funktion der Modulname vorangestellt werden um ein einheitliches Namensschema zu gewährleisten. Hier die wichtigsten Modulfunktionen:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;text-align:left&amp;quot; | Funktionsname !! style=&amp;quot;text-align:left&amp;quot; class=&amp;quot;unsortable&amp;quot;| Kurzbeschreibung&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Define|X_Define]] || Wird im Rahmen des &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt;-Befehls aufgerufen.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Undef|X_Undef]] || Wird im Rahmen des &amp;lt;code&amp;gt;delete&amp;lt;/code&amp;gt;-Befehls, sowie &amp;lt;code&amp;gt;rereadcfg&amp;lt;/code&amp;gt;-Befehl aufgerufen. Dient zum Abbau von offenen Verbindungen, Timern, etc.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Delete|X_Delete]] || Wird im Rahmen des beim &amp;lt;code&amp;gt;delete&amp;lt;/code&amp;gt;-Befehls aufgerufen wenn das Gerät endgültig gelöscht wird um weiterführende Aktionen vor dem Löschen durchzuführen.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Get|X_Get]] || Wird im Rahmen des &amp;lt;code&amp;gt;get&amp;lt;/code&amp;gt;-Befehls aufgerufen um Daten vom Gerät abzufragen&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Set|X_Set]]  || Wird im Rahmen des &amp;lt;code&amp;gt;set&amp;lt;/code&amp;gt;-Befehls aufgerufen um Daten an das Gerät zu senden.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Attr|X_Attr]]  || Wird im Rahmen des &amp;lt;code&amp;gt;attr&amp;lt;/code&amp;gt;-Befehls aufgerufen um Attributwerte zu prüfen)&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Read|X_Read]]  || Wird durch FHEM aufgerufen, wenn ein gelisteter Filedeskriptor in &amp;lt;code&amp;gt;[[#Wichtige_globale_Variablen_aus_fhem.pl|%selectlist]]&amp;lt;/code&amp;gt; Daten zum Lesen bereitstellt.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Ready|X_Ready]]  || Wird unter Windows durch FHEM aufgerufen um zyklisch einen seriellen Filedeskriptor auf lesbare Daten zu prüfen. Unter Linux dient diese Funktion dem Wiederaufbau verlorener Verbindungen.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Notify|X_Notify]]  || Verarbeitet Events von anderen Geräten innerhalb von FHEM&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Rename|X_Rename]] || Wird aufgerufen, wenn ein Gerät umbenannt wird.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Shutdown|X_Shutdown]] || Wird beim Herunterfahren von FHEM ausgeführt.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Diese Funktionen werden in diesem Abschnitt genauer beschrieben.&lt;br /&gt;
&lt;br /&gt;
==== X_Initialize ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Initialize($)&lt;br /&gt;
{&lt;br /&gt;
	my ($hash) = @_;&lt;br /&gt;
	...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das &amp;lt;code&amp;gt;X&amp;lt;/code&amp;gt; im Namen muss dabei auf den Namen des Moduls bzw. des definierten Gerätetyps geändert werden. Im Modul mit der Datei &amp;lt;code&amp;gt;36_JeeLink.pm&amp;lt;/code&amp;gt; beispielsweise ist der Name der Funktion &amp;lt;code&amp;gt;JeeLink_Initialize&amp;lt;/code&amp;gt;. Die Funktion wird von fhem.pl nach dem Laden des Moduls aufgerufen und bekommt eine leere Hashreferenz für den Initialisierungsvorgang übergeben. &lt;br /&gt;
&lt;br /&gt;
Dieser Hash muss nun von X_Initialize mit allen modulrelevanten Funktionsnamen gefüllt werden. Anschließend wird dieser Hash durch fhem.pl im globalen Hash &amp;lt;code&amp;gt;%modules&amp;lt;/code&amp;gt; gespeichert. &amp;lt;code&amp;gt;$modules{ModulName}&amp;lt;/code&amp;gt; wäre dabei der Hash für das Modul mit dem Namen &amp;lt;code&amp;gt;ModulName&amp;lt;/code&amp;gt;. Es handelt sich also nicht um den oben beschriebenen Hash der Geräteinstanzen sondern einen Hash, der für jedes Modul existiert und modulspezifische Daten wie bspw. die implementierten Modulfunktionen enthält. Die Initialize-Funktion setzt diese Funktionsnamen, in den Hash des Moduls wie folgt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
$hash-&amp;gt;{DefFn}         = &amp;quot;X_Define&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{UndefFn}       = &amp;quot;X_Undef&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{DeleteFn}      = &amp;quot;X_Delete&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{SetFn}         = &amp;quot;X_Set&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{GetFn}         = &amp;quot;X_Get&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{AttrFn}        = &amp;quot;X_Attr&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{ReadFn}        = &amp;quot;X_Read&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{ReadyFn}       = &amp;quot;X_Ready&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{NotifyFn}      = &amp;quot;X_Notify&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{RenameFn}      = &amp;quot;X_Rename&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{ShutdownFn}    = &amp;quot;X_Shutdown&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Um eine entsprechende Funktion in FHEM bekannt zu machen muss dazu der Funktionsname, wie er im Modul als &amp;lt;code&amp;gt;sub &amp;amp;lt;&#039;&#039;Funktionsname&#039;&#039;&amp;amp;gt;() { ... }&amp;lt;/code&amp;gt; definiert ist, als Zeichenkette in &amp;lt;code&amp;gt;$hash&amp;lt;/code&amp;gt; gesetzt werden. Dabei sollten die entsprechenden Funktionsnamen immer den Modulnamen (in diesem Beispiel &amp;lt;code&amp;gt;X&amp;lt;/code&amp;gt;) als Präfix verwenden.&lt;br /&gt;
Auf diese Weise können sämtliche modulspezifisch implementierten Funktionen wie &amp;lt;code&amp;gt;X_Read&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;X_Parse&amp;lt;/code&amp;gt; etc. durch Zuweisung an &amp;lt;code&amp;gt;$hash-&amp;gt;{ReadFn}&amp;lt;/code&amp;gt; bzw. &amp;lt;code&amp;gt;$hash-&amp;gt;{ParseFn}&amp;lt;/code&amp;gt; usw. bekannt gemacht werden.&lt;br /&gt;
&lt;br /&gt;
Darüber hinaus sollten die vom Modul unterstützten Attribute definiert werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
$hash-&amp;gt;{AttrList} =&lt;br /&gt;
  &amp;quot;do_not_notify:1,0 &amp;quot; . &lt;br /&gt;
  &amp;quot;header &amp;quot; .&lt;br /&gt;
  $readingFnAttributes;  &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Auflistung aller unterstützten modulspezifischen Attribute erfolgt in Form einer durch Leerzeichen getrennten Liste in &amp;lt;code&amp;gt;$hash-&amp;gt;{AttrList}}&amp;lt;/code&amp;gt;. Es gibt in FHEM globale Attribute, die in allen Gerätedefinitionen verfügbar sind und nur modulspezifische Attribute die jedes Modul via &amp;lt;code&amp;gt;$hash-&amp;gt;{AttrList}&amp;lt;/code&amp;gt; über die eigene Initialize-Funktion setzt.  In fhem.pl werden dann die entsprechenden Attributwerte beim Aufruf eines &amp;lt;code&amp;gt;attr&amp;lt;/code&amp;gt;-Befehls in die globale Datenstruktur &amp;lt;code&amp;gt;$attr{$name}&amp;lt;/code&amp;gt;, z.B. &amp;lt;code&amp;gt;$attr{$name}{header}&amp;lt;/code&amp;gt; für das Attribut &amp;lt;code&amp;gt;header&amp;lt;/code&amp;gt; gespeichert. Falls im Modul weitere Aktionen oder Prüfungen beim Setzen eines Attributs nötig sind, dann kann wie im Beispiel oben die [[#X_Attr|Attr]]-Funktion implementiert und in der Initialize-Funktion bekannt gemacht werden.&lt;br /&gt;
&lt;br /&gt;
Die Variable &amp;lt;code&amp;gt;$readingFnAttributes&amp;lt;/code&amp;gt;, die im obigen Beispiel an die Liste der unterstützten Attribute angefügt wird, definiert Attributnamen, die dann zusätzlich gemacht werden, wenn das Modul zum Setzen von Readings die Funktionen &amp;lt;code&amp;gt;[[DevelopmentModuleAPI#readingsBeginUpdate|readingsBeginUpdate()]]&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;[[DevelopmentModuleAPI#readingsBulkUpdate|readingsBulkUpdate()]]&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;[[DevelopmentModuleAPI#readingsEndUpdate|readingsEndUpdate()]]&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;[[DevelopmentModuleAPI#readingsSingleUpdate|readingsSingleUpdate()]]&amp;lt;/code&amp;gt; verwendet. In diesen Funktionen werden Attribute wie &amp;lt;code&amp;gt;event-min-interval&amp;lt;/code&amp;gt; oder auch &amp;lt;code&amp;gt;event-on-change-reading&amp;lt;/code&amp;gt; ausgewertet. Für Details hierzu siehe commandref zu [http://fhem.de/commandref.html#readingFnAttributes readingFnAttributes].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Nutzung von parseParams()&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Funktion &amp;lt;code&amp;gt; [[DevelopmentModuleAPI#parseParams|parseParams()]]&amp;lt;/code&amp;gt; unterstützt Modulautoren beim Parsen von Übergabeparametern, welche bei &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;get&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;set&amp;lt;/code&amp;gt; Kommandos an die entsprechenden Modulfunktionen übergeben werden. Dadurch lassen sich auf einfache Weise insbesondere komplexe Parameter (wie bspw. Perl-Ausdrücke) sehr einfach parsen.&lt;br /&gt;
&lt;br /&gt;
Diese Zusatzfunktion kann man in der Initialize-Funktion einfach über folgenden Parameter für [[#X_Define|Define]]-, [[#X_Get|Get]]- und [[#X_Set|Set]]-Funktion modulweit aktivieren:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;$hash-&amp;gt;{parseParams} = 1;&amp;lt;/source&amp;gt;&lt;br /&gt;
Sobald es gesetzt ist wird automatisch durch fhem.pl &amp;lt;code&amp;gt;[[DevelopmentModuleAPI#parseParams|parseParams()]]&amp;lt;/code&amp;gt; aufgerufen und die an die [[#X_Define|Define]]-, [[#X_Get|Get]]- und [[#X_Set|Set]]-Funktion übergebenen Parameter ändern sich wie weiter unten in den jeweiligen Funktionen beschrieben.&lt;br /&gt;
&lt;br /&gt;
==== X_Define ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Define($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $def ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
 &lt;br /&gt;
	return $error;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Define-Funktion eines Moduls wird von FHEM aufgerufen wenn der Define-Befehl für ein Geräte ausgeführt wird und das Modul bereits geladen und mit der Initialize-Funktion initialisiert ist. Sie ist typischerweise dazu da, die übergebenen Parameter zu prüfen und an geeigneter Stelle zu speichern sowie einen Kommunikationsweg zum Gerät zu öffnen (z.B. TCP-Verbindung, USB-Schnittstelle o.ä.) oder einen [[#Pollen_von_Geräten|Status-Timer]] zu starten.&lt;br /&gt;
Sie beginnt typischerweise mit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Define($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $def ) = @_;&lt;br /&gt;
	my @a = split( &amp;quot;[ \t][ \t]*&amp;quot;, $def );&lt;br /&gt;
	...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Als Übergabeparameter bekommt die Define-Funktion den Hash der Geräteinstanz sowie den die im &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt;-Befehl übergebenen Parameter. Welche bzw. wie viele Parameter &lt;br /&gt;
akzeptiert werden und welcher Syntax diese entsprechen müssen ist Sache dieser Funktion. Im obigen Beispiel wird die Argumentzeile &amp;lt;code&amp;gt;$def&amp;lt;/code&amp;gt; in ein Array aufgeteilt (durch Leerzeichen/Tabulator getrennt) und so können die vom Modul bzw. der Define-Funktion erwarteten Werte über das Array der Reihe nach verarbeitet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
my $name   = $a[0];&lt;br /&gt;
my $module = $a[1];&lt;br /&gt;
my $url    = $a[2];&lt;br /&gt;
my $inter  = 300;&lt;br /&gt;
&lt;br /&gt;
if(int(@a) == 4) { &lt;br /&gt;
	$inter = $a[3]; &lt;br /&gt;
	if ($inter &amp;lt; 5) {&lt;br /&gt;
		return &amp;quot;interval too small, please use something &amp;gt; 5s, default is 300 seconds&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Damit die übergebenen Werte auch anderen Funktionen zur Verfügung stehen und an die jeweilige Geräteinstanz gebunden sind, werden die Werte typischerweise als Internals im Hash der Geräteinstanz gespeichert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
$hash-&amp;gt;{url} 		= $url;&lt;br /&gt;
$hash-&amp;gt;{Interval}	= $inter;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sobald alle Parameter korrekt verarbeitet wurden, wird in der Regel die erste Verbindung zum Gerät aufgebaut. Je nach Art des Geräts kann das eine permanente Datenverbindung sein (z.B. serielle Schnittstelle oder TCP-Verbindung) oder das Starten eines regelmäßigen Timers, der zyklisch den Status z.B. via [[HttpUtils|HTTP]] ausliest.&lt;br /&gt;
&lt;br /&gt;
Sollten im Rahmen der Define-Funktion Syntax-Probleme der Übergabeparameter festgestellt werden oder es kann bspw. keine Verbindung aufgebaut werden, so ist als Funktionsrückgabewert eine entsprechende Fehlermeldung zurückzugeben. Nur wenn alle Übergabeparameter akzeptiert werden, darf &amp;lt;code&amp;gt;undef&amp;lt;/code&amp;gt; zurückgegeben werden. Sobald eine Define-Funktion eine Fehlermeldung zurückmeldet, wird der define-Befehl durch FHEM zurückgewiesen und der User erhält die Fehlermeldung, welche die Define-Funktion produziert hat, als Ausgabe zurück.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Verfügbarkeit von Attributen&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Während die Define-Funktion ausgeführt wird, sollte man nicht davon ausgehen, dass alle vom Nutzer konfigurierten Attribute via [[DevelopmentModuleAPI#AttrVal|AttrVal()]] verfügbar sind. Attribute stehen in der Define-Funktion nur dann zur Verfügung, wenn FHEM sich nicht in der Initialisierungsphase befindet (globale Variable &amp;lt;code&amp;gt;$init_done&amp;lt;/code&amp;gt; ist wahr; der Nutzer hat die Gerätedefinition modifiziert). Daher sollte man weiterführende Funktion, welche auf gesetzte Attribute angewiesen sind, nur dann in der Define-Funktion starten, wenn &amp;lt;code&amp;gt;$init_done&amp;lt;/code&amp;gt; zutrifft.&lt;br /&gt;
&lt;br /&gt;
Andernfalls sollte man den Aufruf in der Notify-Funktion durchführen sobald &amp;lt;code&amp;gt;global:INITIALIZED&amp;lt;/code&amp;gt; bzw. &amp;lt;code&amp;gt;global:REREADCFG&amp;lt;/code&amp;gt; getriggert wurde:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Define($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $def ) = @_;&lt;br /&gt;
 &lt;br /&gt;
	...&lt;br /&gt;
&lt;br /&gt;
	$hash-&amp;gt;{NOTIFYDEV} = &amp;quot;global&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	X_FunctionWhoNeedsAttr($hash) if($init_done);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub X_Notify($$)&lt;br /&gt;
{&lt;br /&gt;
	my ($own_hash, $dev_hash) = @_;&lt;br /&gt;
	my $ownName = $own_hash-&amp;gt;{NAME}; # own name / hash&lt;br /&gt;
 &lt;br /&gt;
	return &amp;quot;&amp;quot; if(IsDisabled($ownName)); # Return without any further action if the module is disabled&lt;br /&gt;
 &lt;br /&gt;
	my $devName = $dev_hash-&amp;gt;{NAME}; # Device that created the events&lt;br /&gt;
	my $events = deviceEvents($dev_hash, 1);&lt;br /&gt;
&lt;br /&gt;
	if($devName eq &amp;quot;global&amp;quot; &amp;amp;&amp;amp; grep(m/^INITIALIZED|REREADCFG$/, @{$events}))&lt;br /&gt;
	{&lt;br /&gt;
		 X_FunctionWhoNeedsAttr($hash);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dadurch wird die Modulfunktion X_FunctionWhoNeedsAttr() nach dem Start erst aufgerufen, wenn alle Attribute aus der Konfiguration geladen wurden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Nutzung von parseParams()&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zum Aufteilen und Parsen von &amp;lt;code&amp;gt;$def&amp;lt;/code&amp;gt; lässt sich die Funktion [[DevelopmentModuleAPI#parseParams|parseParams]] verwenden um die einzelnen Argumente einfach zu parsen. Wenn in X_Initialize &amp;lt;code&amp;gt;$hash-&amp;gt;{parseParams} = 1;&amp;lt;/code&amp;gt; gesetzt wurde dann wird parseParams automatisch aufgerufen und X_Define ändert sich wie folgt:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Define($$$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $a, $h ) = @_;&lt;br /&gt;
	...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die genauen Möglichkeiten von parseParams sind in dem entsprechenden [[DevelopmentModuleAPI#parseParams|Artikel]] dokumentiert.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Nutzung von DevIo&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn eine physische Schnittstelle geöffnet werden soll und dann bei verfügbaren Eingabedaten eine Lese-Funktion von Fhem aufgerufen werden soll, dann kann man in der Define-Funktion die Funktion DevIo_OpenDev aufrufen, die sich um alles weitere kümmert. Sie öffnet die Schnittstelle und fügt den Filedeskriptor an die globale Liste offener Verbindungen (selectlist / readyfnlist) an. Damit kann Fhem in seiner Hauptschleife erkennen, von welchem Gerät Daten bereit stehen und die zuständigen Funktionen aufrufen.&lt;br /&gt;
&lt;br /&gt;
Um DevIo mitzuteilen welche Verbindung genau zu öffnen ist, muss das Internal &amp;lt;code&amp;gt;$hash-&amp;gt;{DeviceName} mit einer entsprechenden Syntax gefüllt sein (z.B. &amp;lt;code&amp;gt;&amp;quot;/dev/ttyUSB0@9600&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;192.168.2.105:3000&amp;quot;&amp;lt;/code&amp;gt;, ...). Üblicherweise wird diese Information als Argument im &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt;-Befehl vom Nutzer angegeben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
my $ret = DevIo_OpenDev( $hash, 0, &amp;quot;X_DeviceInit&amp;quot; );&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die optionale Funktion &amp;lt;code&amp;gt;X_DevInit&amp;lt;/code&amp;gt; wird zur weiteren Initialisierung der Verbindung von &amp;lt;code&amp;gt;DevIo_OpenDev&amp;lt;/code&amp;gt; aufgerufen. Der zweite Übergabeparameter an &amp;lt;code&amp;gt;DevIo_OpenDev&amp;lt;/code&amp;gt; (hier &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;) steht für reopen und wird benötigt, da die Funktion auch aufgerufen wird, wenn ein USB-Geräte beispielsweise im Betrieb aus- und wieder eingesteckt wird. In diesem Fall wird die Funktion mit &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; aufgerufen. Dies ist jedoch nur in der [[#X_Ready|X_Ready]]-Funktion notwendig. In der Define-Funktion wird immer &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; (erster Verbindungsversuch) angegen&lt;br /&gt;
&lt;br /&gt;
==== X_Undef ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Undef ($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $name ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
 &lt;br /&gt;
	return $error;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Die Undef-Funktion wird aufgerufen wenn ein Gerät mit &amp;lt;code&amp;gt;delete&amp;lt;/code&amp;gt; gelöscht wird oder bei der Abarbeitung des Befehls &amp;lt;code&amp;gt;rereadcfg&amp;lt;/code&amp;gt;, der ebenfalls alle Geräte löscht und danach das Konfigurationsfile neu einliest. Entsprechend müssen in der Funktion typische Aufräumarbeiten durchgeführt werden wie das saubere Schließen von Verbindungen oder das Entfernen von internen Timern, sofern diese im Modul zum Pollen verwendet wurden (siehe Abschnitt [[#Pollen_von_Geräten|Pollen von Geräten]]). &lt;br /&gt;
&lt;br /&gt;
Zugewiesene Variablen im Hash der Geräteinstanz, Internals oder Readings müssen hier nicht gelöscht werden. In fhem.pl werden die entsprechenden Strukturen beim Löschen der Geräteinstanz ohnehin vollständig gelöscht.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Undef($$)    &lt;br /&gt;
{                     &lt;br /&gt;
	my ( $hash, $name) = @_;       &lt;br /&gt;
	DevIo_CloseDev($hash);         &lt;br /&gt;
	RemoveInternalTimer($hash);    &lt;br /&gt;
	return undef;                  &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sollten im Rahmen der Undef-Funktion Probleme festgestellt werden, die ein Löschen nicht zulassen, so ist als Funktionsrückgabewert eine entsprechende Fehlermeldung zurückzugeben. Nur wenn die Undef-Funktion erfolgreich durchgeführt wurde, darf &amp;lt;code&amp;gt;undef&amp;lt;/code&amp;gt; zurückgegeben werden. Nur dann wird eine Gerätedefinition von FHEM auch tatsächlich gelöscht bzw. neu angelegt. Sollte die Undef-Funktion jedoch eine Fehlermeldung zurückgeben, wird der entsprechende Vorgang (&amp;lt;code&amp;gt;delete&amp;lt;/code&amp;gt; bzw. &amp;lt;code&amp;gt;rereadcfg&amp;lt;/code&amp;gt;) für dieses Gerät abgebrochen. Es bleibt dann unverändert in FHEM bestehen.&lt;br /&gt;
&lt;br /&gt;
==== X_Delete ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Delete ($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $name ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
 &lt;br /&gt;
	return $error;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Delete-Funktion ist das Gegenstück zur Funktion [[#X_Define|X_Define]] und wird aufgerufen wenn ein Gerät mit dem Befehl &amp;lt;code&amp;gt;delete&amp;lt;/code&amp;gt; gelöscht wird. &lt;br /&gt;
&lt;br /&gt;
Wenn ein Gerät in FHEM gelöscht wird, wird zuerst die Funktion [[#X_Undef|X_Undef]] aufgerufen um offene Verbindungen zu schließen, anschließend wird die Funktion X_Delete aufgerufen. Diese dient eher zum Aufräumen von dauerhaften Daten, welche durch das Modul evtl. für dieses Gerät spezifisch erstellt worden sind. Es geht hier also eher darum, alle Spuren sowohl im laufenden FHEM-Prozess, als auch dauerhafte Daten bspw. im physikalischen Gerät zu löschen die mit dieser Gerätedefinition zu tun haben.&lt;br /&gt;
&lt;br /&gt;
Dies kann z.B. folgendes sein:&lt;br /&gt;
&lt;br /&gt;
* Löschen von Dateien im Dateisystem die während der Nutzung dieses Geräts angelegt worden sind.&lt;br /&gt;
* Lösen von evtl. Pairings mit dem physikalischen Gerät &lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Delete($$)    &lt;br /&gt;
{                     &lt;br /&gt;
	my ( $hash, $name ) = @_;       &lt;br /&gt;
&lt;br /&gt;
	# Löschen von Geräte-assoziiertem Temp-File&lt;br /&gt;
	unlink($attr{global}{modpath}.&amp;quot;/FHEM/FhemUtils/$name.tmp&amp;quot;;)&lt;br /&gt;
&lt;br /&gt;
	return undef;&lt;br /&gt;
}    &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sollten im Rahmen der Delete-Funktion Probleme festgestellt werden, die ein Löschen nicht zulassen, so ist als Funktionsrückgabewert eine entsprechende Fehlermeldung zurückzugeben. Nur die Delete-Funktion erfolgreich durchgeführt wurde, darf &amp;lt;code&amp;gt;undef&amp;lt;/code&amp;gt; zurückgegeben werden. Nur dann wird eine Gerätedefinition von FHEM auch tatsächlich gelöscht. Sollte die Delete-Funktion eine Fehlermeldung zurückgeben, wird der Löschvorgang abgebrochen und das Gerät bleibt weiter in FHEM bestehen.&lt;br /&gt;
&lt;br /&gt;
==== X_Get ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Get ($$@)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $name, $opt, @args ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
 &lt;br /&gt;
	return $result;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Die Get-Funktion wird aufgerufen wenn der FHEM-Befehl &amp;lt;code&amp;gt;get&amp;lt;/code&amp;gt; mit einem Gerät dieses Moduls ausgeführt wird. Mit &amp;lt;code&amp;gt;get&amp;lt;/code&amp;gt; werden typischerweise Werte von einem Gerät abgefragt. In vielen Modulen wird auf diese Weise auch der Zugriff auf generierte Readings ermöglicht. Der Get-Funktion wird dabei der Geräte-Hash, der Gerätename, sowie die Aufrufparameter des get-Befehls übergeben. Als Rückgabewert wird das Ergebnis des entsprechenden Befehls in Form einer Zeichenkette zurückgegeben. Der Rückgabewert &amp;lt;code&amp;gt;undef&amp;lt;/code&amp;gt; hat hierbei keine besondere Bedeutung und wird behandelt wie eine leere Zeichenkette &amp;lt;code&amp;gt;&amp;quot;&amp;quot;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Get($$@)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $name, $opt, @args ) = @_;&lt;br /&gt;
&lt;br /&gt;
	return &amp;quot;\&amp;quot;get $name\&amp;quot; needs at least one argument&amp;quot; unless(defined($opt)));&lt;br /&gt;
&lt;br /&gt;
	if($opt eq &amp;quot;status&amp;quot;) &lt;br /&gt;
	{&lt;br /&gt;
	   ...&lt;br /&gt;
	}&lt;br /&gt;
	elsif($opt eq &amp;quot;powser&amp;quot;)&lt;br /&gt;
	{&lt;br /&gt;
	   ...&lt;br /&gt;
	}&lt;br /&gt;
	...&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		return &amp;quot;Unknown argument $opt, choose one of status power [...]&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn eine unbekannte Option an die Get-Funktion übergeben wird, so muss als Rückgabewert der Funktion eine bestimmte Syntax einhalten um FHEM mitzuteilen, welche Optionen für einen Get-Befehl aktuell unterstützt werden. Die Rückgabe muss dabei folgender Syntax entsprechen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&#039;&#039;&#039;unknown&#039;&#039;&#039; argument &#039;&#039;&amp;lt;font color=&amp;quot;grey&amp;quot;&amp;gt;[Parameter]&amp;lt;/font&amp;gt;&#039;&#039; &#039;&#039;&#039;choose one of&#039;&#039;&#039; &#039;&#039;&amp;lt;font color=&amp;quot;grey&amp;quot;&amp;gt;[Liste möglicher Optionen]&amp;lt;/font&amp;gt;&#039;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hierbei sind die fett gedruckten Teile der Rückmeldung besonders wichtig. Sind diese nicht vorhanden, kann FHEM nicht die möglichen Get-Kommandos für das entsprechende Gerät ermitteln. Es muss am Anfang der Meldung das Stichwort &amp;quot;unknown&amp;quot; vorkommen gefolgt von einer frei definierbaren Fehlermeldung (i.d.R der übergebene Parameter, welcher ungültig ist). Anschließend folgt &amp;quot;choose one of&amp;quot; mit einer anschließenden Liste möglicher Optionen getrennt durch ein Leerzeichen. &lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;return &amp;quot;unknown argument $opt choose one of state temperature humidity&amp;quot;;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hier werden als mögliche Optionen für einen Get-Befehl folgende Parameter angegeben:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;temperature&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;humidity&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dies würde in folgenden, mögliche Get-Befehle für einen User resultieren:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;get &#039;&#039;&amp;amp;lt;NAME&amp;amp;gt;&#039;&#039; state&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;get &#039;&#039;&amp;amp;lt;NAME&amp;amp;gt;&#039;&#039; temperature&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;get &#039;&#039;&amp;amp;lt;NAME&amp;amp;gt;&#039;&#039; humidity&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Ausgabe einer solchen Meldung ist sehr wichtig, da sie im GUI-Modul verwendet wird um die möglichen &amp;lt;code&amp;gt;get&amp;lt;/code&amp;gt;-Optionen zu ermitteln und als Auswahl anzubieten. Im weiteren Verlauf der Get-Funktion könnte man dann mit dem physischen Gerät kommunizieren und den gefragten Wert direkt abfragen und diesen als Return-Wert der Get-Funktion zurückgeben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Nutzung von parseParams()&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn in [[#X_Initialize|X_Initialize]] &amp;lt;code&amp;gt;$hash-&amp;gt;{parseParams} = 1;&amp;lt;/code&amp;gt; gesetzt wurde dann wird [[DevelopmentModuleAPI#parseParams|parseParams]] automatisch aufgerufen und X_Get ändert sich wie folgt:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Get($$$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $a, $h ) = @_;&lt;br /&gt;
	...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die genauen Möglichkeiten von parseParams sind in dem entsprechenden [[DevelopmentModuleAPI#parseParams|Artikel]] dokumentiert.&lt;br /&gt;
&lt;br /&gt;
==== X_Set ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Set ($$@)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $name, $cmd, @args ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
 &lt;br /&gt;
	return $error;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Set-Funktion ist das Gegenteil zur [[#X_Get|Get]]-Funktion. Sie ist dafür gedacht, Daten zum physischen Gerät zu schicken, bzw. entsprechende Aktionen im Gerät selber auszulösen. Ein Set-Befehl dient daher der direkten Steuerung des physikalischen Gerätes in dem es bspw. Zustände verändert (wie &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;off&amp;lt;/code&amp;gt;). Der Set-Funktion wird dabei der Geräte-Hash, der Gerätename, sowie die Aufrufparameter des set-Befehls übergeben. Als Rückgabewert kann eine Fehlermeldung in Form Zeichenkette zurückgegeben werden. Der Rückgabewert &amp;lt;code&amp;gt;undef&amp;lt;/code&amp;gt; bedeutet hierbei, dass der Set-Befehl erfolgreich durchgeführt wurde. Eine Set-Funktion gibt daher nur im Fehlerfall eine Rückmeldung mit einer entsprechenden Fehlermeldung. Der Wert &amp;lt;code&amp;gt;undef&amp;lt;/code&amp;gt; wird als &amp;quot;erfolgreich&amp;quot; interpretiert. Rückmeldungen von set-Befehlen sämtlicher Module, die im Rahmen eines ausgeführten [[Notify]] auftreten werden im FHEM Logfile festgehalten.&lt;br /&gt;
&lt;br /&gt;
Falls nur interne Daten, die ausschließlich für das Modul relevant sind, gesetzt werden müssen, so sollte statt Set die [[#X_Attr|Attr]]-Funktion verwendet werden. Attribute werden bei Save-Config auch in der Fhem.cfg gesichert. Set-Befehle nicht, da sie nur zur Steuerungszwecken im laufenden Betrieb von FHEM dienen.&lt;br /&gt;
 &lt;br /&gt;
Eine Set-Funktion ist ähnlich aufgebaut wie die Get-Funktion, sie bekommt jedoch in der Regel weitere zusätzliche Parameter übergeben um Zustände zu setzen. &lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Set($@)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $name, $cmd, @args ) = @_;&lt;br /&gt;
&lt;br /&gt;
	return &amp;quot;\&amp;quot;set $name\&amp;quot; needs at least one argument&amp;quot; unless(defined($cmd)));&lt;br /&gt;
&lt;br /&gt;
	if($cmd eq &amp;quot;status&amp;quot;)&lt;br /&gt;
	{&lt;br /&gt;
	   if($args[0] eq &amp;quot;up&amp;quot;)&lt;br /&gt;
	   {&lt;br /&gt;
	      ...&lt;br /&gt;
	   }&lt;br /&gt;
	   elsif($args[0] eq &amp;quot;down&amp;quot;)&lt;br /&gt;
	   {&lt;br /&gt;
	      ...&lt;br /&gt;
	   }&lt;br /&gt;
	   else&lt;br /&gt;
	   {&lt;br /&gt;
	      return &amp;quot;Unknown value $args[0] for $cmd, choose one of status power&amp;quot;;&lt;br /&gt;
	   }   &lt;br /&gt;
	}&lt;br /&gt;
	elsif($cmd eq &amp;quot;power&amp;quot;)&lt;br /&gt;
	{&lt;br /&gt;
	   if($args[0] eq &amp;quot;on&amp;quot;)&lt;br /&gt;
	   {&lt;br /&gt;
	      ...&lt;br /&gt;
	   }&lt;br /&gt;
	   elsif($args[0] eq &amp;quot;off&amp;quot;)&lt;br /&gt;
	   {&lt;br /&gt;
	      ...&lt;br /&gt;
	   }  &lt;br /&gt;
	   else&lt;br /&gt;
	   {&lt;br /&gt;
	      return &amp;quot;Unknown value $args[0] for $cmd, choose one of status power&amp;quot;;&lt;br /&gt;
	   }       &lt;br /&gt;
	}&lt;br /&gt;
	...&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		return &amp;quot;Unknown argument $cmd, choose one of status power&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn eine unbekannte Option an die Set-Funktion übergeben wird, so muss als Rückgabewert der Funktion eine bestimmte Syntax eingehalten werden um FHEM mitzuteilen, welche Optionen für einen Set-Befehl aktuell unterstützt werden. Die Rückgabe muss dabei folgender Syntax entsprechen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&#039;&#039;&#039;unknown&#039;&#039;&#039; argument &#039;&#039;&amp;lt;font color=&amp;quot;grey&amp;quot;&amp;gt;[Parameter]&amp;lt;/font&amp;gt;&#039;&#039; &#039;&#039;&#039;choose one of&#039;&#039;&#039; &#039;&#039;&amp;lt;font color=&amp;quot;grey&amp;quot;&amp;gt;[Liste möglicher Optionen]&amp;lt;/font&amp;gt;&#039;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hierbei sind die fett gedruckten Teile der Rückmeldung besonders wichtig. Sind diese nicht vorhanden, kann FHEM nicht die möglichen Set-Kommandos für das entsprechende Gerät ermitteln. Es muss am Anfang der Meldung das Stichwort &amp;quot;unknown&amp;quot; vorkommen gefolgt von einer frei definierbaren Fehlermeldung (i.d.R der übergebene Parameter, welcher ungültig ist). Anschließend folgt &amp;quot;choose one of&amp;quot; mit einer anschließenden Liste möglicher Optionen getrennt durch ein Leerzeichen. &lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;return &amp;quot;unknown argument $cmd choose one of state power&amp;quot;;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hier werden als mögliche Optionen für einen Get-Befehl folgende Parameter angegeben:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;power&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dies würde in folgenden, mögliche Get-Befehle für einen User resultieren:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;get &#039;&#039;&amp;amp;lt;NAME&amp;amp;gt;&#039;&#039; state&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;get &#039;&#039;&amp;amp;lt;NAME&amp;amp;gt;&#039;&#039; power&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Ausgabe einer solchen Meldung ist sehr wichtig, da sie im GUI-Modul verwendet wird um die möglichen &amp;lt;code&amp;gt;set&amp;lt;/code&amp;gt;-Optionen zu ermitteln und als Auswahl anzubieten&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Nutzung von SetExtensions.pm&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn man dem Nutzer zusätzlich zu den Set-Befehlen &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;off&amp;lt;/code&amp;gt; auch weiterführende Befehle wie &amp;lt;code&amp;gt;on-for-timer&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;on-till&amp;lt;/code&amp;gt;, usw. anbieten möchte, obwohl die zu steuernde Hardware solche Kommandos nicht unterstützt, kann man dies über das Hilfsmodul SetExtensions.pm realisieren.&lt;br /&gt;
&lt;br /&gt;
Das Hilfsmodul SetExtensions.pm bietet weiterführende Set-Kommandos basierend auf den Befehlen &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;off&amp;lt;/code&amp;gt; an. Dabei werden durch interne Timer bzw. eigens angelegten [[at]]-Definitionen diese Befehle durch FHEM selber umgesetzt. Je nach ausgeführtem Befehl wird der &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt;- bzw. &amp;lt;code&amp;gt;off&amp;lt;/code&amp;gt;-Befehl dann durch FHEM zum richtigen Zeitpunkt ausgeführt. Vorausgesetzt das Modul unterstützt in der Set-Funktion die Befehle &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;off&amp;lt;/code&amp;gt;, so werden durch den Einsatz von SetExtensions.pm folgende Befehle zusätzlich unterstützt:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Set-Kommando !! Beispiel !! Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;on-for-timer &#039;&#039;&amp;amp;lt;Dauer&amp;amp;gt;&#039;&#039;&amp;lt;/code&amp;gt;  || style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;on-for-timer 120&amp;lt;/code&amp;gt; || Schaltet das Gerät sofort mit dem &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt;-Befehl ein und nach der angegebenen Dauer in Sekunden via &amp;lt;code&amp;gt;off&amp;lt;/code&amp;gt; wieder aus.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;off-for-timer &#039;&#039;&amp;amp;lt;Dauer&amp;amp;gt;&#039;&#039;&amp;lt;/code&amp;gt;  || style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;off-for-timer 120&amp;lt;/code&amp;gt; || Schaltet das Gerät sofort mit dem &amp;lt;code&amp;gt;off&amp;lt;/code&amp;gt;-Befehl aus und nach der angegebenen Dauer in Sekunden via &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt; wieder ein.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;on-till &#039;&#039;&amp;amp;lt;Zeitpunkt&amp;amp;gt;&#039;&#039;&amp;lt;/code&amp;gt;  || style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;on-till 16:30&amp;lt;/code&amp;gt; || Schaltet das Gerät sofort mit dem &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt;-Befehl ein und zum angegebenen Zeitpunkt via &amp;lt;code&amp;gt;off&amp;lt;/code&amp;gt; wieder aus.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;off-till &#039;&#039;&amp;amp;lt;Zeitpunkt&amp;amp;gt;&#039;&#039;&amp;lt;/code&amp;gt;  || style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;off-till 16:30&amp;lt;/code&amp;gt; || Schaltet das Gerät sofort mit dem &amp;lt;code&amp;gt;off&amp;lt;/code&amp;gt;-Befehl aus und zum angegebenen Zeitpunkt via &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt; wieder ein.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;on-till-overnight &#039;&#039;&amp;amp;lt;Zeitpunkt&amp;amp;gt;&#039;&#039;&amp;lt;/code&amp;gt;  || style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;on-till-overnight 01:00&amp;lt;/code&amp;gt; || Ähnlich wie &amp;lt;code&amp;gt;on-till&amp;lt;/code&amp;gt;. Der übergebene Zeitpunkt wird aber nicht geprüft, ob er für den heutigen Tag bereits überschritten wurde. Dadurch kann man Abends einen Zeitpunkt setzen, der erst am nächsten Tag zutrifft.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;off-till-overnight &#039;&#039;&amp;amp;lt;Zeitpunkt&amp;amp;gt;&#039;&#039;&amp;lt;/code&amp;gt;  || style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;off-till-overnight 01:00&amp;lt;/code&amp;gt; || Ähnlich wie &amp;lt;code&amp;gt;off-till&amp;lt;/code&amp;gt;. Der übergebene Zeitpunkt wird aber nicht geprüft, ob er für den heutigen Tag bereits überschritten wurde. Dadurch kann man Abends einen Zeitpunkt setzen, der erst am nächsten Tag zutrifft.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;blink &#039;&#039;&amp;amp;lt;Anzahl&amp;amp;gt; &amp;amp;lt;Interval&amp;amp;gt;&#039;&#039;&amp;lt;/code&amp;gt;  || style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;blink 3 1&amp;lt;/code&amp;gt; || Schaltet das Gerät via &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt; für &amp;lt;code&amp;gt;&#039;&#039;&amp;amp;lt;Interval&amp;amp;gt;&#039;&#039;&amp;lt;/code&amp;gt; Sekunden ein und anschließend via &amp;lt;code&amp;gt;off&amp;lt;/code&amp;gt; wieder aus. Nach &amp;lt;code&amp;gt;&#039;&#039;&amp;amp;lt;Interval&amp;amp;gt;&#039;&#039;&amp;lt;/code&amp;gt; Sekunden wird das ganze wiederholt, solange bis die angegebene Anzahl erreicht ist.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;intervals &#039;&#039;&amp;amp;lt;Start&amp;amp;gt;-&amp;amp;lt;Ende&amp;amp;gt;&#039;&#039; &#039;&#039;&amp;amp;lt;Start&amp;amp;gt;-&amp;amp;lt;Ende&amp;amp;gt;&#039;&#039; ...&amp;lt;/code&amp;gt; || style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;intervals 07:00-08:00 16:30-18:00&amp;lt;/code&amp;gt; || Schaltet das Gerät innerhalb der übergebenen Zeiträumen via &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt; ein. Sobald die aktuelle Zeit ausserhalb dieser Zeiträume liegt, wird das Gerät via &amp;lt;code&amp;gt;off&amp;lt;/code&amp;gt; wieder ausgeschaltet. Es können dabei beliebig viele Zeiträume angegeben werden.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;toggle&amp;lt;/code&amp;gt; || style=&amp;quot;white-space: nowrap;&amp;quot; | &amp;lt;code&amp;gt;toggle&amp;lt;/code&amp;gt;  || Sofern der aktuelle Status &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt; ist, wird das Gerät via &amp;lt;code&amp;gt;off&amp;lt;/code&amp;gt; ausgeschaltet. Andernfalls wird es via &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt; eingeschaltet.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Eine kurze Beschreibung zu den möglichen Befehlen durch SetExtensions.pm gibt es auch in der Commandref zum [http://fhem.de/commandref.html#set Set-Befehl].&lt;br /&gt;
&lt;br /&gt;
Um SetExtensions.pm in der Set-Funktion nutzen zu können müssen folgende Aktionen durchgeführt werden:&lt;br /&gt;
&lt;br /&gt;
# Laden von SetExtensions.pm via &amp;lt;code&amp;gt;use SetExtensions;&amp;lt;/code&amp;gt; am Anfang des Moduls&lt;br /&gt;
# Aufruf und Rückgabe der Funktion [[DevelopmentModuleAPI#SetExtensions|SetExtensions()]] sofern die Set-Funktion mit dem übergebenen Befehl nichts anfangen kann.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
use SetExtensions;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
sub X_Set($@)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $name, $cmd, @args ) = @_;&lt;br /&gt;
	my $cmdList = &amp;quot;on off&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	return &amp;quot;\&amp;quot;set $name\&amp;quot; needs at least one argument&amp;quot; unless(defined($cmd)));&lt;br /&gt;
&lt;br /&gt;
	if($cmd eq &amp;quot;on&amp;quot;)&lt;br /&gt;
	{&lt;br /&gt;
		# Gerät einschalten...&lt;br /&gt;
	}&lt;br /&gt;
	elsif($cmd eq &amp;quot;off&amp;quot;)&lt;br /&gt;
	{&lt;br /&gt;
		# Gerät ausschalten...&lt;br /&gt;
	}&lt;br /&gt;
	...&lt;br /&gt;
	else # wenn der übergebene Befehl nicht durch X_Set() verarbeitet werden kann, Weitergabe an SetExtensions()&lt;br /&gt;
	{&lt;br /&gt;
		return SetExtensions($hash, $cmdList, $name, $cmd, @args);&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sollte der übergebene Set-Befehl auch für SetExtensions unbekannt sein (bspw. &amp;lt;code&amp;gt;set &#039;&#039;&amp;amp;lt;Name&amp;amp;gt;&#039;&#039; ?&amp;lt;/code&amp;gt;), so generiert SetExtensions() eine entsprechende Usage-Meldung, welche innerhalb der Set-Funktion an FHEM zurückgegeben werden muss.&lt;br /&gt;
&lt;br /&gt;
Eine ausführliche Beschreibung zu der Funktion SetExtensions() gibt es in der  [[DevelopmentModuleAPI#SetExtensions|API-Referenz]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Nutzung von parseParams()&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn in [[#X_Initialize|X_Initialize]] &amp;lt;code&amp;gt;$hash-&amp;gt;{parseParams} = 1;&amp;lt;/code&amp;gt; gesetzt wurde dann wird [[DevelopmentModuleAPI#parseParams|parseParams]] automatisch aufgerufen und X_Set ändert sich wie folgt:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Set($$$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $a, $h ) = @_;&lt;br /&gt;
	...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die genauen Möglichkeiten von parseParams sind in dem entsprechenden [[DevelopmentModuleAPI#parseParams|Artikel]] dokumentiert.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Nutzung von FHEMWEB-Widgets&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das GUI-Modul [[FHEMWEB]] kann für die einzelnen Set-Optionen, die das Modul versteht, automatisch Eingabehilfen wie Drop-Down Boxen oder Slider erzeugen. In der Detailansicht der GUI kann der Anwender dann die jeweiligen Werte komfortabel auswählen. Dafür muss die Set-Funktion, wenn sie mit der Option &amp;lt;code&amp;gt;?&amp;lt;/code&amp;gt; aufgerufen wird, nicht nur einen Text mit  &amp;lt;code&amp;gt;&amp;quot;Unknown ... choose one of ...&amp;quot;&amp;lt;/code&amp;gt; zurückgeben sondern den einzelnen Set-Optionen in diesem Rückgabetext nach einem Doppelpunkt entsprechende Zusatzinformationen anhängen.&lt;br /&gt;
Meist prüft man in den Modulen gar nicht auf die Option &amp;lt;code&amp;gt;?&amp;lt;/code&amp;gt; sondern gibt generell bei unbekannten Optionen diesen Text zurück. Das Modul FHEMWEB ermittelt die Syntax eines Gerätes jedoch immer mit dem Befehl:&lt;br /&gt;
 set &#039;&#039;&amp;amp;lt;NAME&amp;amp;gt;&#039;&#039; ?&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
	return &amp;quot;Unknown argument $cmd, choose one of state:up,down power:on,off on:noArg off:noArg&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit Kommata getrennte Werte ergeben eine Drop-Down Liste, mit der der User die Werte auswählen kann&lt;br /&gt;
&amp;lt;pre&amp;gt;timer:30,120,300&lt;br /&gt;
mode:verbose,ultra,relaxed&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wird kein Doppelpunkt zum Kommando angegeben, so wird eine Eingabezeile angezeigt, die die freie Eingabe eines Wertes erlaubt.&lt;br /&gt;
&lt;br /&gt;
Man kann jedoch die Eingabe-/Auswahlmöglichkeiten durch Widgets vereinfachen. Dazu gibt man hinter dem Doppelpunkt einen Widgetnamen und widgetspezifische Parameter an. Es existieren mehrere solcher Widgets in FHEMWEB. Die gebräuchlichsten sind:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Zusatz !! Beispiel !! Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;noArg&#039;&#039;&#039; || &amp;lt;code&amp;gt;reset:noArg&amp;lt;/code&amp;gt;|| Es werden keine weiteren Argumente mehr benötigt. In so einem Fall wird bei der Auswahl keine Textbox oder ähnliches angezeigt, da keine weiteren Argumente für diesen Befehl notwendig sind.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;slider&#039;&#039;&#039;:&amp;lt;min&amp;gt;,&amp;lt;step&amp;gt;,&amp;lt;max&amp;gt; || &amp;lt;code&amp;gt;dim:slider,0,1,100&amp;lt;/code&amp;gt;|| Es wird ein Schieberegler angezeigt um den Parameter auszuwählen. Dabei werden als Zusatzparameter Minimum, Schrittweite und Maximum angegeben.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;colorpicker&#039;&#039;&#039; || &amp;lt;code&amp;gt;rgb:colorpicker,RGB&amp;lt;/code&amp;gt;|| Es wird ein Colorpicker angezeigt, der dem Anwender die Auswahl einer Farbe ermöglicht. Die genaue Parametersyntax kann man dem Artikel zum  [[Color#Colorpicker|Colorpicker]] entnehmen.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;multiple&#039;&#039;&#039; || &amp;lt;code&amp;gt;group:multiple,Telefon,Multimedia,Licht,Heizung&amp;lt;/code&amp;gt; || Es erscheint ein Auswahldialog, wo man verschiedene Werte durch klicken auswählen kann. Optional kann man in einem Freitext eigene Werte ergänzen. dieser Dialog wird bspw. bei der Raum-Auswahl (Attribut &amp;quot;room&amp;quot;) oder der Gruppen-Auswahl (Attribut &amp;quot;group&amp;quot;) in FHEMWEB genutzt. &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;sortable&#039;&#039;&#039; || &amp;lt;code&amp;gt;command:sortable,monday,tuesday,...&amp;lt;/code&amp;gt; || Es erscheint ein Auswahldialog, wo man verschiedene Werte auswählen und sortieren kann. Man kann dabei Werte durch Klicken auswählen und durch Drag&#039;n&#039;Drop sortieren.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Es gibt noch weitere solcher Widgets. Eine genaue Auflistung dazu findet sich in der [http://fhem.de/commandref.html#widgetOverride commandref] unter widgetOverride zu FHEMWEB.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweise&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Damit in einer Eingabe bereits der aktuelle Wert vorbelegt bzw. in einer Auswahlliste der aktuelle Wert vorselektiert ist, muss es im Modul bzw. Gerät ein Reading mit dem gleichen Namen wie die Set-Option geben. Der Wert des gleichnamigen Readings wird dann als Vorbelegung / Vorselektion verwendet. &lt;br /&gt;
* Der User kann sich in der Raumübersicht nach wie vor via [[WebCmd|webCmd]] eine entsprechende Steuerung anlegen.&lt;br /&gt;
&lt;br /&gt;
==== X_Attr ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Attr ($$$$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $cmd, $name, $attrName, $attrValue  ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
 &lt;br /&gt;
	return $error;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Attr-Funktion dient der Prüfung von Attributen, welche über den &amp;lt;code&amp;gt;attr&amp;lt;/code&amp;gt;-Befehl gesetzt werden können. Sobald versucht wird, ein Attribut für ein Gerät zu setzen, wird vorher die Attr-Funktion des entsprechenden Moduls aufgerufen um zu prüfen, ob das Attribut aus Sicht des Moduls korrekt ist.&lt;br /&gt;
Liegt ein Problem mit dem Attribut bzw. dem Wert vor, so muss die Funktion eine aussagekräftige Fehlermeldung zurückgeben, welche dem User angezeigt wird.&lt;br /&gt;
Sofern das übergebene Attribut samt Inhalt korrekt ist, gibt die Attr-Funktion den Wert &amp;lt;code&amp;gt;undef&amp;lt;/code&amp;gt; zurück. Erst dann wird das Attribut in der globalen Datenstruktur &amp;lt;code&amp;gt;%attr&amp;lt;/code&amp;gt; gespeichert und ist somit erst aktiv.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
X_Attr(@)&lt;br /&gt;
{&lt;br /&gt;
	my ( $cmd, $name, $attrName, $attrValue ) = @_;&lt;br /&gt;
    &lt;br /&gt;
  	# $cmd  - Vorgangsart - kann die Werte &amp;quot;del&amp;quot; (löschen) oder &amp;quot;set&amp;quot; (setzen) annehmen&lt;br /&gt;
	# $name - Gerätename&lt;br /&gt;
	# $attrName/$attrValue sind Attribut-Name und Attribut-Wert&lt;br /&gt;
    &lt;br /&gt;
	if ($cmd eq &amp;quot;set&amp;quot;) {&lt;br /&gt;
		if ($aName eq &amp;quot;Regex&amp;quot;) {&lt;br /&gt;
			eval { qr/$aVal/ };&lt;br /&gt;
			if ($@) {&lt;br /&gt;
				Log3 $name, 3, &amp;quot;X ($name) - Invalid regex in attr $name $aName $aVal: $@&amp;quot;;&lt;br /&gt;
				return &amp;quot;Invalid Regex $aVal: $@&amp;quot;;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	return undef;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zusätzlich ist es möglich auch übergebene Attributwerte zu verändern bzw. zu korrigieren, indem man im Parameterarray &amp;lt;code&amp;gt;@_&amp;lt;/code&amp;gt; den ursprünglichen Wert anpasst. Dies erfolgt im Beispiel über die Modifikation des Wertes mit Index 3 (entspricht dem 4. Element) im Parameterarray, also &amp;lt;code&amp;gt;$_[3]&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Da das Attribut zum Zeitpunkt des Aufrufs der Attr-Funktion noch nicht gespeichert ist, wird der neue Wert zu diesem Zeitpunkt noch nicht via [[DevelopmentModuleAPI#AttrVal|AttrVal()]] zurückgegeben. Erst, wenn die Attr-Funktion mit &amp;lt;code&amp;gt;undef&amp;lt;/code&amp;gt; beendet ist, wird der neue Wert in FHEM gespeichert und steht dann via AttrVal() zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
Die Attr-Funktion bekommt nicht den Hash der Geräteinstanz übergeben, da sie normalerweise keine Werte dort speichern muss, sondern lediglich das Attribut auf Korrektheit prüfen muss.&lt;br /&gt;
Im obigen Beispiel wird für ein Attribut mit Namen &amp;quot;Regex&amp;quot; geprüft ob der reguläre Ausdruck fehlerhaft ist. Sofern dieser OK ist, wird &amp;lt;code&amp;gt;undef&amp;lt;/code&amp;gt; zurückgegeben und fhem.pl speichert den Wert des Attributs in &amp;lt;code&amp;gt;%attr&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Attributnamen mit Platzhaltern&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Falls man Attribute in der [[#X_Initialize|Initialize]]-Funktion mit Platzhaltern definiert (Wildcard-Attribute) wie z.B.:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
    $hash-&amp;gt;{AttrList} =&lt;br /&gt;
      &amp;quot;reading[0-9]*Name &amp;quot; .&lt;br /&gt;
    # usw.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
dann können Anwender Attribute wie reading01Name, reading02Name etc. setzen. Leider funktioniert das bisher nicht durch Klicken in der Web-Oberfläche, da FHEMWEB nicht alle denkbaren Ausprägungen in einem Dropdown anbieten kann. Der Benutzer muss solche Attribute manuell über den &amp;lt;code&amp;gt;attr&amp;lt;/code&amp;gt;-Befehl eingeben.&lt;br /&gt;
&lt;br /&gt;
Man kann jedoch in der Attr-Funktion neu gesetzte Ausprägungen von Wildcard-Attributen an die gerätespezifische userattr-Variable anfügen. Dann können bereits gesetzte Attribute in FHEMWEB durch Klicken ausgewählt und geändert werden.&lt;br /&gt;
Dazu reicht ein Aufruf der Funktion [[DevelopmentModuleAPI#addToDevAttrList|addToDevAttrList()]]: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
    addToDevAttrList($name, $aName);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== X_Read ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Read ($)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Die X_Read-Funktion wird aufgerufen, wenn ein dem Gerät zugeordneter Filedeskriptor (serielle Schnittstelle, TCP-Verbindung, ...) Daten zum Lesen bereitgestellt hat. Die Daten müssen nun eingelesen und interpretiert werden.&lt;br /&gt;
&lt;br /&gt;
Im folgenden Beispiel wird über eine serielle Schnittstelle (beziehungsweise über einen USB-To-Seriell-Konverter) von einem angeschlossenen Gerät gelesen. Dazu werden die bisher verfügbaren Daten mit der Funktion &amp;lt;code&amp;gt;DevIo_SimpleRead&amp;lt;/code&amp;gt; gelesen. Da die Übertragung möglicherweise noch nicht vollständig ist, kann es sein, dass kurz darauf die X_Read-Funktion wieder aufgerufen wird und ein weiterer Teil oder der Rest der Daten gelesen werden kann.&lt;br /&gt;
Die Funktion muss daher prüfen ob schon alle erwarteten Daten angekommen sind und gegebenenfalls die bisher gelesenen Daten in einem eigenen Puffer (idealerweise in &amp;lt;code&amp;gt;$hash&amp;lt;/code&amp;gt;) zwischenspeichern. Im Beispiel ist dies &amp;lt;code&amp;gt;$hash-&amp;gt;{helper}{BUFFER}&amp;lt;/code&amp;gt; an den die aktuell gelesenen Daten angehängt werden, bis die folgende Prüfung ein für das jeweilige Protokoll vollständige Frame erkennt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Read($)&lt;br /&gt;
{&lt;br /&gt;
	my ($hash) = @_;&lt;br /&gt;
	my $name = $hash-&amp;gt;{NAME};&lt;br /&gt;
	&lt;br /&gt;
	# einlesen der bereitstehenden Daten&lt;br /&gt;
	my $buf = DevIo_SimpleRead($hash);		&lt;br /&gt;
	return &amp;quot;&amp;quot; if ( !defined($buf) );&lt;br /&gt;
	Log3 $name, 5, &amp;quot;X ($name) - received data: &amp;quot;.$buf;    &lt;br /&gt;
&lt;br /&gt;
	# Daten in Hex konvertieren und an den Puffer anhängen&lt;br /&gt;
	$hash-&amp;gt;{helper}{BUFFER} .= unpack (&#039;H*&#039;, $buf);	&lt;br /&gt;
	Log3 $name, 5, &amp;quot;X ($name) - current buffer content: &amp;quot;.$hash-&amp;gt;{helper}{BUFFER};&lt;br /&gt;
&lt;br /&gt;
	# prüfen, ob im Buffer ein vollständiger Frame zur Verarbeitung vorhanden ist.&lt;br /&gt;
	if ($hash-&amp;gt;{helper}{BUFFER} =~ &amp;quot;ff1002(.{4})(.*)1003(.{4})ff(.*)&amp;quot;) {&lt;br /&gt;
	...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die zu lesenden Nutzdaten können dann je nach Protokoll des Geräts beispielsweise an einer festgelegten Stelle im Frame (dann in &amp;lt;code&amp;gt;$hash-&amp;gt;{helper}{BUFFER}&amp;lt;/code&amp;gt;) stehen oder aus dem Kontext mit einem Regex-Match extrahiert werden und via [[DevelopmentModuleAPI#Readings_.2F_Events|Reading-Funktionen]] in Readings gespeichert werden (siehe unten).&lt;br /&gt;
&lt;br /&gt;
Der Rückgabewert der Read-Funktion wird nicht geprüft und hat daher keinerlei Bedeutung.&lt;br /&gt;
&lt;br /&gt;
==== X_Ready ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Ready ($)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
    &lt;br /&gt;
	return $success;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wird im Main-Loop aufgerufen falls das Modul in der globalen Liste &amp;lt;code&amp;gt;%readyfnlist&amp;lt;/code&amp;gt; existiert. Diese Funktion hat je nachdem auf welchem OS FHEM ausgeführt wird unterschiedliche Aufgaben:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;UNIX-artiges Betriebssystem:&#039;&#039;&#039; prüfen, ob eine Verbindung nach einem Verbindungsabbruch wieder aufgebaut werden kann. Sobald der Verbindungsaufbau erfolgreich war, muss die Funktion einen erfolgreichen Wahrheitswert zurückliefern (z.B. &amp;quot;1&amp;quot;) und den eigenen Eintrag entsprechend aus &amp;lt;code&amp;gt;%readyfnlist&amp;lt;/code&amp;gt; löschen.&lt;br /&gt;
* &#039;&#039;&#039;Windows-Betriebssystem:&#039;&#039;&#039; prüfen, ob lesbare Daten für ein serielles Device (via COM1, COM2, ...) vorliegen. Sofern lesbare Daten vorliegen, muss Funktion einen erfolgreichen Wahrheitswert zurückliefern (z.B. &amp;quot;1&amp;quot;). Zusätzlich dazu muss die Funktion, wie bei UNIX-artigen Betriebssystem, ebenfalls bei einem Verbindungsabbruch einen neuen Verbindungsversuch initiieren. Der Eintrag in &amp;lt;code&amp;gt;%readyfnlist&amp;lt;/code&amp;gt; bleibt solange erhalten, bis die Verbindung seitens FHEM beendet wird.&lt;br /&gt;
&lt;br /&gt;
Der Windows-spezifische Teil zur Datenprüfung ist dabei nur zu implementieren, wenn das Modul über eine serielle Verbindung kommuniziert.&lt;br /&gt;
&lt;br /&gt;
Bei der Nutzung des Moduls DevIo wird dem Modulentwickler der Umgang mit &amp;lt;code&amp;gt;%readyfnlist&amp;lt;/code&amp;gt; abgenommen, da DevIo sich selbst um die entsprechenden Einträge kümmert und diese selbstständig wieder entfernt.&lt;br /&gt;
&lt;br /&gt;
In der Regel sieht eine Ready-Funktion immer gleich aus.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Ready($)&lt;br /&gt;
{&lt;br /&gt;
	my ($hash) = @_;&lt;br /&gt;
      &lt;br /&gt;
	# Versuch eines Verbindungsaufbaus, sofern die Verbindung beendet ist.&lt;br /&gt;
	return DevIo_OpenDev($hash, 1, undef ) if ( $hash-&amp;gt;{STATE} eq &amp;quot;disconnected&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
	# This is relevant for Windows/USB only&lt;br /&gt;
	if(defined($hash-&amp;gt;{USBDev})) {&lt;br /&gt;
		my $po = $hash-&amp;gt;{USBDev};&lt;br /&gt;
		my ( $BlockingFlags, $InBytes, $OutBytes, $ErrorFlags ) = $po-&amp;gt;status;&lt;br /&gt;
		return ( $InBytes &amp;gt; 0 );&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== X_Notify ====&lt;br /&gt;
&lt;br /&gt;
Die X_Notify-Funktion wird aus der Funktion [[DevelopmentModuleAPI#DoTrigger|DoTrigger()]] in fhem.pl heraus aufgerufen sobald ein Modul Events erzeugt hat. Damit kann ein Modul auf Events anderer Module reagieren. Typische Beispiele sind dabei das [[FileLog]]-Modul oder das [[notify]]-Modul.&lt;br /&gt;
&lt;br /&gt;
Die Notify-Funktion bekommt dafür zwei Hash-Referenzen übergeben: den Hash des eigenen Geräts und den Hash des Geräts, dass die Events erzeugt hat. &lt;br /&gt;
Über den Hash des eigenen Geräts kann die Notify-Funktion beispielsweise auf die Internals oder Attribute des eigenen Geräts zugreifen.&lt;br /&gt;
Über den Hash des Gerätes und der [[DevelopmentModuleAPI#deviceEvents|deviceEvents()]]-Funktion kann man auf die generierten Events zugreifen. Über den zweiten Parameter dieser Routine lässt sich bestimmen ob für das Reading &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt; ein &#039;normales&#039; Event (d.h. in der form &amp;lt;code&amp;gt;state: &amp;lt;wert&amp;gt;&amp;lt;/code&amp;gt;) erzeugen soll (Wert: 1) oder ob z.b. aus Gründen der Rückwärtskompatibilität ein Event ohne &amp;lt;code&amp;gt;state: &amp;lt;/code&amp;gt; erzeugt werden soll. Falls dem Anwender die Wahl des verwendeten Formats überlassen werden soll ist hierzu das [http://fhem.de/commandref_DE.html#addStateEvent addStateEvent-Attribut] vorzusehen.&lt;br /&gt;
&lt;br /&gt;
Der direkte Zugriff auf &amp;lt;code&amp;gt;$hash-&amp;gt;{CHANGED}&amp;lt;/code&amp;gt; ist nicht mehr zu empfehlen.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Notify($$)&lt;br /&gt;
{&lt;br /&gt;
  my ($own_hash, $dev_hash) = @_;&lt;br /&gt;
  my $ownName = $own_hash-&amp;gt;{NAME}; # own name / hash&lt;br /&gt;
&lt;br /&gt;
  return &amp;quot;&amp;quot; if(IsDisabled($ownName)); # Return without any further action if the module is disabled&lt;br /&gt;
&lt;br /&gt;
  my $devName = $dev_hash-&amp;gt;{NAME}; # Device that created the events&lt;br /&gt;
&lt;br /&gt;
  my $events = deviceEvents($dev_hash,1);&lt;br /&gt;
  return if( !$events );&lt;br /&gt;
&lt;br /&gt;
  foreach my $event (@{$events}) {&lt;br /&gt;
    $event = &amp;quot;&amp;quot; if(!defined($event));&lt;br /&gt;
&lt;br /&gt;
    # Examples:&lt;br /&gt;
    # $event = &amp;quot;readingname: value&amp;quot; &lt;br /&gt;
    # or&lt;br /&gt;
    # $event = &amp;quot;INITIALIZED&amp;quot; (for $devName equal &amp;quot;global&amp;quot;)&lt;br /&gt;
    #&lt;br /&gt;
    # processing $event with further code&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Begrenzung der Aufrufe auf bestimmte Geräte&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Da die Notify-Funktion für jedes definierte Gerät mit all seinen Events aufgerufen wird, muss sie in einer Schleife jedesmal prüfen und entscheiden, ob es mit dem jeweiligen Event etwas anfangen kann. Ein Gerät, dass die Notify-Funktion implementiert, sieht dafür typischerweise einen regulären Ausdruck vor, welcher für die Filterung verwendet wird.&lt;br /&gt;
&lt;br /&gt;
Wenn man nur gezielt von bestimmten Definitionen Events erhalten will, kann man diese auch in Form einer [http://fhem.de/commandref_DE.html#devspec devspec] in &amp;lt;code&amp;gt;$hash-&amp;gt;{NOTIFYDEV}&amp;lt;/code&amp;gt; angeben. Bspw. kann man in der Define-Funktion diesen Wert setzen. Dadurch wird die Notify-Funktion nur aufgerufen wenn eine der Definitionen, auf welche die devspec passt, ein Event erzeugt hat. Ein typischer Fall ist die Begrenzung von Events auf &amp;quot;global&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
in der Define-Funktion:&lt;br /&gt;
&lt;br /&gt;
$hash-&amp;gt;{NOTIFYDEV} = &amp;quot;global&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{NOTIFYDEV} = &amp;quot;global,Definition_A,Definition_B&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{NOTIFYDEV} = &amp;quot;global,TYPE=CUL_HM&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dies schont insbesondere bei grossen Installationen Ressourcen, da die Notify-Funktion nicht sämtliche Events, sondern nur noch Events der gewünschten Definitionen erhält. Dadurch erfolgen deutlich weniger Aufrufe der Notify-Funktion, was Systemressourcen schont.&lt;br /&gt;
&lt;br /&gt;
Sofern in der [[#X_Define|Define-Funktion]] eine Regexp als Argument übergeben wird, die ähnlich wie beim Modul [[notify]] auf Events wie &amp;lt;code&amp;gt;&amp;amp;lt;Definitionsname&amp;amp;gt;&amp;lt;/code&amp;gt; bzw. &amp;lt;code&amp;gt;&amp;amp;lt;Definitionsname&amp;amp;gt;:&amp;amp;lt;Event&amp;amp;gt;&amp;lt;/code&amp;gt; reagiert, so sollte man in der Define-Funktion die Funktion [[DevelopmentModuleAPI#notifyRegexpChanged|notifyRegexpChanged()]] verwenden. Diese versucht einen passenden Eintrag für &amp;lt;code&amp;gt;$hash-&amp;gt;{NOTIFYDEV}&amp;lt;/code&amp;gt; basierend auf der übergebenen Regexp zu setzen, sofern dies möglich ist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Reihenfolge für den Aufruf der Notify-Funktion beeinflussen&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sobald ein Event ausgelöst wurde, stellt sich FHEM eine Liste aller relevanten Geräte-Hashes zusammen, welche via Notify-Funktion prüfen müssen, ob das Event relevant ist. Dabei wird die Liste nach &amp;lt;code&amp;gt;$hash-&amp;gt;{NTFY_ORDER}&amp;lt;/code&amp;gt; sortiert. Diese enthält ein Order-Präfix in Form einer Ganzzahl, sowie den Namen der Definition (Bsp: &amp;lt;code&amp;gt;&#039;&#039;&#039;50&#039;&#039;&#039;-Lampe_Wohnzimmer&amp;lt;/code&amp;gt;). Dadurch kann man jedoch nicht sicherstellen, dass Events von bestimmten Modulen zuerst verarbeitet werden.&lt;br /&gt;
&lt;br /&gt;
Wenn das eigene Modul bei der Eventverarbeitung gegenüber den anderen Modulen eine bestimmte Reihenfolge einhalten muss, kann man in der [[#X_Initialize|Initialize]]-Funktion durch Setzen von &amp;lt;code&amp;gt;$hash-&amp;gt;{NotifyOrderPrefix}&amp;lt;/code&amp;gt; diese Reihenfolge beeinflussen. Standardmäßig werden Module immer mit einem Order-Präfix von &amp;quot;50-&amp;quot; in FHEM registriert. Durch die Veränderung dieses Präfixes kann man das eigene Modul in der Reihenfolge gegenüber anderen Modulen bei der Eventverarbeitung beeinflussen. &lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Initialize($)&lt;br /&gt;
{&lt;br /&gt;
	my ($hash) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
	&lt;br /&gt;
	$hash-&amp;gt;{NotifyOrderPrefix} = &amp;quot;45-&amp;quot;  # Alle Definitionen des Moduls X werden bei der Eventverarbeitung zuerst geprüft&lt;br /&gt;
	&lt;br /&gt;
	# oder...&lt;br /&gt;
	&lt;br /&gt;
	$hash-&amp;gt;{NotifyOrderPrefix} = &amp;quot;55-&amp;quot;  # Alle Definitionen des Moduls X werden bei der Eventverarbeitung als letztes geprüft&lt;br /&gt;
	&lt;br /&gt;
&amp;lt;/source&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
Da dieses Präfix bei eventverarbeitenden Definitionen in &amp;lt;code&amp;gt;$hash-&amp;gt;{NTFY_ORDER}&amp;lt;/code&amp;gt; dem Definitionsnamen vorangestellt wird bewirkt es bei einer normalen aufsteigenden Sortierung nach &amp;lt;code&amp;gt;$hash-&amp;gt;{NTFY_ORDER}&amp;lt;/code&amp;gt; eine veränderte Reihenfolge. Alle Module die in der Initialize-Funktion nicht &amp;lt;code&amp;gt;$hash-&amp;gt;{NotifyOrderPrefix}&amp;lt;/code&amp;gt; explizit setzen, werden mit &amp;quot;50-&amp;quot; als Standardwert vorbelegt.&lt;br /&gt;
&lt;br /&gt;
==== X_Rename ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Rename ($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $new_name, $old_name) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Rename-Funktion wird ausgeführt, nachdem ein Gerät umbenannt wurde. Auf diese Weise kann ein Modul auf eine Namensänderung reagieren, wenn das Gerät &amp;lt;code&amp;gt;$old_name&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;$new_name&amp;lt;/code&amp;gt; umbenannt wurde. Ein typischer Fall ist das Umsetzen der Namensänderungen bei Daten die mittels [[DevelopmentModuleAPI#setKeyValue|setKeyValue()]] gespeichert wurden. Hierbei müssen die Daten, welche unter dem alten Namen gespeichert sind, auf den neuen Namen geändert werden.&lt;br /&gt;
&lt;br /&gt;
Der Rename-Funktion wird lediglich der alte, sowie der neue Gerätename übergeben. Der Rückgabewert wird nicht ausgewertet.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Rename ($)&lt;br /&gt;
{&lt;br /&gt;
	my ( $new_name, $old_name ) = @_;&lt;br /&gt;
&lt;br /&gt;
	my $old_index = &amp;quot;Module_X_&amp;quot;.$old_name.&amp;quot;_data&amp;quot;;&lt;br /&gt;
	my $new_index = &amp;quot;Module_X_&amp;quot;.$new_name.&amp;quot;_data&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
	my ($err, $data) = getKeyValue($old_index);&lt;br /&gt;
	return undef unless(defined($old_pwd));&lt;br /&gt;
&lt;br /&gt;
	setKeyValue($new_index, $data);&lt;br /&gt;
	setKeyValue($old_index, undef);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== X_Shutdown ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Shutdown ($)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Mit der X_Shutdown Funktion kann ein Modul Aktionen durchführen bevor FHEM gestoppt wird. Dies kann z.B. der ordnungsgemäße Verbindungsabbau mit dem physikalischen Gerät sein (z.B. Session beenden, Logout, etc.). Als Übergabeparameter wird der Geräte-Hash bereitgestellt. Der Rückgabewert einer Shutdown-Funktion wird nicht ausgewertet und ist daher irrelevant.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Shutdown($)&lt;br /&gt;
{&lt;br /&gt;
	my ($hash) = @_;&lt;br /&gt;
&lt;br /&gt;
	# Verbindung schließen&lt;br /&gt;
	DevIo_CloseDev($hash);&lt;br /&gt;
        return undef;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Funktionen für zweistufiges Modulkonzept ===&lt;br /&gt;
&lt;br /&gt;
Für das [[#Zweistufiges_Modell_für_Module|zweistufige Modulkonzept]] gibt es weiterhin:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;text-align:left&amp;quot; | Funktionsname !! style=&amp;quot;text-align:left&amp;quot; class=&amp;quot;unsortable&amp;quot; | Kurzbeschreibung&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Parse|X_Parse]] || Zustellen von Daten via [[DevelopmentModuleAPI#Dispatch|Dispatch()]] vom physischen Modul zum logischen Modul zwecks der Verarbeitung.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Write|X_Write]]|| Zustellen von Daten via [[DevelopmentModuleAPI#Dispatch|IOWrite()]] vom logischen zum physischen Modul um diese an die Hardware weiterzureichen.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Fingerprint|X_Fingerprint]] || Rückgabe eines &amp;quot;Fingerabdrucks&amp;quot; einer Nachricht. Dient der Erkennung von Duplikaten im Rahmen von [[DevelopmentModuleAPI#Dispatch|Dispatch()]]. Kann im physischen, als auch logischen Modul benutzt werden.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Für das zweistufige Modulkonzept muss in einem logischen Modul eine [[#X_Parse|Parse]]-Funktion im Modul-Hash registriert werden. In einem physikalischen Modul muss eine [[#X_Write|Write]]-Funktion definiert sein. Diese dienem dem Datenaustausch in beide Richtungen und werden von dem jeweils anderen Modul indirekt aufgerufen.&lt;br /&gt;
&lt;br /&gt;
In der [[#X_Initialize|Initialize]]-Funktion werden diese wie folgt definiert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
$hash-&amp;gt;{ParseFn}       = &amp;quot;X_Parse&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{WriteFn}       = &amp;quot;X_Write&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{FingerprintFn} = &amp;quot;X_Fingerprint&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Funktionen werden in diesem Abschnitt genauer beschrieben.&lt;br /&gt;
&lt;br /&gt;
==== X_Parse ====&lt;br /&gt;
{{Randnotiz|RNTyp=Info|RNText=&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&amp;lt;u&amp;gt;&#039;&#039;&#039;ACHTUNG&#039;&#039;&#039;:&amp;lt;/u&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
Dieser Abschnitt geht davon aus, dass das Modul mit dem Namen &amp;quot;X&amp;quot; ein &#039;&#039;&#039;logisches Modul&#039;&#039;&#039; im Sinne des zweistufigen Modulkonzepts ist, also Daten mit einem übergeordneten, physikalischen Modul austauscht.}}&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Parse ($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $io_hash, $message) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
	&lt;br /&gt;
	return $found;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Funktion X_Parse wird aufgerufen, sobald von dem IO-Gerät &amp;lt;code&amp;gt;$io_hash&amp;lt;/code&amp;gt; eine Nachricht &amp;lt;code&amp;gt;$message&amp;lt;/code&amp;gt; via [[DevelopmentModuleAPI#Dispatch|Dispatch()]] zur Verarbeitung angefragt wird. Die Parse-Funktion muss dann prüfen, zu welcher Gerätedefinition diese Nachricht gehört und diese entsprechend verarbeiten.&lt;br /&gt;
&lt;br /&gt;
Üblicherweise enthält eine Nachricht immer eine Komponente durch welche sich die Nachricht einem Gerät zuordnen lässt (z.B. Adresse, ID-Nummer, ...). Eine solche Identifikation sollte man im Rahmen der [[#X_Define|Define]]-Funktion im logischen Modul an geeigneter Stelle speichern, um in der Parse-Funktion eine einfache Zuordnung von Adresse/ID einer Nachricht zur entsprechenden Gerätedefinition zu haben. Dazu wird in der Regel im Modul-Hash im modulspezifischen Berreich eine Liste &amp;lt;code&amp;gt;defptr&amp;lt;/code&amp;gt; (Definition Pointer) geführt, welche jede eindeutige Adresse/ID dem entsprechenden Geräte-Hash zuordnet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sub X_Define ($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $def) = @_;&lt;br /&gt;
	my @a = split(&amp;quot;[ \t][ \t]*&amp;quot;, $def);&lt;br /&gt;
	my $name = $a[0];&lt;br /&gt;
&lt;br /&gt;
	...&lt;br /&gt;
	&lt;br /&gt;
	# erstes Argument ist die eindeutige Geräteadresse&lt;br /&gt;
	my $address = $a[1];&lt;br /&gt;
&lt;br /&gt;
	# Adresse rückwärts dem Hash zuordnen (für ParseFn)&lt;br /&gt;
	$modules{X}{defptr}{$address} = $hash;&lt;br /&gt;
&lt;br /&gt;
	...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Auf Basis dieses Definition Pointers kann die Parse-Funktion nun sehr einfach prüfen, ob für die empfangene Nachricht bereits eine entsprechende Gerätedefinition existiert. Sofern diese existiert, kann die Nachricht entsprechend verarbeitet werden. Sollte jedoch keine passende Gerätedefinition zu der empfangenen Nachricht existieren, so muss die Parse-Funktion den Gerätenamen &amp;quot;UNDEFINED&amp;quot; zusammen mit den Argumenten für einen &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt;-Befehl zurückgeben, welcher ein passendes Gerät in FHEM anlegen würde (durch [[autocreate]]).&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sub X_Parse ($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $io_hash, $message) = @_;&lt;br /&gt;
	&lt;br /&gt;
	# Die Stellen 10-15 enthalten die eindeutige Identifikation des Geräts&lt;br /&gt;
	my $address = substr($message, 10, 5); &lt;br /&gt;
&lt;br /&gt;
	# wenn bereits eine Gerätedefinition existiert (via Definition Pointer aus Define-Funktion)&lt;br /&gt;
	if(my $hash = $modules{X}{defptr}{$address}) &lt;br /&gt;
	{&lt;br /&gt;
		...  # Nachricht für $hash verarbeiten&lt;br /&gt;
		&lt;br /&gt;
		# Rückgabe des Gerätenamens, für welches die Nachricht bestimmt ist.&lt;br /&gt;
		return $hash-&amp;gt;{NAME}; &lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		# Keine Gerätedefinition verfügbar&lt;br /&gt;
		# Daher Vorschlag define-Befehl: &amp;lt;NAME&amp;gt; &amp;lt;MODULNAME&amp;gt; &amp;lt;ADDRESSE&amp;gt;&lt;br /&gt;
		return &amp;quot;UNDEFINED X_&amp;quot;.$address.&amp;quot; X $address&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== X_Write ====&lt;br /&gt;
{{Randnotiz|RNTyp=Info|RNText=&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&amp;lt;u&amp;gt;&#039;&#039;&#039;ACHTUNG&#039;&#039;&#039;:&amp;lt;/u&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
Dieser Abschnitt geht davon aus, dass das Modul mit dem Namen &amp;quot;X&amp;quot; ein &#039;&#039;&#039;physisches Modul&#039;&#039;&#039; im Sinne des zweistufigen Modulkonzepts ist, also Daten mit untergeordneten logischen Modulen austauscht. }}&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Write ($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, @arguments) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
	&lt;br /&gt;
	return $return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Write-Funktion wird durch die Funktion [[DevelopmentModuleAPI#IOWrite|IOWrite()]] aufgerufen, sobald eine logische Gerätedefinition Daten per IO-Gerät an die Hardware übertragen möchte. Dazu kümmert sich die Write-Funktion um die Übertragung der Nachricht in geeigneter Form an die verbundene Hardware. Als Argumente wird der Hash des physischen Gerätes übertragen, sowie alle weiteren Argumente, die das logische Modul beim Aufruf von IOWrite() mitgegeben hat. Im Normalfall ist das ein Skalar mit der zu sendenden Nachricht in Textform. Es kann aber auch sein, dass weitere Daten zum Versand notwendig sind (evtl. Schlüssel, Session-Key, ...). Daher ist die Parametersyntax einer zu schreibenden Nachricht via IOWrite-/Write-Funktion zwischen logischem und physikalischen Modul abzustimmen.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Write ($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $message, $address) = @_;&lt;br /&gt;
	&lt;br /&gt;
	DevIo_SimpleWrite($hash, $address.$message, 2);&lt;br /&gt;
&lt;br /&gt;
	return undef;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== X_Fingerprint ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Fingerprint($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $io_name, $msg ) = @_;&lt;br /&gt;
 &lt;br /&gt;
	...&lt;br /&gt;
 &lt;br /&gt;
	return ( $io_name, $fingerprint );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Fingerprint-Funktion dient der Erkennung von Duplikaten empfangener Nachrichten. Diese Funktion kann dabei sowohl im physischen, als auch im logischen Modul implementiert sein. Je nachdem auf welcher Ebene man für eine Nachricht einen Fingerprint bilden kann. &lt;br /&gt;
&lt;br /&gt;
Als Parameter wird der Name des IO-Geräts &amp;lt;code&amp;gt;$io_name&amp;lt;/code&amp;gt; übergeben, sowie die Nachricht &amp;lt;code&amp;gt;$msg&amp;lt;/code&amp;gt;, welche empfangen wurde. Nun muss aus dieser Nachricht ein eindeutiger Fingerprint gebildet werden. Dies bedeutet, dass alle variablen Inhalte, die aufgrund des Empfangs dieser Nachricht über unterschiedliche IO-Geräte enthalten sein können, entfernt werden müssen. Dies können bspw. Empfangsadressen von IO-Geräten sein oder Session-ID&#039;s die in der Nachricht enthalten sind. Alle Fingerprints sämtlicher Nachrichten, die innerhalb der letzten 500 Millisekunden (konfigurierbar via &amp;lt;code&amp;gt;global&amp;lt;/code&amp;gt; Attribut &amp;lt;code&amp;gt;dupTimeout&amp;lt;/code&amp;gt;) empfangen wurden, werden gegen diesen generierten Fingerprint getestet. Sollte innerhalb dieser Zeit bereits eine Nachricht mit diesem Fingerprint verarbeitet worden sein, so wird sie als Duplikat erkannt und nicht weiter verarbeitet. In diesem Fall gibt [[DevelopmentModuleAPI#Dispatch|Dispatch()]] den Namen der Gerätedefinition zurück, welche eine Nachricht mit dem selben Fingerprint bereits verarbeitet hat. Es erfolgt dann kein Aufruf der [[#X_Parse|Parse]]-Funktion.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Fingerprint($$)&lt;br /&gt;
{&lt;br /&gt;
  my ( $io_name, $msg ) = @_;&lt;br /&gt;
&lt;br /&gt;
  substr( $msg, 2, 2, &amp;quot;--&amp;quot; ); # entferne Empfangsadresse&lt;br /&gt;
  substr( $msg, 4, 1, &amp;quot;-&amp;quot; );  # entferne Hop-Count&lt;br /&gt;
&lt;br /&gt;
  return ( $io_name, $msg );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es wird zuerst, sofern implementiert, die Fingerprint-Funktion des physischen Moduls aufgerufen. Sollte sich hierdurch kein Duplikat erkennen lassen, wird die Fingerprint-Funktion jedes möglichen geladenen logischen Moduls aufgerufen, sofern implementiert. &lt;br /&gt;
&lt;br /&gt;
Sollte sowohl im physischen, als auch im logischen Modul keine Fingerprint-Funktion implementiert sein, so wird keinerlei Duplikatserkennung durchgeführt.&lt;br /&gt;
&lt;br /&gt;
=== FHEMWEB-spezifische Funktionen ===&lt;br /&gt;
&lt;br /&gt;
FHEMWEB bietet Modulautoren die Möglichkeit an durch spezielle Funktionsaufrufe in Modulen, eigene HTML-Inhalte zu verwenden. Dadurch können in Verbindung mit zusätzlichem JavaScript komplexe Dialoge/Inhalte/Steuermöglichkeiten dargestellt werden. &lt;br /&gt;
&lt;br /&gt;
Eine genaue Auflistung aller FHEMWEB-spezifischen Funktionsaufrufe gibt es in dem separaten Artikel [[DevelopmentFHEMWEB]]&lt;br /&gt;
&lt;br /&gt;
=== sonstige Funktionen ===&lt;br /&gt;
&lt;br /&gt;
In diesem Abschnitt werden weitere Funktionen behandelt die zum Teil aus FHEM, aber auch aus anderen Modulen aufgerufen werden. Sie sind dabei nur in speziellen Anwendungsfällen relevant. Hier eine Auflistung aller sonstigen Modulfunktionen:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Funktionsname !! class=&amp;quot;unsortable&amp;quot; | Kurzbeschreibung&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_DbLog_split|X_DbLog_split]] || Wird durch das Modul 93_DbLog.pm aufgerufen. Dient dem korrekten Split eines moduleigenen Events in Name/Wert/Einheit für die Nutzung einer Datenbank.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Except|X_Except]]|| Wird aufgerufen, sobald ein ein geöffneter Filedescriptor in [[#Wichtige_globale_Variablen_aus_fhem.pl|&amp;lt;code&amp;gt;%selectlist&amp;lt;/code&amp;gt;]], der unter &amp;lt;code&amp;gt;$hash-&amp;gt;{EXCEPT_FD}&amp;lt;/code&amp;gt; im Geräte-Hash gesetzt ist, einen Interrupt bzw. Exception auslöst.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Copy|X_Copy]]|| Wird durch das Modul 98_copy.pm aufgerufen im Rahmen des &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt;-Befehls sobald ein Gerät kopiert wurde.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_State|X_State]]|| Wird aufgerufen im Rahmen des &amp;lt;code&amp;gt;setstate&amp;lt;/code&amp;gt;-Befehls bevor der Status einer Gerätedefinition bzw. eines zugehörigen Readings gesetzt wird.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_AsyncOutput|X_AsyncOutput]]|| Nur Relevant für Module die via [[TcpServerUtils]] eine Client-Verbindung zu FHEM ermöglichen (z.B. FHEMWEB und telnet). Ermöglicht die asynchrone Ausgabe von Daten via [[DevelopmentModuleAPI#asyncOutput|asyncOutput()]] an einen einzelnen verbundenen Client.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_ActivateInform|X_ActivateInform]]|| Nur Relevant für Module die via [[TcpServerUtils]] eine Client-Verbindung zu FHEM ermöglichen (z.B. FHEMWEB und telnet). Ermöglicht das aktivieren des inform-Mechanismus zum senden von Events für einen einzelnen verbundenen Client.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Authorize|X_Authorize]]|| Wird aufgerufen im Rahmen von [[DevelopmentModuleAPI#Authorize|Authorize()]] um eine gewünschte Vorgangs-Art zu autorisieren.&lt;br /&gt;
|-&lt;br /&gt;
| [[#X_Authenticate|X_Authenticate]]||  Wird aufgerufen im Rahmen von [[DevelopmentModuleAPI#Authenticate|Authenticate()]] um eine Authentifizierung zu prüfen und ggf. zu genehmigen.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In der [[#X_Initialize|Initialize]]-Funktion werden diese wie folgt definiert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
$hash-&amp;gt;{DbLog_splitFn} = &amp;quot;X_DbLog_split&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{ExceptFn} = &amp;quot;X_Except&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{CopyFn} = &amp;quot;X_Copy&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{AsyncOutputFn} = &amp;quot;X_AsyncOutput&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{ActivateInformFn} = &amp;quot;X_ActivateInform&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{StateFn} = &amp;quot;X_State&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{AuthorizeFn} = &amp;quot;X_Authorize&amp;quot;;&lt;br /&gt;
$hash-&amp;gt;{AuthenticateFn} = &amp;quot;X_Authenticate&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Diese Funktionen werden in diesem Abschnitt genauer beschrieben.&lt;br /&gt;
==== X_DbLog_split ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_DbLog_split ($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $event, $device_name ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
    &lt;br /&gt;
	return  ( $reading, $value, $unit );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die DbLog_split-Funktion wird durch das Modul [[DbLog]] aufgerufen, sofern der Nutzer DbLog benutzt. Sofern diese Funktion implementiert ist, kann der Modulautor das Auftrennen von Events in den Reading-Namen, -Wert und der Einheit selbst steuern. Andernfalls nimmt DbLog diese Auftrennung selber mittels Trennung durch Leerzeichen sowie vordefinierten Regeln zu verschiedenen Modulen vor. Je nachdem, welche Readings man in seinem Modul implementiert, passt diese standardmäßige Trennung jedoch nicht immer.&lt;br /&gt;
&lt;br /&gt;
Der Funktion werden folgende Eingangsparameter übergeben:&lt;br /&gt;
# Das generierte Event (Bsp: &amp;lt;code&amp;gt;temperature: 20.5 °C&amp;lt;/code&amp;gt;)&lt;br /&gt;
# Der Name des Geräts, welche das Event erzeugt hat (Bsp: &amp;lt;code&amp;gt;Temperatursensor_Wohnzimmer&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Es ist nicht möglich in der DbLog_split-Funktion auf die verarbeitende DbLog-Definition zu referenzieren.&lt;br /&gt;
&lt;br /&gt;
Als Rückgabewerte muss die Funktion folgende Werte bereitstellen:&lt;br /&gt;
# Name des Readings (Bsp: &amp;lt;code&amp;gt;temperature&amp;lt;/code&amp;gt;)&lt;br /&gt;
# Wert des Readings (Bsp: &amp;lt;code&amp;gt;20.5&amp;lt;/code&amp;gt;)&lt;br /&gt;
# Einheit des Readings (Bsp: &amp;lt;code&amp;gt;°C&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_DbLog_splitFn($$)&lt;br /&gt;
{&lt;br /&gt;
	my ($event, $device) = @_;&lt;br /&gt;
	my ($reading, $value, $unit);&lt;br /&gt;
        my $devhash = $defs{$device}&lt;br /&gt;
&lt;br /&gt;
	if($event =~ m/temperature/) {&lt;br /&gt;
	   $reading = &#039;temperature&#039;;&lt;br /&gt;
	   $value = substr($event,12,4);&lt;br /&gt;
	   $unit = &#039;°C&#039;;&lt;br /&gt;
	}   &lt;br /&gt;
        &lt;br /&gt;
        return ($reading, $value, $unit);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== X_Except ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Except ($)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die X_Except-Funktion wird durch fhem.pl aufgerufen, wenn die Gerätedefinition &amp;lt;code&amp;gt;$hash&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;[[#Wichtige_globale_Variablen_aus_fhem.pl|%selectlist]]&amp;lt;/code&amp;gt; aufgeführt ist und der Filedeskriptor in &amp;lt;code&amp;gt;$hash-&amp;gt;{EXCEPT_FD}&amp;lt;/code&amp;gt; eine Exception bzw. Interrupt auslöst. &lt;br /&gt;
&lt;br /&gt;
Der Rückgabewert wird nicht ausgewertet und ist daher irrelevant.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
use IO::File;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
sub X_Except ($)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	# Filehandle aus Filedescriptor erstellen&lt;br /&gt;
	my $filehandle = IO::File-&amp;gt;new_from_fd($hash-&amp;gt;{EXCEPT_FD}, &#039;r&#039;);&lt;br /&gt;
	seek($filehandle,0,0);	&lt;br /&gt;
&lt;br /&gt;
	# aktuellen Inhalt auslesen&lt;br /&gt;
	my $current_value = $filehandle-&amp;gt;getline;&lt;br /&gt;
&lt;br /&gt;
	if($current_value eq &amp;quot;1&amp;quot;)&lt;br /&gt;
	{&lt;br /&gt;
		...&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		...&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== X_Copy ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Copy ($)&lt;br /&gt;
{&lt;br /&gt;
	my ( $old_name, $new_name ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die X_Copy-Funktion wird durch das Modul [[copy]] aufgerufen nachdem ein Nutzer eine Gerätedefinition über den Befehl &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt; kopiert hat. Dazu werden als Funktionsparameter die Definitionsnamen der alten und neuen Gerätedefinition übergeben. Es dient dazu zusätzliche Daten aus der zu kopierenden Gerätedefinition in die neue Definition zu übernehmen. Der Befehl &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt; überträgt lediglich &amp;lt;code&amp;gt;$hash-&amp;gt;{DEF}&amp;lt;/code&amp;gt; in die neue Definition sowie sämtliche gesetzte Attribute. Weitere Daten müssen dann durch die X_Copy-Funktion übertragen werden. &lt;br /&gt;
&lt;br /&gt;
Die X_Copy-Funktion wird erst nach dem erfolgtem Kopiervorgang aufgerufen.&lt;br /&gt;
&lt;br /&gt;
Der Rückgabewert wird nicht ausgewertet und ist daher irrelevant.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
sub X_Copy ($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $old_name, $new_name ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	my $old_hash = $defs{$old_name};&lt;br /&gt;
	my $new_hash = $defs{$new_name};&lt;br /&gt;
&lt;br /&gt;
	# copy also temporary session key&lt;br /&gt;
	$new_hash-&amp;gt;{helper}{SESSION_KEY} = $old_hash-&amp;gt;{helper}{SESSION_KEY};&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== X_AsyncOutput ====&lt;br /&gt;
TBD&lt;br /&gt;
&lt;br /&gt;
==== X_ActivateInform ====&lt;br /&gt;
TBD&lt;br /&gt;
==== X_State ====&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_State($)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $time, $readingName, $value ) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
&lt;br /&gt;
	return $error;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die X_State-Funktion wird durch fhem.pl aufgerufen, sobald über den Befehl &amp;lt;code&amp;gt;setstate&amp;lt;/code&amp;gt; versucht wird ein Wert für ein Reading oder den Status (&amp;lt;code&amp;gt;$hash-&amp;gt;{STATE}&amp;lt;/code&amp;gt;) einer Gerätedefinition zu setzen. Dieser Befehl wird primär beim Starten von FHEM aufgerufen sobald das State-File eingelesen wird. Je nachdem, ob im gegebenen Fall ein Reading oder der Definitionsstatus gesetzt wird, haben die Übergabeparameter verschiedene Werte:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Funktionsparameter!! Wert beim Setzen eines Readings !! Wert beim Setzen eines Definitionsstatus&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$hash&amp;lt;/code&amp;gt; || colspan=2 align=center | Die Hashreferenz der betreffenden Gerätedefinition&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$time&amp;lt;/code&amp;gt;|| Der Zeitstempel auf welchen das Reading &amp;lt;code&amp;gt;$readingName&amp;lt;/code&amp;gt; gesetzt werden soll. Das Ergebnis entspricht dem Rückgabewert der Funktion || Der aktuelle Zeitstempel zum jetzigen diesem Zeitpunkt.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$readingName&amp;lt;/code&amp;gt;|| Der Name des Readings, welches auf einen neuen Wert gesetzt werden soll. || Statischer Wert &amp;quot;STATE&amp;quot; um anzuzeigen, dass es sich um den Definitionsstatus handelt, welcher gesetzt werden soll (&amp;lt;code&amp;gt;$hash-&amp;gt;{STATE}&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$value&amp;lt;/code&amp;gt; || Der Wert, welchen das Reading &amp;lt;code&amp;gt;$readingName&amp;lt;/code&amp;gt; annehmen soll. || Der Wert, welchen die Gerätedefinition als Status annehmen soll.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Wenn via &amp;lt;code&amp;gt;setstate&amp;lt;/code&amp;gt; ein Reading gesetzt wird, kann die X_State-Funktion das Setzen dieses Readings durch die Rückgabe einer aussagekräftigen Fehlermeldung unterbinden. Sofern &amp;lt;code&amp;gt;undef&amp;lt;/code&amp;gt; zurückgegeben wird, wird das entsprechende Reading auf den übergebenen Status gesetzt.&lt;br /&gt;
&lt;br /&gt;
Wenn via &amp;lt;code&amp;gt;setstate&amp;lt;/code&amp;gt; der Definitionsstatus gesetzt wird, wird die X_State-Funktion erst nach dem Setzen des Status aufgerufen. Man kann dabei zwar eine Fehlermeldung zurückgeben. Der Status wird aber dennoch übernommen. Die Fehlermeldung wird lediglich dem Nutzer angezeigt.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_State($)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $time, $readingName, $value ) = @_;&lt;br /&gt;
&lt;br /&gt;
	return undef if($readingName &amp;quot;STATE&amp;quot; || $value ne &amp;quot;inactive&amp;quot;);&lt;br /&gt;
	readingsSingleUpdate($hash, &amp;quot;state&amp;quot;, &amp;quot;inactive&amp;quot;, 1);&lt;br /&gt;
	return undef;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== X_Authorize ====&lt;br /&gt;
TBD&lt;br /&gt;
&lt;br /&gt;
==== X_Authenticate ====&lt;br /&gt;
TBD&lt;br /&gt;
&lt;br /&gt;
== Bereitstellen eines eigenen Befehls (Befehlsmodul) ==&lt;br /&gt;
&lt;br /&gt;
Ein Modul kann primär einen neuen FHEM-Befehl bereitstellen. Man spricht in so einem Fall nicht von einem Gerätemodul, sondern einem Befehlsmodul. Ein solches Befehlsmodul stellt nur einen einzelnen Befehl bereit, der dem Modulnamen entsprechen muss. Nur, wenn der Modulname dem Befehlsname entspricht, kann FHEM das Modul beim ersten Ausführen dieses unbekannten Befehls finden und nachladen.&lt;br /&gt;
&lt;br /&gt;
Der entsprechende Befehl wird dazu in der [[#X_Initialize|Initialize]]-Funktion im globalen Hash &amp;lt;code&amp;gt;[[DevelopmentModuleIntro#Wichtige_globale_Variablen_aus_fhem.pl|%cmds]]&amp;lt;/code&amp;gt; registriert:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Initialize($$) {&lt;br /&gt;
&lt;br /&gt;
	$cmds{X} = { Fn           =&amp;gt; &amp;quot;CommandX&amp;quot;,&lt;br /&gt;
	             Hlp          =&amp;gt; &amp;quot;&amp;lt;argument1&amp;gt; [optional_argument2], print something very useful&amp;quot;,&lt;br /&gt;
 &lt;br /&gt;
                     # optional&lt;br /&gt;
		     ClientFilter =&amp;gt; &amp;quot;FHEMWEB&amp;quot;&lt;br /&gt;
	           };&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Damit wird der neue Befehl &amp;lt;code&amp;gt;X&amp;lt;/code&amp;gt; in FHEM registriert. Die Funktion mit dem Namen &amp;lt;code&amp;gt;CommandX&amp;lt;/code&amp;gt; setzt diesen Befehl innerhalb des Moduls um. Desweiteren wird eine kurze Aufrufsyntax mitgegeben, welche beim Aufruf des &amp;lt;code&amp;gt;help&amp;lt;/code&amp;gt;-Befehls dem Nutzer angezeigt wird um als Gedankenstütze zu dienen. Optional kann man mittels &amp;lt;code&amp;gt;ClientFilter&amp;lt;/code&amp;gt; die Ausführbarkeit nur auf bestimmte Client-Module (wie FHEMWEB oder telnet) beschränken. &lt;br /&gt;
&lt;br /&gt;
Nun muss noch die Funktion &amp;lt;code&amp;gt;CommandX&amp;lt;/code&amp;gt; im Rahmen des Moduls implementiert werden, welche den Befehl &amp;lt;code&amp;gt;X&amp;lt;/code&amp;gt; umsetzt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
sub CommandX($$)&lt;br /&gt;
{&lt;br /&gt;
 	my ($client_hash, $arguments) = @_;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
	&lt;br /&gt;
	return $output;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dabei werden der Befehlsfunktion zwei Parameter übergeben. Zuerst die Hash-Referenz des aufrufenden Clients (sofern manuell ausgeführt, ansonsten &amp;lt;code&amp;gt;undef&amp;lt;/code&amp;gt;) zwecks Rechteprüfung via [[allowed|allowed-Definitionen]]. Anschließend folgen die Aufrufparameter als zusammenhängende Zeichenkette. Die Trennung der einzelnen Argumente obligt der Funktion (bspw. via [[DevelopmentModuleAPI#parseParams|parseParams()]]). Als Funktionsrückgabewert wird eine Ausgabemeldung erwartet, die dem Nutzer angezeigt werden soll.&lt;br /&gt;
&lt;br /&gt;
== Pollen von Geräten ==&lt;br /&gt;
Wenn Geräte von sich aus keine Informationen senden sondern abgefragt werden müssen, kann man im Modul die Funktion [[DevelopmentModuleAPI#InternalTimer|InternalTimer()]] verwenden um einen Funktionsaufruf zu einem späteren Zeitpunkt durchführen zu können. Man übergibt dabei den Zeitpunkt für den nächsten Aufruf, den Namen der Funktion, die aufgerufen werden soll, sowie den zu übergebenden Parameter. Als zu übergebender Parameter wird üblicherweise der Hash der betroffenen Geräteinstanz verwendet. Damit hat die aufgerufene Funktion Zugriff auf alle wichtigen Daten der Geräteinstanz. Eventuell zusätzlich benötigte Werte können einfach als weitere Internals über den Hash zugänglich gemacht werden.&lt;br /&gt;
&lt;br /&gt;
Beispielsweise könnte man für das Abfragen eines Geräts in der [[#X_Define|Define]]-Funktion den Timer folgendermaßen setzen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
InternalTimer(gettimeofday()+2, &amp;quot;X_GetUpdate&amp;quot;, $hash);	&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternativ kann man auch in der [[#X_Notify|Notify]]-Funktion auf das Event &amp;lt;code&amp;gt;global:INITIALIZED&amp;lt;/code&amp;gt; bzw. &amp;lt;code&amp;gt;global:REREADCFG&amp;lt;/code&amp;gt; reagieren und erst dort, den Timer anstoßen, sobald die Konfiguration komplett eingelesen wurde. Dies ist insbesondere notwendig, wenn man sicherstellen will, dass alle Attribute aus der Konfiguration gesetzt sind, sobald man einen Status-Update initiiert.&lt;br /&gt;
&lt;br /&gt;
In der Funktion &amp;lt;code&amp;gt;X_GetUpdate&amp;lt;/code&amp;gt; selbst wird dann der Timer neu gesetzt, so dass nach einem Intervall die Funktion erneut aufgerufen wird:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_GetUpdate($)&lt;br /&gt;
{&lt;br /&gt;
	my ($hash) = @_;&lt;br /&gt;
	my $name = $hash-&amp;gt;{NAME};&lt;br /&gt;
	Log3 $name, 4, &amp;quot;X: GetUpdate called ...&amp;quot;;&lt;br /&gt;
	&lt;br /&gt;
	...&lt;br /&gt;
	&lt;br /&gt;
	# neuen Timer starten in einem konfigurierten Interval.&lt;br /&gt;
	InternalTimer(gettimeofday()+$hash-&amp;gt;{Interval}, &amp;quot;X_GetUpdate&amp;quot;, $hash);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Innerhalb der Funktion kann man nun das Gerät abfragen und die abgefragten Werte in Readings speichern. Falls das Abfragen der Werte jedoch zu einer Verzögerung und damit zu einer Blockade von FHEM führen kann, ist es möglich, in der GetUpdate-Funktion nur die Aufforderung zum Senden bestimmter Daten an das angeschlossene Gerät zu senden und dann das Lesen über die oben beschriebene [[#X_Read|Read]]-Funktion zu implementieren.&lt;br /&gt;
&lt;br /&gt;
Eine genaue Beschreibung der Timer-Funktion gibt es [[DevelopmentModuleAPI#Timer|hier im Wiki]]&lt;br /&gt;
&lt;br /&gt;
== Logging / Debugging ==&lt;br /&gt;
Um Innerhalb eines Moduls eine Log-Meldung in die FHEM-Logdatei zu schreiben, wird die Funktion [[DevelopmentModuleAPI#Log3|Log3()]] aufgerufen.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
Log3 $name, 3, &amp;quot;X ($name) - Problem erkannt ...&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Eine genaue Beschreibung zu der Funktion inkl. Aufrufparameter findet man [[DevelopmentModuleAPI#Log3|hier]]. Es ist generell ratsam in der Logmeldung sowohl den Namen des eigenen Moduls zu schreiben, sowie den Namen des Geräts, welche diese Logmeldung produziert, da die Meldung, so wie sie ist, direkt in das Logfile wandert und es für User ohne diese Informationen schwierig ist, die Meldungen korrekt zuzuordnen.&lt;br /&gt;
&lt;br /&gt;
Die Funktion Log3() verwendet den Namen der Geräteinstanz um das &amp;lt;code&amp;gt;verbose&amp;lt;/code&amp;gt;-Attribut zu prüfen. In der Regel wird bei Modulfunktionen jedoch immer nur der Gerätehash &amp;lt;code&amp;gt;$hash&amp;lt;/code&amp;gt; übergeben. Um den Namen der Definition zu ermitteln ist es daher notwendig sich diesen aus dem Hash extrahieren:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
my $name = $hash-&amp;gt;{NAME};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Um für ein neues Modul das Verbose-Level zu erhöhen, ohne gleich für das Gesamte FHEM alle Meldungen zu erzeugen kann man den Befehl &lt;br /&gt;
&amp;lt;code&amp;gt;attr gerätename verbose&amp;lt;/code&amp;gt; verwenden. Beispielsweise &amp;lt;code&amp;gt;attr PM verbose 5&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Logmeldungen sollten je nach Art und Wichtigkeit für den Nutzer in unterschiedlichen Loglevels erzeugt werden. Es gibt insgesamt 5 Stufen in denen geloggt werden kann. Standardmäßig steht der systemweite Loglevel (&amp;lt;code&amp;gt;global&amp;lt;/code&amp;gt;-Attribut &amp;lt;code&amp;gt;verbose&amp;lt;/code&amp;gt;) auf der Stufe 3. Die Bedeutung der jeweiligen Stufen ist in der [http://fhem.de/commandref_DE.html#verbose commandref] beschrieben.&lt;br /&gt;
&lt;br /&gt;
Während der Entwicklung eines Moduls kann man für eigene Debug-Zwecke auch die Funktion [[DevelopmentModuleAPI#Debug|Debug()]] verwenden um schnell und einfach Debug-Ausgaben in das Log zu schreiben. Diese sollten in der endgültigen Fassung jedoch nicht mehr vorhanden sein. Sie dienen ausschließlich zum Debugging während der Entwicklung.&lt;br /&gt;
&lt;br /&gt;
Eine genaue Beschreibung der Log-Funktion gibt es [[DevelopmentModuleAPI#Logging|hier im Wiki]].&lt;br /&gt;
&lt;br /&gt;
== Zweistufiges Modell für Module ==&lt;br /&gt;
[[Datei:Zweistufiges Modulkonzept.jpg|mini|rechts]]&lt;br /&gt;
Es gibt viele Geräte, welche die Kommunikation mit weiteren Geräten mit tlw. unterschiedlichen Protokollen ermöglichen. Das typischste Beispiel bietet hier der [[CUL]], welcher via Funk mit verschiedenen Protokollen weitere Geräte ansprechen kann (z.B. Aktoren, Sensoren, ...). Hier bildet ein Gerät eine Brücke durch die weitere Geräte in FHEM zugänglich gemacht werden können. Dabei werden über einen Kommunikationsweg (z.B. serielle Schnittstelle, TCP, ...) beliebig viele Geräte gesteuert. Typische Beispiele dazu sind:&lt;br /&gt;
&lt;br /&gt;
* [[CUL]]: stellt Geräte mit verschiedenen Kommunikationsprotokollen via Funk bereit (u.a. [[FS20]], [[HomeMatic]], [[Funk-Heizkörperregler_Kurz-Bedienungsanleitung_FHT|FHT]], [[MAX]], ...)&lt;br /&gt;
* [[HMLAN]]: stellt HomeMatic Geräte via Funk bereit&lt;br /&gt;
* [[MAX#MAXLAN|MAXLAN]]: stellt [[MAX|MAX!]] Geräte via Funk bereit&lt;br /&gt;
* [[PanStamp#panStick.2FShield|panStamp]]: stellt weitere panStamp Geräte via Funk bereit&lt;br /&gt;
&lt;br /&gt;
Dabei wird die Kommunikation in 2 Stufen unterteilt:&lt;br /&gt;
* physisches Modul - z.B. 00_CUL.pm - zuständig für die physikalische Kommunikation mit der Hardware. Empfangene Daten müssen einem logischen Modul zugeordnet werden.&lt;br /&gt;
* logische Modul(e) - z.B. 10_FS20.pm - interpretiert protokollspezifische Nachrichten. Sendet protokollspezifische Daten über das physische Modul an die Hardware.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;physisches Modul&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das physische Modul öffnet die Datenverbindung zum Gerät (z.B. CUL) und verarbeitet sämtliche Daten. Es kümmert sich um den Erhalt der Verbindung (bsp. durch Keep-Alives) und konfiguriert das Gerät so, dass eine Kommunikation mit allen weiteren Geräten möglich ist (bsp. Frequenz, Modulation, Kanal, etc.).&lt;br /&gt;
&lt;br /&gt;
Empfangene Nutzdaten werden über die Funktion [[DevelopmentModuleAPI#Dispatch|Dispatch()]] an logische Module weitergegeben.&lt;br /&gt;
&lt;br /&gt;
Das Modul stellt eine [[#Die_Match-Liste|Match-Liste]] bereit, anhand FHEM die Nachricht einem Modul zuordnen kann, sofern dieses noch nicht geladen sein sollte. FHEM lädt dann automatisch dieses Modul nach, zwecks Verarbeitung der Nachricht. Anhand einer bereitgestellten [[#Die_Client-Liste|Client-Liste]] kann FHEM feststellen, welche logischen Module mit diesem Modul kommunizieren können.&lt;br /&gt;
&lt;br /&gt;
Das Modul stellt eine [[#X_Write|Write]]-Funktion zur Verfügung, über die logische Module Daten an die Hardware übertragen können. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;logisches Modul&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das logische Modul interpretiert die Nachricht über eine bereitgestellte [[#X_Parse|Parse]]-Funktion und erzeugt entsprechende Readings/Events. Es stellt über &amp;lt;code&amp;gt;set&amp;lt;/code&amp;gt;-/&amp;lt;code&amp;gt;get&amp;lt;/code&amp;gt;-Kommandos Steuerungsmöglichkeiten dem Nutzer zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
Es stellt FHEM einen [[#Der_Match-Ausdruck|Match-Ausdruck]] zur Verfügung anhand FHEM ermitteln kann, ob die Nachricht durch das logische Modul verarbeitet werden kann.&lt;br /&gt;
&lt;br /&gt;
=== Die Client-Liste ===&lt;br /&gt;
&lt;br /&gt;
Die Client-Liste ist eine Auflistung von Modulnamen (genauer: regulären Ausdrücken die auf Modulnamen passen) die in einem physischen Modul gesetzt ist. Damit wird definiert, mit welche logischen Modulen das physikalische Modul  kommunizieren kann. &lt;br /&gt;
&lt;br /&gt;
Eine Client-Liste ist eine Zeichenkette, welche aus allen logischen Modulnamen besteht. Die einzelnen Namen werden durch einen Doppelpunkt getrennt. Anstatt kompletter Modulnamen können auch reguläre Ausdrücke verwendet werden, die auf mehrere Modulnamen passen.&lt;br /&gt;
&lt;br /&gt;
Bsp.: Die Client-Liste von dem Modul CUL lautet daher wie folgt:&lt;br /&gt;
&lt;br /&gt;
 FS20:FHT.*:KS300:USF1000:BS:HMS:CUL_EM:CUL_WS:CUL_FHTTK:CUL_HOERMANN:ESA2000:CUL_IR:CUL_TX:Revolt:IT:UNIRoll:SOMFY:STACKABLE_CC:CUL_RFR:CUL_TCM97001:CUL_REDIRECT&lt;br /&gt;
&lt;br /&gt;
Alle hier aufgelisteten Module können über das Modul CUL Daten empfangen bzw. senden.&lt;br /&gt;
&lt;br /&gt;
Die Client-Liste hat generell folgende Funktion:&lt;br /&gt;
* Die Funktion [[DevelopmentModuleAPI#Dispatch|Dispatch()]] prüft nur Module, welche in der Client-Liste enthalten sind, ob diese die Nachricht verarbeiten können.&lt;br /&gt;
* Die Funktion [[DevelopmentModuleAPI#AssignIoPort|AssignIoPort()]] prüft anhand sämtlicher Client-Listen in FHEM, welches IO-Gerät für ein logisches Gerät nutzbar ist.&lt;br /&gt;
&lt;br /&gt;
Üblicherweise wird die Client-Liste in der [[#X_Initialize|Initialize]]-Funktion im Modul-Hash gesetzt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Initialize($)&lt;br /&gt;
{&lt;br /&gt;
	my ($hash) = @_;&lt;br /&gt;
	...&lt;br /&gt;
	$hash-&amp;gt;{Clients} = &amp;quot;FS20:KS300:FHT.*&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man kann die Client-Liste jedoch auch pro physikalisches Gerät setzen. Eine gesetzte Client-Liste in einem Gerät hat immer Vorrang vor der Liste im Modul-Hash. Eine gerätespezifische Client-Liste wird dann verwendet, wenn bspw. ein Gerät je nach Konfiguration nur bestimmte logische Module bedienen kann. Bspw. kann ein CUL je nach RF-Einstellungen FS20, uvm. oder nur HomeMatic bedienen. In einem solchen Fall wird die Client-Liste im Geräte-Hash gesetzt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Define($$)&lt;br /&gt;
{&lt;br /&gt;
	my ( $hash, $def ) = @_;&lt;br /&gt;
	...&lt;br /&gt;
	$hash-&amp;gt;{Clients} = &amp;quot;CUL_HM&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In vielen Modulen, welche nach dem zweistufigem Konzept arbeiten, beginnt und endet die Client-Liste mit einem Doppelpunkt. Dies ist ein historisches Überbleibsel, da der Prüfmechanismus die Client-Liste früher auf das Vorhandensein von &amp;lt;code&amp;gt;&#039;&#039;&#039;&amp;lt;u&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;:&amp;lt;/font&amp;gt;&amp;lt;/u&amp;gt;&#039;&#039;&#039;&amp;amp;lt;Modulname&amp;amp;gt;&#039;&#039;&#039;&amp;lt;u&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;:&amp;lt;/font&amp;gt;&amp;lt;/u&amp;gt;&#039;&#039;&#039;&amp;lt;/code&amp;gt; prüfte. Dies ist nun nicht mehr notwendig. Die einzelnen Modulnamen müssen lediglich durch einen Doppelpunkt getrennt werden.&lt;br /&gt;
&lt;br /&gt;
=== Die Match-Liste ===&lt;br /&gt;
{{Randnotiz|RNTyp=Info|RNText=&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&amp;lt;u&amp;gt;&#039;&#039;&#039;ACHTUNG&#039;&#039;&#039;:&amp;lt;/u&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
Sämtliche regulären Ausdrücke in der Match-Liste werden &amp;quot;case insensitive&amp;quot; überprüft. Das bedeutet, dass Groß-/Kleinschreibung nicht berücksichtigt wird.&lt;br /&gt;
&lt;br /&gt;
Um dennoch in einem regulären Ausdruck auf Groß-/Kleinschreibung zu prüfen, kann man dieses mit dem Modifizierer &amp;lt;code&amp;gt;(?-i)&amp;lt;/code&amp;gt; wieder aktivieren:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
my %matchListFHEMduino = (&lt;br /&gt;
    ....&lt;br /&gt;
    &amp;quot;5:FHEMduino_PT2262&amp;quot;   =&amp;gt; &amp;quot;^(?-i)IR.*\$&amp;quot;,&lt;br /&gt;
    ....&lt;br /&gt;
    &amp;quot;13:IT&amp;quot;                =&amp;gt; &amp;quot;^(?-i)i......\$&amp;quot;,&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Siehe dazu Forumsbeitrag: {{Link2Forum|Topic=33422}}&lt;br /&gt;
}}&lt;br /&gt;
Die Match-Liste ordnet eine Nachrichtensyntax (regulärer Ausdruck) einem Modulnamen zu und wird in einem physikalischen Modul gesetzt. Sollte eine Nachricht vom physikalischen Gerät empfangen werden, die durch kein geladenes Modul verarbeitet werden kann, so wird über die Match-Liste geprüft, welches Modul diese Nachricht verarbeiten kann. Dieses Modul wird anschließend geladen und die Nachricht durch dieses verarbeitet. In dieser Liste findet mittels regulärem Ausdruck eine Zuordnung der Nachrichtenstruktur zum verarbeitenden logischen Modul statt.&lt;br /&gt;
&lt;br /&gt;
Diese Liste wird ausschließlich in der [[DevelopmentModuleAPI#Dispatch|Dispatch()]]-Funktion verwendet. Sollte keine passendes Modul, welches bereits geladen ist, zur Verarbeitung einer Nachricht gefunden werden, so wird mithilfe der Match-Liste aufgrund der vorliegenden Nachricht das entsprechende Modul ermittelt. Dieses Modul wird dann direkt geladen und die Nachricht wird via [[#X_Parse|Parse]]-Funktion verarbeitet.&lt;br /&gt;
&lt;br /&gt;
Die Match-Liste ist eine Zuordnung von einem Sortierpräfix + Modulname zu einem regulären Ausdruck:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;1:FS20&amp;quot;  =&amp;gt; &amp;quot;^81..(04|0c)..0101a001&amp;quot;,&lt;br /&gt;
    &amp;quot;2:KS300&amp;quot; =&amp;gt; &amp;quot;^810d04..4027a001&amp;quot;,&lt;br /&gt;
    &amp;quot;3:FHT&amp;quot;   =&amp;gt; &amp;quot;^81..(04|09|0d)..(0909a001|83098301|c409c401)..&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Sortierpräfix dient als Sortierhilfe um so die Reihenfolge der Prüfung festzulegen. Bei der Prüfung wird der Hash mittels sort() sortiert und die regulären Ausdrücke werden dann nacheinander getestet. Daher sollten die präzisesten Ausdrücke immer zuerst getestet werden, sofern es weniger präzise Ausdrücke in der Match-Liste gibt. Dabei ist zu beachten, dass der Sortierpräfix nicht nach numerischen Regeln sortiert wird, sondern basierend auf der Zeichenreihenfolge.&lt;br /&gt;
&lt;br /&gt;
Üblicherweise wird die Match-Liste in der [[#X_Initialize|Initialize]]-Funktion im Modul-Hash gesetzt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Initialize($)&lt;br /&gt;
{&lt;br /&gt;
	my ($hash) = @_;&lt;br /&gt;
&lt;br /&gt;
	...&lt;br /&gt;
&lt;br /&gt;
	$hash-&amp;gt;{MatchList} = { &amp;quot;1:FS20&amp;quot;      =&amp;gt; &amp;quot;^81..(04|0c)..0101a001&amp;quot;,&lt;br /&gt;
			       &amp;quot;2:KS300&amp;quot;     =&amp;gt; &amp;quot;^810d04..4027a001&amp;quot;,&lt;br /&gt;
			       &amp;quot;3:FHT&amp;quot;       =&amp;gt; &amp;quot;^81..(04|09|0d)..(0909a001|83098301|c409c401)..&amp;quot; };&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man kann die Match-Liste, ähnlich wie bei der Client-Liste, auch pro physikalisches Gerät setzen. Dabei hat auch hier die Match-Liste eines Gerätes immer Vorrang vor der Match-Liste aus dem Modul-Hash:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Define($$)&lt;br /&gt;
{&lt;br /&gt;
	my ($hash, $def) = @_;&lt;br /&gt;
&lt;br /&gt;
	...&lt;br /&gt;
&lt;br /&gt;
	$hash-&amp;gt;{MatchList} = { &amp;quot;1:CUL_HM&amp;quot; =&amp;gt; &amp;quot;^A....................&amp;quot; };&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Der Match-Ausdruck ===&lt;br /&gt;
&lt;br /&gt;
Ein Match-Ausdruck wird in einem logischen Modul gesetzt und dient der Prüfung, ob eine Nachricht durch das eigene Modul via [[#X_Parse|Parse]]-Funktion verarbeitet werden kann. Es handelt sich hierbei um einen einzelnen regulären Ausdruck, den FHEM innerhalb der [[DevelopmentModuleAPI#Dispatch|Dispatch()]]-Funktion prüft. Nur wenn eine Nachricht via Dispatch() auf diesen Audruck matcht, wird die Parse-Funktion aufgerufen um die Nachricht zu verarbeiten. &lt;br /&gt;
&lt;br /&gt;
Der Hintergrund, warum man den Aufruf mit einem solchen Ausdruck vorher abprüft, liegt in der Möglichkeit, dass ein physikalisches Modul mehrere unterschiedliche logische Module ansprechen kann. So kann FHEM jedes geladene Modul durch diesen Match-Ausdruck prüfen, ob es diese Nachricht verarbeiten kann. Erst, wenn alle geladenen Module, aufgrund einer Prüfung des Ausdrucks, die Nachricht nicht verarbeiten können, wird via [[#Die_Match-Liste|Match-Liste]] ermittelt, welches Modul geladen werden muss um die Nachricht zu verarbeiten. &lt;br /&gt;
&lt;br /&gt;
Der Match-Ausdruck wird in der [[#X_Initialize|Initialize]]-Funktion zur Verfügung gestellt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Initialize($)&lt;br /&gt;
{&lt;br /&gt;
	my ($hash) = @_;&lt;br /&gt;
&lt;br /&gt;
	...&lt;br /&gt;
	&lt;br /&gt;
	# Dieses Modul verarbeitet FS20 Nachrichten&lt;br /&gt;
	$hash-&amp;gt;{Match} = &amp;quot;^81..(04|0c)..0101a001&amp;quot;; &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Die vollständige Implementierung ===&lt;br /&gt;
&lt;br /&gt;
Hier nun eine Zusammenfassung beim zweistufigen Modulkonzept in der jeweiligen Stufe implementiert werden muss, damit die Kommunikation funktioniert.&lt;br /&gt;
&lt;br /&gt;
==== physisches Modul ====&lt;br /&gt;
&lt;br /&gt;
Das physische Modul, welches als Kommunikationsbrücke zwischen der Hardware und logischen Modulen fungieren wird, sollte mindestens folgende Funktionen implementieren:&lt;br /&gt;
&lt;br /&gt;
* [[#X_Initialize|Initialize]]-Funktion - Zum Registrieren des Moduls in FHEM.&lt;br /&gt;
* [[#X_Define|Define]]-Funktion - Zum öffnen der Datenverbindung zur Hardware (IP-Adresse/serielle Schnittstelle/...).&lt;br /&gt;
* [[#X_Read|Read]]-Funktion - Zum Lesen von Daten, welche die Hardware übermittelt.&lt;br /&gt;
* [[#X_Read|Ready]]-Funktion - Zum Wiederaufbau der Verbindung bei Verbindungsabbruch, bzw. Prüfung auf lesbare Daten bei serieller Schnittstelle unter Windows.&lt;br /&gt;
* [[#X_Write|Write]]-Funktion - Zum Senden von Daten, welche logische Module via [[DevelopmentModuleAPI#IOWrite|IOWrite()]] an die Hardware übertragen möchten.&lt;br /&gt;
* [[#X_Undef|Undef]]-Funktion - Schließen der Verbindung zur Hardware beim Löschen via &amp;lt;code&amp;gt;delete&amp;lt;/code&amp;gt; bzw. &amp;lt;code&amp;gt;rereadcfg&amp;lt;/code&amp;gt;.&lt;br /&gt;
* [[#X_Shutdown|Shutdown]]-Funktion - Schließen der Verbindung zur Hardware beim Stopp von FHEM via &amp;lt;code&amp;gt;shutdown&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Desweiteren müssen in der [[#X_Initialize|Initialize]]-Funktion folgende Daten bereitgestellt werden:&lt;br /&gt;
&lt;br /&gt;
* [[#Die_Client-Liste|Client-Liste]] - Auflistung aller logischen Module, die über dieses Modul kommunizieren können&lt;br /&gt;
* [[#Die_Match-Liste|Match-Liste]] - Zuordnung von Nachrichtensyntax zu Modul zwecks Autoload-Funktionalität.&lt;br /&gt;
&lt;br /&gt;
==== logisches Modul ====&lt;br /&gt;
&lt;br /&gt;
Das logische Modul, bildet ein einzelnes Gerät ab, über das mit einem physikalisches Modul kommuniziert werden kann. Es sollte mindestens folgende Funktionen implementieren:&lt;br /&gt;
&lt;br /&gt;
* [[#X_Initialize|Initialize]]-Funktion - Zum Registrieren des Moduls in FHEM.&lt;br /&gt;
* [[#X_Define|Define]]-Funktion - Speichern des Definition Pointers (siehe [[#X_Parse|Parse-Funktion]])&lt;br /&gt;
* [[#X_Parse|Parse]]-Funktion - Zum Lesen von Daten, welche die Hardware übermittelt.&lt;br /&gt;
* [[#X_Undef|Undef]]-Funktion - Löschen des Definition Pointers beim Löschen via &amp;lt;code&amp;gt;delete&amp;lt;/code&amp;gt; bzw. &amp;lt;code&amp;gt;rereadcfg&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Desweiteren müssen in der [[#X_Initialize|Initialize]]-Funktion folgende Daten bereitgestellt werden:&lt;br /&gt;
&lt;br /&gt;
* [[#Der_Match-Ausdruck|Match-Ausdruck]] - Prüfausdruck, ob eine Nachricht durch dieses Modul verarbeitet werden kann.&lt;br /&gt;
&lt;br /&gt;
=== Kommunikation von der Hardware bis zu den logischen Modulen ===&lt;br /&gt;
&lt;br /&gt;
Die Gerätedefinition eines physische Moduls öffnet eine Verbindung zur Hardware. Die [[#X_Read|Read]]-Funktion wird bei anstehenden Daten aus der Hauptschleife von fhem.pl aufgerufen.&lt;br /&gt;
&lt;br /&gt;
Die Read-Funktion stellt dabei sicher, dass die Daten&lt;br /&gt;
* komplett (in der Regel über einen internen Puffer in &amp;lt;code&amp;gt;$hash&amp;lt;/code&amp;gt;) und&lt;br /&gt;
* korrekt (z.B. via Prüfung mittels regulärem Ausdruck)&lt;br /&gt;
sind und ruft die globale Funktion [[DevelopmentModuleAPI#Dispatch|Dispatch()]] mit einer kompletten Nachricht auf.&lt;br /&gt;
&lt;br /&gt;
Die Funktion Dispatch() sucht nach einer passenden Definition via [[#Die_Client-Liste|Client-Liste]] in physischen Definitionen/Modulen nach möglichen logischen Modulen zur Verarbeitung. Alle zum Zeitpunkt geladenen Module, die in der Client-Liste aufgeführt sind, werden über den [[#Der_Match-Ausdruck|Match-Ausdruck]] geprüft, ob sie mit der Nachricht etwas anfangen können. Sollte bei einem Modul der Match-Ausdruck passen, so wird die entsprechende [[#X_Parse|Parse]]-Funktion des logischen Moduls aufgerufen. Sofern keine passendes Modul gefunden wurde, um die Nachricht zu verarbeiten, wird in der [[#Die_Match-Liste|Match-Liste]] im Geräte- bzw. Modul-Hash der physischen Gerätedefinition nach dem passenden Modul gesucht. Sollte es darin ein Modul geben, was diese Art von Nachricht verarbeiten kann, so wird versucht dieses Modul zu laden um nun die Nachricht via Parse-Funktion zu verarbeiten. Es erfolgt in diesem Fall keine Vorprüfung durch den Match-Ausdruck.&lt;br /&gt;
&lt;br /&gt;
Durch Dispatch() wird nun die [[#X_Parse|Parse]]-Funktion des gefundenen logischen Moduls aufgerufen. Diese&lt;br /&gt;
* interpretiert die übergebene Nachricht,&lt;br /&gt;
* versucht eine existierende Gerätedefinition in FHEM zu finden (z.B. mittels Definition Pointer), für welche die Nachricht addressiert ist,&lt;br /&gt;
* setzt alle [[#Readings|Readings]] für die gefundene Gerätedefinition via [[DevelopmentModuleAPI#Readings_.2F_Events|readings*update]]()-Funktionen,&lt;br /&gt;
* gibt den Namen der logischen Definition zurück, welche die Nachricht verarbeitet hat.&lt;br /&gt;
&lt;br /&gt;
Sollte keine passende Gerätedefinition für die entsprechende Nachricht existieren (Adresse/ID/Kanal/...), wird der Gerätename &amp;quot;UNDEFINED&amp;quot; inkl. einem passenden &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt;-Statement zurückgegeben, um die Definition durch [[autocreate]] erzeugen zu lassen.&lt;br /&gt;
&lt;br /&gt;
Es findet während der Verarbeitung einer Nachricht durch Dispatch()/Parse-Funktion keine sofortige Eventverarbeitung (via [[DevelopmentModuleAPI#Dispatch|DoTrigger()]]) statt, wenn die [[DevelopmentModuleAPI#Readings_.2F_Events|readings*update]]()-Funktionen verwendet werden.&lt;br /&gt;
(Im Gegensatz zum direkten Aufrufen der readings*update Funktionen ohne vorhergehendes Dispatch() )&lt;br /&gt;
&lt;br /&gt;
Die Funktion Dispatch() triggert das Event-Handling für das von der Parse-Funktion zurückgegebene logische Device selbstständig.&lt;br /&gt;
&lt;br /&gt;
Optional führt die Funktion Dispatch() eine Überprüfung auf Nachrichtenduplikate beim Einsatz von mehreren IO-Geräten durch. Dazu wird eine implementierte [[#X_Fingerprint|Fingerprint]]-Funktion im physischen oder logischen Modul benötigt.&lt;br /&gt;
&lt;br /&gt;
=== Kommunikation von den logischen Modulen bis zur Hardware ===&lt;br /&gt;
&lt;br /&gt;
Um von einem logischen Modul eine Nachricht an die Hardware senden zu können, muss zunächst im logischen Gerät ein passenden IO-Gerät ausgewählt sein. Dazu muss die Funktion [[DevelopmentModuleAPI#AssignIoPort|AssignIoPort()]] ein entsprechendes IO-Gerät auswählen und in &amp;lt;code&amp;gt;$hash-&amp;gt;{IODev}&amp;lt;/code&amp;gt; setzen. Dieser Aufruf wird üblicherweise in der [[#X_Define|Define]]-Funktion des logischen Moduls ausgeführt. Erst, wenn ein IO-Gerät ausgewählt wurde, können Daten über das physikalische Gerät an die Hardware übermittelt werden.&lt;br /&gt;
&lt;br /&gt;
Zum Senden von Daten ruft das logische Modul die Funktion [[DevelopmentModuleAPI#IOWrite|IOWrite()]] samt Daten auf. Diese ruft für das entsprechende IO-Gerät die [[#X_Write|Write]]-Funktion auf und übergibt die Daten zum Schreiben an das physikalische Modul. Die Write-Funktion kümmert sich nun um die Übertragung der Daten an die Hardware. &lt;br /&gt;
&lt;br /&gt;
Keine direkten Zugriffe zwischen dem logischen und dem physischen Gerät gibt (d.h. keine direkten Aufrufe von Funktionen, kein direktes Überprüfen von &amp;lt;code&amp;gt;$hash&amp;lt;/code&amp;gt;-Inhalten, ...), so können die Module hintereinander geschaltet werden (z.B. für Routerfunktionen wie bei der [[RFR_CUL|RFR]]-Funktionalität) oder mittels [[FHEM2FHEM]] im RAW-Modus zwei FHEM-Installationen verbunden werden und die logischen Geräte können dennoch kommunizieren.&lt;br /&gt;
&lt;br /&gt;
=== Automatisches Anlegen von logischen Gerätedefinitionen (autocreate) ===&lt;br /&gt;
&lt;br /&gt;
Das logische Modul kann im Rahmen der [[#X_Parse|Parse]]-Funktion eine neue Gerätedefinition anlegen, sofern eine passende Definition nicht existieren sollte. Die Parse-Funktion gibt generell den Namen der logischen Gerätedefinition zurück, für welche die Nachricht verarbeitet wurde. Sollte keine passende Definition gefunden werden, so muss die Parse-Funktion folgenden Rückgabewert liefern (zusammenhängende Zeichenkette):&lt;br /&gt;
&lt;br /&gt;
 UNDEFINED &#039;&#039;&amp;amp;lt;Namensvorschlag&amp;amp;gt;&#039;&#039; &#039;&#039;&amp;amp;lt;Modulname&amp;amp;gt;&#039;&#039; &#039;&#039;&amp;amp;lt;Define-Parameter&amp;amp;gt;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Sollte also bspw. im Rahmen der Parse-Funktion zu Modul X eine Nachricht nicht einer existierenden Gerätedefinition zugeordnet werden können, so muss ein Namensvorschlag erstellt werden der eine eindeutige Komponente wie bspw. eine Adresse/ID/Kanal-Nr enthält. In der Regel wird hier immer der Modulname zusammen mit der eindeutigen Komponente, durch einen Unterstrich getrennt, verwendet (Bsp: &amp;lt;code&amp;gt;X_4834&amp;lt;/code&amp;gt;). Der Modulname ist in der Regel immer der, des eigenen Moduls. In besonderen Fällen kann man hier auch einen abweichenden Modulnamen angeben. Dies wird bspw. bei den [[PanStamp#FHEM-Module.2FDevice_Definition_Files|SWAP-Modulen]] eingesetzt. Als Define-Parameter müssen alle notwendigen Parameter angegeben werden, die beim Aufruf des &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt;-Befehls notwendig sind, damit eine neu angelegte Gerätedefinition Nachrichten zu dieser eindeutigen Adresse Daten verarbeitet. Dazu muss mind. die eindeutige Adresse mitgegeben werden.&lt;br /&gt;
&lt;br /&gt;
Beispiel für FS20:&lt;br /&gt;
&lt;br /&gt;
 UNDEFINED FS20_0ae42f8 FS20 0ae42 f8&lt;br /&gt;
&lt;br /&gt;
Sobald [[DevelopmentModuleAPI#Dispatch|Dispatch()]] einen solchen Rückgabewert von einer [[#X_Parse|Parse]]-Funktion erhält, wird diese Zeichenkette so wie sie ist via [[DevelopmentModuleAPI#DoTrigger|DoTrigger()]] als Event für die Definition &amp;lt;code&amp;gt;global&amp;lt;/code&amp;gt; getriggert.&lt;br /&gt;
&lt;br /&gt;
Sofern der Nutzer das Modul [[autocreate]] verwendet (definiert hat), kümmert sich dieses nun um das Anlegen einer entsprechenden Gerätedefinition. Es lauscht dabei auf generierte Events der Definition &amp;lt;code&amp;gt;global&amp;lt;/code&amp;gt; via [[#X_Notify|Notify]]-Funktion. Der Nutzer kann dabei das Verhalten von autocreate durch entsprechende Parameter beeinflussen.&lt;br /&gt;
&lt;br /&gt;
Das Modul, für welches autocreate eine neue Definition anlegen möchte, kann das Verhalten durch entsprechende Parameter im Modul-Hash beeinflussen. Dabei gilt, dass gesetzte Attribute durch den Nutzer generell Vorrang haben. Die entsprechenden Parameter werden dabei im Rahmen der [[#X_Initialize|Initialize]]-Funktion im Modul-Hash gesetzt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub X_Initialize($)&lt;br /&gt;
{&lt;br /&gt;
	my ($hash) = @_;&lt;br /&gt;
 &lt;br /&gt;
	...&lt;br /&gt;
 &lt;br /&gt;
	$hash-&amp;gt;{AutoCreate} = {&amp;quot;X_.*&amp;quot;  =&amp;gt; { ATTR   =&amp;gt; &amp;quot;event-on-change-reading:.* event-min-interval:.*:300&amp;quot;,&lt;br /&gt;
	                                    FILTER =&amp;gt; &amp;quot;%NAME&amp;quot;,&lt;br /&gt;
	                                    GPLOT  =&amp;gt; &amp;quot;temp4hum4:Temp/Hum,&amp;quot;,&lt;br /&gt;
	                                    autocreateThreshold =&amp;gt; &amp;quot;2:140&amp;quot;&lt;br /&gt;
					  }&lt;br /&gt;
	                      };&lt;br /&gt;
			    &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hierbei wird unterhalb von &amp;lt;code&amp;gt;$hash-&amp;gt;{AutoCreate}&amp;lt;/code&amp;gt; eine Liste angelegt, wo einem regulären Ausdruck für einen anzulegenden Definitionsnamen entsprechende Optionen zugeordnet werden. Sobald durch autocreate eine Gerätedefintion angelegt wird, auf den ein hier gelisteter Ausdruck matcht, so werden die zugeordneten Optionen berücksichtigt.&lt;br /&gt;
&lt;br /&gt;
Hier eine Auflistung aller möglichen Optionen und ihrer Bedeutung:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Optionsname !! Beispiel !! Bedeutung&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ATTR&amp;lt;/code&amp;gt;|| &amp;lt;code&amp;gt;&amp;quot;event-on-change-reading:.* event-min-interval:.*:300&amp;quot;&amp;lt;/code&amp;gt; || Eine Auflistung von Attributen, die nach dem Anlegen einer Definition zusätzlich gesetzt werden. Es handelt sich hierbei um eine Leerzeichen-separierte Liste von Doppelpunkt-getrennten Tupels mit Attributname und -wert.&lt;br /&gt;
&lt;br /&gt;
Für das dargestellte Beispiel bedeutet dies, dass nach dem Anlegen der Definition folgende FHEM-Befehle zusätzlich ausgeführt werden:&lt;br /&gt;
&lt;br /&gt;
 attr &#039;&#039;&amp;amp;lt;Name&amp;amp;gt;&#039;&#039; event-on-change-reading .*&lt;br /&gt;
 attr &#039;&#039;&amp;amp;lt;Name&amp;amp;gt;&#039;&#039; event-min-interval .*:300&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;FILTER&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;%NAME&amp;lt;/code&amp;gt;|| Sofern in der autocreate-Definiton das Attribut &amp;lt;code&amp;gt;filelog&amp;lt;/code&amp;gt; entsprechend durch den Nutzer gesetzt ist, wird eine zugehörige FileLog-Definition angelegt. Diese Option setzt den dabei benutzten Filter-Regexp, der beim Anlegen der FileLog-Definition gesetzt wird. &lt;br /&gt;
&lt;br /&gt;
Dabei werden folgende Platzhalter durch die entsprechenden Werte der neu angelegten Gerätedefinition ersetzt:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;%NAME&amp;lt;/code&amp;gt; - wird ersetzt durch den Definitionsnamen&lt;br /&gt;
* &amp;lt;code&amp;gt;%TYPE&amp;lt;/code&amp;gt; - wird ersetzt durch den Modulnamen&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;GPLOT&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;temp4hum4:Temp/Hum,&amp;quot;&amp;lt;/code&amp;gt; || Sofern eine FileLog-Definition angelegt wurde, kann man weiterführend dazu eine passende SVG-Definition erzeugen um Daten aus dem erzeugten FileLog zu visualisieren. Ein typischer Fall sind hierbei Temperatursensoren, wo es sinnvoll sein kann, einen passenden SVG-Plot mit Temperatur/Luftfeuchtigkeit direkt anzulegen.&lt;br /&gt;
&lt;br /&gt;
Es handelt sich hierbei um eine kommaseparierte Auflistung von gplot-Dateinamen und optionalen Label-Texten durch einen Doppelpunkt getrennt. Im genannten Beispiel entspricht &amp;lt;code&amp;gt;temp4hum4&amp;lt;/code&amp;gt; der zu verwendenden GnuPlot-Datei und &amp;lt;code&amp;gt;Temp/Hum&amp;lt;/code&amp;gt; dem zu verwendenden Label ([[SVG]] Attribut &amp;lt;code&amp;gt;label&amp;lt;/code&amp;gt;). Das Label wird auch durch FileLog verwendet als Link-Text zum entsprechenden SVG Plot. Alternativ kann auch nur die entsprechende GnuPlot-Datei anegeben werden ohne Label. Für jede angegebene GnuPlot-Datei wird anschließend eine entsprechende SVG-Definition erzeugt mit der vorher erzeugten FileLog-Definition als Datenquelle.&lt;br /&gt;
&lt;br /&gt;
Der gesamte Inhalt der &amp;lt;code&amp;gt;GPLOT&amp;lt;/code&amp;gt;-Option wird beim Anlegen einer FileLog-Definition dem Attribut &amp;lt;code&amp;gt;logtype&amp;lt;/code&amp;gt; als Wert plus dem Text &amp;lt;code&amp;gt;text&amp;lt;/code&amp;gt; zugewiesen. Daher muss der Inhalt der Option &amp;lt;code&amp;gt;GPLOT&amp;lt;/code&amp;gt; immer mit einem Komma enden. &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;autocreateThreshold&amp;lt;/code&amp;gt;|| &amp;lt;code&amp;gt;&amp;quot;2:10&amp;quot;|| Definiert, wie viele Aufrufe (im Bsp: &amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt;) von autocreate innerhalb welcher Zeit (im Bsp: &amp;lt;code&amp;gt;10&amp;lt;/code&amp;gt; Sek.) stattfinden müssen, bevor die Gerätedefinition tatsächlich durch autocreate angelegt wird. Dadurch kann das ungewollte Anlegen von Geräten verhindert werden die tatsächlich nicht in Echt existieren. Aufgrund von Funkstörungen kann es durchaus zum ungewollten Anlegen einer Definition kommen. Diese Funktion lässt eine Definition erst zu wenn innerhalb einer vorgegeben Zeit eine Mindestzahl an Nachrichten eintrifft.&lt;br /&gt;
&lt;br /&gt;
Die erste Zahl stellt dabei die Mindestanzahl an Nachrichten dar. Die Zweite Zahl stellt die Zeit in Sekunden dar, in der die Mindestanzahl an Nachrichten erreicht werden muss um eine entsprechende Gerätedefinition anzulegen. &lt;br /&gt;
&lt;br /&gt;
Sofern diese Option nicht gesetzt ist, wird standardmäßig &amp;lt;code&amp;gt;2:60&amp;lt;/code&amp;gt; verwendet.&lt;br /&gt;
&lt;br /&gt;
Diese Option kann durch den Anwender über das Attribut &amp;lt;code&amp;gt;autocreateThreshold&amp;lt;/code&amp;gt; übersteuert werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sofern diese Option nicht gesetzt ist&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;noAutocreatedFilelog&amp;lt;/code&amp;gt;|| &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;|| Flag. Sofern gesetzt, wird keine FileLog- und ggf. SVG-Definition erzeugt. Selbst wenn der Nutzer durch entsprechende Attribute das Anlegen wünscht. Diese Option ist sinnvoll für Module bzw. Geräte die keine Readings erzeugen.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Ergänzende Hinweise ==&lt;br /&gt;
Die Wahl der vorangestellten Nummer für den Dateinamen eines neuen Moduls hat keine Bedeutung mehr, es sei denn die Nummer ist 99. Module, die mit 99_ beginnen, werden von FHEM automatisch geladen. Module mit einer anderen Nummer nur wenn ein &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt;-Befehl dafür sorgt, dass das Modul geladen wird.&lt;br /&gt;
&lt;br /&gt;
Wenn ein Modul Initialisierungsdaten benötigt, sollten diese im Modul selbst enthalten sein. Eine zusätzliche Datei oder sogar ein Unterverzeichnis mit mehreren Dateien ist bei FHEM nicht üblich und sollte bei Modulen, die mit FHEM ausgeliefert werden nur in Rücksprache mit Rudolf König angelegt werden, da sie sonst bei einem Update nicht verteilt werden.&lt;br /&gt;
&lt;br /&gt;
== Weitere Informationen ==&lt;br /&gt;
Wenn man weitere Details wissen möchte, ist ein erster sinnvoller Schritt ein Blick in die Datei fhem.pl. Dort sieht man im Perl-Code wie die Module aufgerufen werden, was vorher passiert und was danach. Am Anfang der Datei (ca. ab Zeile 130) findet man beispielsweise eine Liste der globalen Variablen, die den Modulen zur Verfügung stehen sowie Details zu den wichtigen Hashes %modules und %defs. Wer mit Perl noch nicht so gut klar kommt, dem hilft eventuell ein Blick auf die Perldoc Website[http://perldoc.perl.org/] oder in das Perl-Buch seiner Wahl. Auch die FHEM Commandref [http://fhem.de/commandref.html] sollte nicht unterschätzt werden. Es stehen oft mehr interessante Details auch für Modulentwickler darin als man zunächst vermuten könnte.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== &amp;quot;Hello World&amp;quot; Beispiel ==&lt;br /&gt;
&lt;br /&gt;
98_Hello.pm&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
package main;&lt;br /&gt;
use strict;&lt;br /&gt;
use warnings;&lt;br /&gt;
&lt;br /&gt;
my %Hello_gets = (&lt;br /&gt;
	&amp;quot;whatyouwant&amp;quot;	=&amp;gt; &amp;quot;can&#039;t&amp;quot;,&lt;br /&gt;
	&amp;quot;whatyouneed&amp;quot;	=&amp;gt; &amp;quot;try sometimes&amp;quot;,&lt;br /&gt;
	&amp;quot;satisfaction&amp;quot;  =&amp;gt; &amp;quot;no&amp;quot;&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
sub Hello_Initialize($) {&lt;br /&gt;
    my ($hash) = @_;&lt;br /&gt;
&lt;br /&gt;
    $hash-&amp;gt;{DefFn}      = &#039;Hello_Define&#039;;&lt;br /&gt;
    $hash-&amp;gt;{UndefFn}    = &#039;Hello_Undef&#039;;&lt;br /&gt;
    $hash-&amp;gt;{SetFn}      = &#039;Hello_Set&#039;;&lt;br /&gt;
    $hash-&amp;gt;{GetFn}      = &#039;Hello_Get&#039;;&lt;br /&gt;
    $hash-&amp;gt;{AttrFn}     = &#039;Hello_Attr&#039;;&lt;br /&gt;
    $hash-&amp;gt;{ReadFn}     = &#039;Hello_Read&#039;;&lt;br /&gt;
&lt;br /&gt;
    $hash-&amp;gt;{AttrList} =&lt;br /&gt;
          &amp;quot;formal:yes,no &amp;quot;&lt;br /&gt;
        . $readingFnAttributes;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub Hello_Define($$) {&lt;br /&gt;
    my ($hash, $def) = @_;&lt;br /&gt;
    my @param = split(&#039;[ \t]+&#039;, $def);&lt;br /&gt;
    &lt;br /&gt;
    if(int(@param) &amp;lt; 3) {&lt;br /&gt;
        return &amp;quot;too few parameters: define &amp;lt;name&amp;gt; Hello &amp;lt;greet&amp;gt;&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    my $hash-&amp;gt;{name}  = $param[0];&lt;br /&gt;
    my $hash-&amp;gt;{greet} = $param[2];&lt;br /&gt;
    &lt;br /&gt;
    return undef;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub Hello_Undef($$) {&lt;br /&gt;
    my ($hash, $arg) = @_; &lt;br /&gt;
    # nothing to do&lt;br /&gt;
    return undef;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub Hello_Get($@) {&lt;br /&gt;
	my ($hash, @param) = @_;&lt;br /&gt;
	&lt;br /&gt;
	return &#039;&amp;quot;get Hello&amp;quot; needs at least one argument&#039; if (int(@param) &amp;lt; 2);&lt;br /&gt;
	&lt;br /&gt;
	my $name = shift @param;&lt;br /&gt;
	my $opt = shift @param;&lt;br /&gt;
	if(!$Hello_gets{$opt}) {&lt;br /&gt;
		my @cList = keys %Hello_gets;&lt;br /&gt;
		return &amp;quot;Unknown argument $opt, choose one of &amp;quot; . join(&amp;quot; &amp;quot;, @cList);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	if($attr{$name}{formal} eq &#039;yes&#039;) {&lt;br /&gt;
	    return $Hello_gets{$opt}.&#039;, sir&#039;;&lt;br /&gt;
    }&lt;br /&gt;
	return $Hello_gets{$opt};&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub Hello_Set($@) {&lt;br /&gt;
	my ($hash, @param) = @_;&lt;br /&gt;
	&lt;br /&gt;
	return &#039;&amp;quot;set Hello&amp;quot; needs at least one argument&#039; if (int(@param) &amp;lt; 2);&lt;br /&gt;
	&lt;br /&gt;
	my $name = shift @param;&lt;br /&gt;
	my $opt = shift @param;&lt;br /&gt;
	my $value = join(&amp;quot;&amp;quot;, @param);&lt;br /&gt;
	&lt;br /&gt;
	if(!defined($Hello_gets{$opt})) {&lt;br /&gt;
		my @cList = keys %Hello_gets;&lt;br /&gt;
		return &amp;quot;Unknown argument $opt, choose one of &amp;quot; . join(&amp;quot; &amp;quot;, @cList);&lt;br /&gt;
	}&lt;br /&gt;
    $hash-&amp;gt;{STATE} = $Hello_gets{$opt} = $value;&lt;br /&gt;
    &lt;br /&gt;
	return &amp;quot;$opt set to $value. Try to get it.&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
sub Hello_Attr(@) {&lt;br /&gt;
	my ($cmd,$name,$attr_name,$attr_value) = @_;&lt;br /&gt;
	if($cmd eq &amp;quot;set&amp;quot;) {&lt;br /&gt;
        if($attr_name eq &amp;quot;formal&amp;quot;) {&lt;br /&gt;
			if($attr_value !~ /^yes|no$/) {&lt;br /&gt;
			    my $err = &amp;quot;Invalid argument $attr_value to $attr_name. Must be yes or no.&amp;quot;;&lt;br /&gt;
			    Log 3, &amp;quot;Hello: &amp;quot;.$err;&lt;br /&gt;
			    return $err;&lt;br /&gt;
			}&lt;br /&gt;
		} else {&lt;br /&gt;
		    return &amp;quot;Unknown attr $attr_name&amp;quot;;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	return undef;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&lt;br /&gt;
=pod&lt;br /&gt;
=begin html&lt;br /&gt;
&lt;br /&gt;
&amp;lt;a name=&amp;quot;Hello&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;Hello&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
    &amp;lt;i&amp;gt;Hello&amp;lt;/i&amp;gt; implements the classical &amp;quot;Hello World&amp;quot; as a starting point for module development. &lt;br /&gt;
    You may want to copy 98_Hello.pm to start implementing a module of your very own. See &lt;br /&gt;
    &amp;lt;a href=&amp;quot;http://www.fhemwiki.de/wiki/DevelopmentModuleIntro&amp;quot;&amp;gt;DevelopmentModuleIntro&amp;lt;/a&amp;gt; for an &lt;br /&gt;
    in-depth instruction to your first module.&lt;br /&gt;
    &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
    &amp;lt;a name=&amp;quot;Hellodefine&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
    &amp;lt;b&amp;gt;Define&amp;lt;/b&amp;gt;&lt;br /&gt;
    &amp;lt;ul&amp;gt;&lt;br /&gt;
        &amp;lt;code&amp;gt;define &amp;amp;lt;name&amp;amp;gt; Hello &amp;amp;lt;greet&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
        &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
        Example: &amp;lt;code&amp;gt;define HELLO Hello TurnUrRadioOn&amp;lt;/code&amp;gt;&lt;br /&gt;
        &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
        The &amp;quot;greet&amp;quot; parameter has no further meaning, it just demonstrates&lt;br /&gt;
        how to set a so called &amp;quot;Internal&amp;quot; value. See &amp;lt;a href=&amp;quot;http://fhem.de/commandref.html#define&amp;quot;&amp;gt;commandref#define&amp;lt;/a&amp;gt; &lt;br /&gt;
        for more info about the define command.&lt;br /&gt;
    &amp;lt;/ul&amp;gt;&lt;br /&gt;
    &amp;lt;br&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
    &amp;lt;a name=&amp;quot;Helloset&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
    &amp;lt;b&amp;gt;Set&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
    &amp;lt;ul&amp;gt;&lt;br /&gt;
        &amp;lt;code&amp;gt;set &amp;amp;lt;name&amp;amp;gt; &amp;amp;lt;option&amp;amp;gt; &amp;amp;lt;value&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
        &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
        You can &amp;lt;i&amp;gt;set&amp;lt;/i&amp;gt; any value to any of the following options. They&#039;re just there to &lt;br /&gt;
        &amp;lt;i&amp;gt;get&amp;lt;/i&amp;gt; them. See &amp;lt;a href=&amp;quot;http://fhem.de/commandref.html#set&amp;quot;&amp;gt;commandref#set&amp;lt;/a&amp;gt; &lt;br /&gt;
        for more info about the set command.&lt;br /&gt;
        &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
        Options:&lt;br /&gt;
        &amp;lt;ul&amp;gt;&lt;br /&gt;
              &amp;lt;li&amp;gt;&amp;lt;i&amp;gt;satisfaction&amp;lt;/i&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
                  Defaults to &amp;quot;no&amp;quot;&amp;lt;/li&amp;gt;&lt;br /&gt;
              &amp;lt;li&amp;gt;&amp;lt;i&amp;gt;whatyouwant&amp;lt;/i&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
                  Defaults to &amp;quot;can&#039;t&amp;quot;&amp;lt;/li&amp;gt;&lt;br /&gt;
              &amp;lt;li&amp;gt;&amp;lt;i&amp;gt;whatyouneed&amp;lt;/i&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
                  Defaults to &amp;quot;try sometimes&amp;quot;&amp;lt;/li&amp;gt;&lt;br /&gt;
        &amp;lt;/ul&amp;gt;&lt;br /&gt;
    &amp;lt;/ul&amp;gt;&lt;br /&gt;
    &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;a name=&amp;quot;Helloget&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
    &amp;lt;b&amp;gt;Get&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
    &amp;lt;ul&amp;gt;&lt;br /&gt;
        &amp;lt;code&amp;gt;get &amp;amp;lt;name&amp;amp;gt; &amp;amp;lt;option&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
        &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
        You can &amp;lt;i&amp;gt;get&amp;lt;/i&amp;gt; the value of any of the options described in &lt;br /&gt;
        &amp;lt;a href=&amp;quot;#Helloset&amp;quot;&amp;gt;paragraph &amp;quot;Set&amp;quot; above&amp;lt;/a&amp;gt;. See &lt;br /&gt;
        &amp;lt;a href=&amp;quot;http://fhem.de/commandref.html#get&amp;quot;&amp;gt;commandref#get&amp;lt;/a&amp;gt; for more info about &lt;br /&gt;
        the get command.&lt;br /&gt;
    &amp;lt;/ul&amp;gt;&lt;br /&gt;
    &amp;lt;br&amp;gt;&lt;br /&gt;
    &lt;br /&gt;
    &amp;lt;a name=&amp;quot;Helloattr&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
    &amp;lt;b&amp;gt;Attributes&amp;lt;/b&amp;gt;&lt;br /&gt;
    &amp;lt;ul&amp;gt;&lt;br /&gt;
        &amp;lt;code&amp;gt;attr &amp;amp;lt;name&amp;amp;gt; &amp;amp;lt;attribute&amp;amp;gt; &amp;amp;lt;value&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
        &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
        See &amp;lt;a href=&amp;quot;http://fhem.de/commandref.html#attr&amp;quot;&amp;gt;commandref#attr&amp;lt;/a&amp;gt; for more info about &lt;br /&gt;
        the attr command.&lt;br /&gt;
        &amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
        Attributes:&lt;br /&gt;
        &amp;lt;ul&amp;gt;&lt;br /&gt;
            &amp;lt;li&amp;gt;&amp;lt;i&amp;gt;formal&amp;lt;/i&amp;gt; no|yes&amp;lt;br&amp;gt;&lt;br /&gt;
                When you set formal to &amp;quot;yes&amp;quot;, all output of &amp;lt;i&amp;gt;get&amp;lt;/i&amp;gt; will be in a&lt;br /&gt;
                more formal language. Default is &amp;quot;no&amp;quot;.&lt;br /&gt;
            &amp;lt;/li&amp;gt;&lt;br /&gt;
        &amp;lt;/ul&amp;gt;&lt;br /&gt;
    &amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=end html&lt;br /&gt;
&lt;br /&gt;
=cut&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der HTML-Code zwischen den Tags &amp;lt;code&amp;gt;=pod&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;=cut&amp;lt;/code&amp;gt; dient zur Generierung der commandref.html. Der HTML-Inhalt wird automatisch beim Verteilen des Moduls im Rahmen des Update-Mechanismus aus jedem Modul extrahiert und daraus die Commandref in verschiedenen Sprachen erstellt. Eine detaillierte Beschreibung wie ein Commandref-Abschnitt in einem Modul definiert wird, siehe: [[Guidelines zur Dokumentation]]&lt;br /&gt;
&lt;br /&gt;
== Noch zu beschreiben ==&lt;br /&gt;
* DevIO&lt;br /&gt;
* AsyncOutputFn / asyncOutput&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Development]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=WMBUS&amp;diff=18148</id>
		<title>WMBUS</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=WMBUS&amp;diff=18148"/>
		<updated>2016-12-31T13:05:48Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: /* Bekannte Probleme */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=Dekodierung von Wireless M-Bus Nachrichten&lt;br /&gt;
|ModType=d&lt;br /&gt;
|ModForumArea=Sonstige Systeme&lt;br /&gt;
|ModTechName=36_WMBUS.pm&lt;br /&gt;
|ModOwner=kaihs&lt;br /&gt;
}}&lt;br /&gt;
[[WMBUS]] ist ein Modul zur Dekodierung von Wireless M-Bus Nachrichten. Solche Nachrichten werden z. B. von Zählern für Wasser, Wärme, Gas und Elektrizität ausgestrahlt.&lt;br /&gt;
Wireless M-Bus ist ein Standardprotokoll das von unterschiedlichen Herstellern unterstützt wird.&lt;br /&gt;
Das Protokoll unterstützt unterschiedliche Kodierungen des Funksignals, im wesentlichen den sogenannten S-Mode und den T-Mode. Der Empfänger (z. B. ein CUL) muss den selben Modus nutzen wie der Sender (der Zähler). &lt;br /&gt;
Wireless M-Bus unterstützt optional die Verschlüsselung der Daten per AES.&lt;br /&gt;
Die von einem Zähler gesendeten Daten können sehr unterschiedlich sein und hängen u. a. vom Zählertyp und dessen Hersteller ab.&lt;br /&gt;
&lt;br /&gt;
== Voraussetzungen ==&lt;br /&gt;
Das Modul interpretiert nur die Nachrichten die von einen geeigneten Empfänger empfangen werden. Aktuell kann ein [[CUL]] und verwandte Geräte die die culfw[http://culfw.de/culfw.html] verwenden sowie ein Amber Wireless AMB8465M dafür verwendet werden. In der culfw muss die Unterstützung des WMBUS-Protokolls aktiviert sein (#define HAS_MBUS). Bei einem CUL mit der Hardwareversion V4 ist das nicht der Fall.&lt;br /&gt;
&lt;br /&gt;
Der CUL muss in fhem mittels Attribut rfmode=WMBus_S oder WMBus_T in den zum Zähler passenden Empfangsmodus versetzt werden.&lt;br /&gt;
&lt;br /&gt;
== Anwendung ==&lt;br /&gt;
Die Erzeugung des passenden Devices in fhem geschieht automatisch beim Empfang des ersten Datenpakets eines Zählers. Voraussetzung dafür ist, dass [[autocreate]] aktiv ist.&lt;br /&gt;
Alternativ kann ein Device manuell angelegt werden. Dazu wird der Hersteller, die Seriennummer, die Version und der Typ (Wasser, Gas, ...) des Zählers benötigt.&lt;br /&gt;
Sind die Daten verschlüsselt wird auch noch der passende Schlüssel benötigt um die Daten entschlüsseln zu können.&lt;br /&gt;
&lt;br /&gt;
== Anwendungsbeispiele ==&lt;br /&gt;
Ein per [[EnergyCam]] abgelesener Elektrizitätszähler sieht in fhem z. B. so aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 Internals: &lt;br /&gt;
   CUL_MBUS_MSGCNT 29 &lt;br /&gt;
   CUL_MBUS_RAWMSG b1944C4189985051701028A7D7A540000A00405FAD4080002FD08222C1295B8::-67.5 &lt;br /&gt;
   CUL_MBUS_RSSI -67.5 &lt;br /&gt;
   CUL_MBUS_TIME 2014-10-24 22:57:53 &lt;br /&gt;
   DEF        FFD 17058599 1 2 &lt;br /&gt;
   DeviceMedium Electricity &lt;br /&gt;
   DeviceType 2 &lt;br /&gt;
   IODev      CUL_MBUS &lt;br /&gt;
   IdentNumber 17058599 &lt;br /&gt;
   LASTInputDev CUL_MBUS &lt;br /&gt;
   MSGCNT     29 &lt;br /&gt;
   Manufacturer FFD &lt;br /&gt;
   NAME       WMBUS_FFD_17058599_1_2 &lt;br /&gt;
   NR         49 &lt;br /&gt;
   STATE      no errors &lt;br /&gt;
   TYPE       WMBUS &lt;br /&gt;
   Version    1 &lt;br /&gt;
   addr       FFD_17058599_1_2 &lt;br /&gt;
   Readings: &lt;br /&gt;
     2014-10-24 22:57:53   1_storage_no    0 &lt;br /&gt;
     2014-10-24 22:57:53   1_type          VIF_ENERGY_WATT &lt;br /&gt;
     2014-10-24 22:57:53   1_unit          Wh &lt;br /&gt;
     2014-10-24 22:57:53   1_value         57881000 &lt;br /&gt;
     2014-10-24 22:57:53   2_storage_no    0 &lt;br /&gt;
     2014-10-24 22:57:53   2_type          VIF_ACCESS_NO &lt;br /&gt;
     2014-10-24 22:57:53   2_unit &lt;br /&gt;
     2014-10-24 22:57:53   2_value         11298 &lt;br /&gt;
     2014-10-24 22:57:53   LQI             184 &lt;br /&gt;
     2014-10-24 22:57:53   RSSI            -67.5 &lt;br /&gt;
     2014-10-24 22:57:53   battery         ok &lt;br /&gt;
     2014-10-24 22:57:53   decryption_ok   1 &lt;br /&gt;
     2014-10-24 22:57:53   energy          57881 &lt;br /&gt;
     2014-10-24 22:57:53   is_encrypted    0 &lt;br /&gt;
     2014-10-24 22:57:53   state           no errors &lt;br /&gt;
     2014-10-24 22:57:53   unit            kWh &lt;br /&gt;
 Attributes: &lt;br /&gt;
   IODev      CUL_MBUS &lt;br /&gt;
   room       WMBUS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Bekannte Probleme ==&lt;br /&gt;
Obwohl Wireless M-Bus ein standardisiertes Protokoll ist, scheint sich kaum ein Hersteller vollständig daran zu halten bzw. verwendet sog. herstellerspezifische Felder um wichtige Daten zu verpacken.&lt;br /&gt;
Aus den bisher beobachteten Datenpaketen ergibt sich &lt;br /&gt;
* Qundis (Herstellerkürzel LSE) verwendet herstellerspezifische Datenblöcke für den eigentlichen Zählerstand&lt;br /&gt;
* Techem und Hydrometer verwenden ein undokumentiertes Datenformat (CI-Field A2)&lt;br /&gt;
:&#039;&#039;(Techem Heizkostenverteiler (CI-Field A0) können über das Modul [[TechemHKV]] ausgewertet werden)&#039;&#039;&lt;br /&gt;
* RWE SmartHome Powercontrol[http://www.rwe-smarthome.de/web/cms/de/1776202/smarthome/informieren/geraete/power-control/] sendet verschlüsselt und der Hersteller gibt nicht den vollständigen Schlüssel an[http://forum.fhem.de/index.php/topic,24517.msg315949.html#msg315949]&lt;br /&gt;
&lt;br /&gt;
Daher werden bisher erst die [[EnergyCam]] der Firma Q-loud und Zähler von Easymeter vollständig unterstützt.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Forumsthread [http://forum.fhem.de/index.php/topic,24517.0.html]&lt;br /&gt;
* Protokoll Beschreibung [http://oms-group.org/download4all/]&lt;br /&gt;
* Beschreibung des M-BUS Protokolls [http://www.m-bus.com/files/MBDOC48.PDF]&lt;br /&gt;
[[Kategorie:Energieverbrauchsmessung]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=EnergyCam&amp;diff=18147</id>
		<title>EnergyCam</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=EnergyCam&amp;diff=18147"/>
		<updated>2016-12-31T13:04:06Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: Fastforward hat die Herstellung eingestellt und an die Q-loud abgegeben&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Hardware&lt;br /&gt;
|Bild=EnergyCam.jpg&lt;br /&gt;
|Bildbeschreibung=EnergyCam mit externer Batterie und externer Antenne montiert auf einem Ferraris-Zähler&lt;br /&gt;
|HWProtocol=Wireless M-Bus &lt;br /&gt;
|HWType=Sensor&lt;br /&gt;
|HWCategory=Energieverbrauchsmessung&lt;br /&gt;
|HWComm=Funk 868MHz, ModBus&lt;br /&gt;
|HWChannels=N/A&lt;br /&gt;
|HWVoltage=3,0 - 3,6V&lt;br /&gt;
|HWPowerConsumption=&amp;lt;0,2W&lt;br /&gt;
|HWPoweredBy=interne CR2450 oder externe Batterie, USB&lt;br /&gt;
|HWSize=B x H x T 48,00 x 55,50 x 15,50 mm&lt;br /&gt;
|HWDeviceFHEM=WMBUS&lt;br /&gt;
|HWManufacturer=Q-loud&lt;br /&gt;
}}&lt;br /&gt;
Die [[EnergyCam]] ist ein Zähleraufsatz der den Zählerstand erfasst und dann drahtlos (Wireless M-Bus) oder drahtgebunden (Modbus) weiterleitet.&lt;br /&gt;
== Features ==&lt;br /&gt;
Eine EnergyCam erfasst optisch den Zählerstand eines herkömmlichen Zählers für Elektrizität, Gas oder Wasser und wandelt diesen per optischer Zeichenerkennung (OCR) in einen Zahlenwert um. Dieser Wert wird dann zyklisch versandt und kann vom Empfänger ausgewertet werden.&lt;br /&gt;
&lt;br /&gt;
Die EnergyCam wird dazu auf den Zähler aufgeklebt. Das Gerät unterstützt dabei durch eine Anzeige die Montage in der richtigen Position. Für die Verwendung mit Gas- und Wasserzählern sind noch zusätzliche Adapter erforderlich.&lt;br /&gt;
Es gibt die EnergyCam sowohl mit interner als auch externer Antenne sowie mit interner und externer Energieversorgung.&lt;br /&gt;
Der aktuelle Zählerstand kann bei Bedarf auch direkt am Gerät abgelesen werden und wird auf dem internen Display dargestellt. &lt;br /&gt;
&lt;br /&gt;
== Hinweise zum Betrieb mit FHEM ==&lt;br /&gt;
Die EnergyCam im Wireless M-Bus Modus wird vom Modul [[WMBUS]] vollständig unterstützt. Das Herstellerkürzel ist FFD.&lt;br /&gt;
&lt;br /&gt;
== Bekannte Probleme ==&lt;br /&gt;
Die Erfassung der Zählerstands erfolgt von schräg unterhalb des eigentlichen Zählwerks. Daher darf dieser Bereich nicht durch Aufdruck oder ähnliches die freie Sicht auf das Zählwerk behindern, sonst ist keine fehlerfreie Erfassung möglich.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Herstellerseite [https://q-loud.de/solucon/solucon-hardware/]&lt;br /&gt;
[[Kategorie:Energieverbrauchsmessung]]&lt;br /&gt;
[[Kategorie:Other Components]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=WMBUS&amp;diff=17238</id>
		<title>WMBUS</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=WMBUS&amp;diff=17238"/>
		<updated>2016-11-13T17:33:31Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: Amber Wireless AMB8465M&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=Dekodierung von Wireless M-Bus Nachrichten&lt;br /&gt;
|ModType=d&lt;br /&gt;
|ModForumArea=Sonstige Systeme&lt;br /&gt;
|ModTechName=36_WMBUS.pm&lt;br /&gt;
|ModOwner=kaihs&lt;br /&gt;
}}&lt;br /&gt;
[[WMBUS]] ist ein Modul zur Dekodierung von Wireless M-Bus Nachrichten. Solche Nachrichten werden z. B. von Zählern für Wasser, Wärme, Gas und Elektrizität ausgestrahlt.&lt;br /&gt;
Wireless M-Bus ist ein Standardprotokoll das von unterschiedlichen Herstellern unterstützt wird.&lt;br /&gt;
Das Protokoll unterstützt unterschiedliche Kodierungen des Funksignals, im wesentlichen den sogenannten S-Mode und den T-Mode. Der Empfänger (z. B. ein CUL) muss den selben Modus nutzen wie der Sender (der Zähler). &lt;br /&gt;
Wireless M-Bus unterstützt optional die Verschlüsselung der Daten per AES.&lt;br /&gt;
Die von einem Zähler gesendeten Daten können sehr unterschiedlich sein und hängen u. a. vom Zählertyp und dessen Hersteller ab.&lt;br /&gt;
&lt;br /&gt;
== Voraussetzungen ==&lt;br /&gt;
Das Modul interpretiert nur die Nachrichten die von einen geeigneten Empfänger empfangen werden. Aktuell kann ein [[CUL]] und verwandte Geräte die die culfw[http://culfw.de/culfw.html] verwenden sowie ein Amber Wireless AMB8465M dafür verwendet werden. In der culfw muss die Unterstützung des WMBUS-Protokolls aktiviert sein (#define HAS_MBUS). Bei einem CUL mit der Hardwareversion V4 ist das nicht der Fall.&lt;br /&gt;
&lt;br /&gt;
Der CUL muss in fhem mittels Attribut rfmode=WMBus_S oder WMBus_T in den zum Zähler passenden Empfangsmodus versetzt werden.&lt;br /&gt;
&lt;br /&gt;
== Anwendung ==&lt;br /&gt;
Die Erzeugung des passenden Devices in fhem geschieht automatisch beim Empfang des ersten Datenpakets eines Zählers. Voraussetzung dafür ist, dass [[autocreate]] aktiv ist.&lt;br /&gt;
Alternativ kann ein Device manuell angelegt werden. Dazu wird der Hersteller, die Seriennummer, die Version und der Typ (Wasser, Gas, ...) des Zählers benötigt.&lt;br /&gt;
Sind die Daten verschlüsselt wird auch noch der passende Schlüssel benötigt um die Daten entschlüsseln zu können.&lt;br /&gt;
&lt;br /&gt;
== Anwendungsbeispiele ==&lt;br /&gt;
Ein per [[EnergyCam]] abgelesener Elektrizitätszähler sieht in fhem z. B. so aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 Internals: &lt;br /&gt;
   CUL_MBUS_MSGCNT 29 &lt;br /&gt;
   CUL_MBUS_RAWMSG b1944C4189985051701028A7D7A540000A00405FAD4080002FD08222C1295B8::-67.5 &lt;br /&gt;
   CUL_MBUS_RSSI -67.5 &lt;br /&gt;
   CUL_MBUS_TIME 2014-10-24 22:57:53 &lt;br /&gt;
   DEF        FFD 17058599 1 2 &lt;br /&gt;
   DeviceMedium Electricity &lt;br /&gt;
   DeviceType 2 &lt;br /&gt;
   IODev      CUL_MBUS &lt;br /&gt;
   IdentNumber 17058599 &lt;br /&gt;
   LASTInputDev CUL_MBUS &lt;br /&gt;
   MSGCNT     29 &lt;br /&gt;
   Manufacturer FFD &lt;br /&gt;
   NAME       WMBUS_FFD_17058599_1_2 &lt;br /&gt;
   NR         49 &lt;br /&gt;
   STATE      no errors &lt;br /&gt;
   TYPE       WMBUS &lt;br /&gt;
   Version    1 &lt;br /&gt;
   addr       FFD_17058599_1_2 &lt;br /&gt;
   Readings: &lt;br /&gt;
     2014-10-24 22:57:53   1_storage_no    0 &lt;br /&gt;
     2014-10-24 22:57:53   1_type          VIF_ENERGY_WATT &lt;br /&gt;
     2014-10-24 22:57:53   1_unit          Wh &lt;br /&gt;
     2014-10-24 22:57:53   1_value         57881000 &lt;br /&gt;
     2014-10-24 22:57:53   2_storage_no    0 &lt;br /&gt;
     2014-10-24 22:57:53   2_type          VIF_ACCESS_NO &lt;br /&gt;
     2014-10-24 22:57:53   2_unit &lt;br /&gt;
     2014-10-24 22:57:53   2_value         11298 &lt;br /&gt;
     2014-10-24 22:57:53   LQI             184 &lt;br /&gt;
     2014-10-24 22:57:53   RSSI            -67.5 &lt;br /&gt;
     2014-10-24 22:57:53   battery         ok &lt;br /&gt;
     2014-10-24 22:57:53   decryption_ok   1 &lt;br /&gt;
     2014-10-24 22:57:53   energy          57881 &lt;br /&gt;
     2014-10-24 22:57:53   is_encrypted    0 &lt;br /&gt;
     2014-10-24 22:57:53   state           no errors &lt;br /&gt;
     2014-10-24 22:57:53   unit            kWh &lt;br /&gt;
 Attributes: &lt;br /&gt;
   IODev      CUL_MBUS &lt;br /&gt;
   room       WMBUS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Bekannte Probleme ==&lt;br /&gt;
Obwohl Wireless M-Bus ein standardisiertes Protokoll ist, scheint sich kaum ein Hersteller vollständig daran zu halten bzw. verwendet sog. herstellerspezifische Felder um wichtige Daten zu verpacken.&lt;br /&gt;
Aus den bisher beobachteten Datenpaketen ergibt sich &lt;br /&gt;
* Qundis (Herstellerkürzel LSE) verwendet herstellerspezifische Datenblöcke für den eigentlichen Zählerstand&lt;br /&gt;
* Techem und Hydrometer verwenden ein undokumentiertes Datenformat (CI-Field A2)&lt;br /&gt;
:&#039;&#039;(Techem Heizkostenverteiler (CI-Field A0) können über das Modul [[TechemHKV]] ausgewertet werden)&#039;&#039;&lt;br /&gt;
* RWE SmartHome Powercontrol[http://www.rwe-smarthome.de/web/cms/de/1776202/smarthome/informieren/geraete/power-control/] sendet verschlüsselt und der Hersteller gibt nicht den vollständigen Schlüssel an[http://forum.fhem.de/index.php/topic,24517.msg315949.html#msg315949]&lt;br /&gt;
&lt;br /&gt;
Daher werden bisher erst die [[EnergyCam]] der Fast Forward AG und Zähler von Easymeter vollständig unterstützt.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Forumsthread [http://forum.fhem.de/index.php/topic,24517.0.html]&lt;br /&gt;
* Protokoll Beschreibung [http://oms-group.org/download4all/]&lt;br /&gt;
* Beschreibung des M-BUS Protokolls [http://www.m-bus.com/files/MBDOC48.PDF]&lt;br /&gt;
[[Kategorie:Energieverbrauchsmessung]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=HM-LC-Sw1PBU-FM_Alternative_Firmware_am_Raspi_bauen_u._flashen&amp;diff=17233</id>
		<title>HM-LC-Sw1PBU-FM Alternative Firmware am Raspi bauen u. flashen</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=HM-LC-Sw1PBU-FM_Alternative_Firmware_am_Raspi_bauen_u._flashen&amp;diff=17233"/>
		<updated>2016-11-13T16:53:42Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: Typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= 1fach Schaltaktor HM-LC-Sw1PBU-FM mit alternativer Firmware =&lt;br /&gt;
* Sinn und Zweck: Der Schalter bietet mit der alternativen Firmware die Möglichkeit ihn in Wechselschaltungen zu integrieren. In einer normalen Wechselschaltung ist es nicht möglich, den Schaltzustand der Lampe zu erkennen. Das Funktioniert nur wenn der Schaltzustand(Leistungsaufnahme) von Funkschalter erkannt werden kann.&lt;br /&gt;
* Vorwort: Dieser Artikel ist eigentlich nur eine Zusammenfassung dessen, was bereits in [[HM-LC-Sw1PBU-FM_Alternative_Firmware#Bootloader_flashen | HM-LC-Sw1PBU-FM_Alternative_Firmware#Bootloader_flashen]] steht! Dort stammen auch alle Tools, Hilfsprogramme und Informationen her.&lt;br /&gt;
Ich habe lediglich alles auf das Flashen am Raspberry Pi ausgerichtet. Mein Dank gilt den Programmierern der Firmware und allen Leuten, die das Projekt mit- und weiterentwickelt haben.&lt;br /&gt;
&lt;br /&gt;
== Vorbereitung ==&lt;br /&gt;
* Windows 7 Desktop-Rechner mit Browser, Text-Editor, puTTY und WinSCP. Man kann zwar alle Schritte auch direkt auf dem Raspi durchführen - ich finde den Windows-Rechner aber praktischer&lt;br /&gt;
* Raspbian Jessie mit Pixel downloaden [https://www.raspberrypi.org/downloads/raspbian/]. Kernel 4.4 Release 2016 09 23&lt;br /&gt;
** Mit WinDiskImager auf min. 8GB SD-Karte spielen, s. auch [http://www.raspberry-projects.com/pi/pi-operating-systems/win32diskimager]&lt;br /&gt;
* Raspberry Pi 2B&lt;br /&gt;
** Die Pins des Raspi müssen nach folgendem Schema mit den Lötpads des HM-LC-Sw1PBU-FM verbunden werden. Die Messpunkte (MP) befinden sich auf der inneren, festgeschraubten, Platine des HM-Schalters&lt;br /&gt;
 [[Raspberry Pi|Raspberry]] PIN | Beschreibung | HM-LC-Sw1PBU-FM&lt;br /&gt;
 --------------|--------------|----------------&lt;br /&gt;
    Pin #17    |    3,3V      |    MP2&lt;br /&gt;
    Pin #19    |    MOSI      |    MP4&lt;br /&gt;
    Pin #21    |    MISO      |    MP5&lt;br /&gt;
    Pin #23    |    SCLK      |    MP6&lt;br /&gt;
    Pin #24    |    Reset     |    MP3&lt;br /&gt;
    Pin #25    |    GND       |    MP15&lt;br /&gt;
** Hinweis: Den Schalter während des gesamten Prozesses &#039;&#039;&#039;nicht mit 230V verbinden&#039;&#039;&#039;. Während des gesamtem Flash-Vorgangs kann die Spannungsvorsorgung aus dem Raspi genutzt werden&lt;br /&gt;
* Nachdem Raspbian sich installiert hat, geht man auf die Linux-Konsole. Entweder direkt oder per puTTY über SSH. Auf dem Raspi arbeite ich gerne als User root, deswegen vergebe ich diesem ein Passwort:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo passwd root&lt;br /&gt;
// user root werden&lt;br /&gt;
su - root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Raspi OS updaten&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt-get update &amp;amp;&amp;amp; apt-get upgrade &amp;amp;&amp;amp; apt-get dist-upgrade&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Software installieren: C-Compiler, arduino-IDE&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt-get install arduino gcc-avr&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* (Optional) Über &#039;&#039;raspi-config -&amp;gt; Internationialisation Options&#039;&#039; Keyboard-Layout, Locale, Timezone anpassen&lt;br /&gt;
* Über &#039;&#039;raspi-config -&amp;gt; Advanced Options&#039;&#039; SPI, Serial, I2C ausschalten (falls aktiv)&lt;br /&gt;
* reboot&lt;br /&gt;
* Verzeichnis für Downloads auf dem Raspi erstellen und dorthin wechseln&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir /root/hm_switch&lt;br /&gt;
mkdir /root/hm_switch/flash&lt;br /&gt;
cd /root/hm_switch&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Bootloader-Umgebung herunterladen&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git clone https://github.com/jabdoa2/Asksin_OTA_Bootloader&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Firmware herunterladen&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git clone https://github.com/jabdoa2/Asksin_HM_LC_Sw1PBU_FM&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Dateien aus [https://seafile.partec.org/d/b6590a5a45/] herunterladen und auf dem Raspi in&#039;s erstellte Verzeichnis &#039;&#039;/root/hm_switch&#039;&#039; kopieren. Da ich nicht weiß, wie man per wget Dateien eines Cloud-Servers auf einer Linux-Maschine kopiert, führe ich diesen Vorgang mit WinSCP durch.&lt;br /&gt;
** Das Modul 99_Asksin_HM_LC_Sw1PBU_FM_CustomFW.pm muss in die fhem-Installation (/opt/fhem/FHEM) kopiert werden. Ansonsten wird der Schalter beim &#039;&#039;&#039;Anlernen nicht erkannt&#039;&#039;&#039;&lt;br /&gt;
* Da die Programming-Software aus dem original Repository nicht verwendet werden kann, muss die Version aus dem Dowload installiert werden&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dpkg -i avrdude_5.10-4_armhf.deb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* In der .conf steht die Definition der Anschlüsse für den Raspi. Diese entpacken und nach /etc kopieren&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gunzip avrdude.conf.gz &amp;amp;&amp;amp; cp avrdude.conf /etc/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Arduino-IDE einrichten /Firmware bauen==&lt;br /&gt;
* Die IDE wird zum späteren Kompilieren der Firmware benötigt - es ist keine Arduino-Hardware erforderlich!&lt;br /&gt;
* Build-Pfad für Arduino-IDE erstellen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir /home/pi/build &amp;amp;&amp;amp; chmod -R 777 /home/pi/build&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* In den Ordner &#039;&#039;/usr/share/arduino/hardware&#039;&#039; wechseln und Hardware-Board für den ATMega644 laden &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/share/arduino/hardware&lt;br /&gt;
git clone https://github.com/jabdoa2/jabduino&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Um alle Pfade und Dateien zu erzeugen, muss die Arduino-IDE aufgerufen und anschließend direkt wieder geschlossen werden. Das kann man in der grafischen Umgebung des Raspis, oder über ein entferntes X-Terminal tun.&lt;br /&gt;
* In manchen Adruino-IDE Umgebungen werden Builds gelöscht, bevor sie auf die Hardware gespielt werden. Das muss verhindert werden! Bei Raspbian Jessie und dem User pi befinden sich die Voreinstellungen der IDE in &#039;&#039;/home/pi/.arduino/preferences.txt&#039;&#039;. Über die Konsole dort folgende Änderungen machen, bzw. Einträge hinzufügen&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
build.path=/home/pi/build&lt;br /&gt;
...&lt;br /&gt;
export.delete_target_folder=false&lt;br /&gt;
...&lt;br /&gt;
preproc.save_build_files=true&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Firmware-Quellen in den Sketchbook-Ordner von User &#039;&#039;pi&#039;&#039; kopieren und Rechte für alle setzen&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp -R /root/hm_switch/Asksin_HM_LC_Sw1PBU_FM/ /home/pi/sketchbook/ &amp;amp;&amp;amp; chmod -R 777 /home/pi/sketchbook/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Wieder in die grafische IDE wechseln&lt;br /&gt;
** &#039;&#039;Tools -&amp;gt; Board -&amp;gt;&#039;&#039; &amp;quot;Jabduino ATmega644A&amp;quot; auswählen &lt;br /&gt;
** &#039;&#039;File -&amp;gt; Sketchbook -&amp;gt; &#039;&#039; &amp;quot;Asksin_HM_LC_Sw1PBU_FM&amp;quot; öffnen&lt;br /&gt;
** In der Datei Asksin_HM_LC_Sw1PBU_FM den Wert in Zeile 64 eventuell &amp;quot;const unsigned long minImpulsLength = 5000;&amp;quot; ändern. Der dort eingetragene Wert gilt als Schwellwert, wann der Schalter erkennen soll, dass ein angeschlossener Wechselschalter gedrückt wurde und somit erkannt wird, dass Strom fließt. &lt;br /&gt;
** In der Datei &#039;&#039;Register.h&#039;&#039; in Zeile 22 den Wert von HMID[3] ändern. &lt;br /&gt;
Zusätzlich kann die eigene Zentrale bereits als Default-Wert in den Schalter eingetragen werden. Dadurch entfällt ein unter Umständen notwendiges Peering. Dafür muss die Zeile 347 von //#define firstLoad&#039; in &#039;#define firstLoad&#039; geändert werden In den Zeilen 354 bis 356 die Werte für die FHEM-Zentral-ID einfügen (Reading: D-HMIdOriginal 2CC71D) reg.ch_0.pairCentral[0] = 0x2C; reg.ch_0.pairCentral[1] = 0xC7; reg.ch_0.pairCentral[2] = 0x1D; Auch andere Default-Werte wie Peerings und Schaltverhalten können an dieser Stelle verändert werden. Sollte das nicht gewünscht sein, sind diese Zeilen entweder auszukommentieren oder einfach zu löschen. &lt;br /&gt;
** Beispiel (Auszug aus Register.h mit Zeilenangaben)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;16&amp;gt;/* Serial ID       10 byte */  &#039;K&#039;,&#039;E&#039;,&#039;Q&#039;,&#039;0&#039;,&#039;0&#039;,&#039;0&#039;,&#039;0&#039;,&#039;0&#039;,&#039;0&#039;,&#039;7&#039;, // serial ID, needed for pairing&lt;br /&gt;
&amp;lt;22&amp;gt;       const uint8_t  HMID[3]     = { 0x08, 0x15, 0x07 };     // 081507&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
** Die beiden geänderten Dateien speichern und mit &#039;&#039;Sketch -&amp;gt; Überprüfen / Kompilieren&#039;&#039; kompilieren. Im unteren Fenster auf Fehlermeldungen achten!&lt;br /&gt;
** Wenn dies funktioniert hat, sollte im Ordner &#039;&#039;/home/pi/build&#039;&#039; die Datei &#039;&#039;Asksin_HM_LC_Sw1PBU_FM.cpp.hex&#039;&#039; mit aktuellem Datum erzeugt worden sein.&lt;br /&gt;
&lt;br /&gt;
== Bootloader ==&lt;br /&gt;
* Datei /root/hm_switch/Asksin_OTA_Bootloader/devices/HM-LC-Sw1PBU-FM.h editieren und dabei Seriennummer, HMID und die Typ setzen. Seriennummer und HMID müssen in eurer Umgebung eindeutig sein, Typ ist: &#039;&#039;&#039;0xF0A9&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
nano /root/hm_switch/Asksin_OTA_Bootloader/devices/HM-LC-Sw1PBU-FM.h&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
** Beispiel: HMID -&amp;gt; 081507, Seriennummer: KEQ0000007&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/ The model type (not used from bootloader)&lt;br /&gt;
#define HM_TYPE              0xF0, 0xA9&lt;br /&gt;
// 10 bytes serial number. Must be unique for each device&lt;br /&gt;
#define HM_SERIAL            &#039;K&#039;, &#039;E&#039;, &#039;Q&#039;, &#039;0&#039;, &#039;0&#039;, &#039;0&#039;, &#039;0&#039;, &#039;0&#039;, &#039;0&#039;, &#039;7&#039;&lt;br /&gt;
// 3 bytes The device address (hm_id)&lt;br /&gt;
#define HM_ID                0x08, 0x15, 0x07&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Eine Verzeichnisebene höher und Bootloader bauen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /root/hm_switch/Asksin_OTA_Bootloader/&lt;br /&gt;
make clean HM_LC_Sw1PBU_FM_8k&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Dabei sollte die Datei &#039;&#039;bootloader_HM-LC-Sw1PBU-FM.hex&#039;&#039; herauskommen. Diese wird später auf den Schalter geflasht&lt;br /&gt;
&lt;br /&gt;
== Flashen ==&lt;br /&gt;
* Erzeugte Bootloader-Datei und Firmware in ein Verzeichnis kopieren:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /home/pi/build/Asksin_HM_LC_Sw1PBU_FM.cpp.hex /root/hm_switch/flash/firmware.hex &amp;amp;&amp;amp; cp /root/hm_switch/Asksin_OTA_Bootloader/Bootloader-AskSin-OTA-HM_LC_Sw1PBU_FM_8k.hex /root/hm_switch/flash/bootloader.hex&lt;br /&gt;
cd /root/hm_switch/flash/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Hinweis: In älteren Beschreibungen findet man häufig die Ziel-Plattform m644. Diese Unterscheidet sich praktisch in der Stromaufnahme des Chips, führt beim avrdude aber zu &#039;&#039;&#039;Fehlermeldungen&#039;&#039;&#039;, deshalb auf &#039;&#039;&#039;m6444p&#039;&#039;&#039; achten&lt;br /&gt;
* &#039;&#039;&#039;Fuses&#039;&#039;&#039; setzen&lt;br /&gt;
&#039;&#039;avrdude -p m644p -P gpio -c gpio -U lfuse:w:0xFD:m -U hfuse:w:0xD8:m -U lock:w:0x3F:m&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
avrdude: AVR device initialized and ready to accept instructions&lt;br /&gt;
Reading | ################################################## | 100% 0.00s&lt;br /&gt;
avrdude: Device signature = 0x1e960a&lt;br /&gt;
avrdude: reading input file &amp;quot;0xFD&amp;quot;&lt;br /&gt;
avrdude: writing lfuse (1 bytes):&lt;br /&gt;
Writing | ################################################## | 100% 0.00s&lt;br /&gt;
avrdude: 1 bytes of lfuse written&lt;br /&gt;
avrdude: verifying lfuse memory against 0xFD:&lt;br /&gt;
avrdude: load data lfuse data from input file 0xFD:&lt;br /&gt;
avrdude: input file 0xFD contains 1 bytes&lt;br /&gt;
avrdude: reading on-chip lfuse data:&lt;br /&gt;
Reading | ################################################## | 100% 0.00s&lt;br /&gt;
avrdude: verifying ...&lt;br /&gt;
avrdude: 1 bytes of lfuse verified&lt;br /&gt;
avrdude: reading input file &amp;quot;0xD8&amp;quot;&lt;br /&gt;
avrdude: writing hfuse (1 bytes):&lt;br /&gt;
Writing | ################################################## | 100% 0.00s&lt;br /&gt;
avrdude: 1 bytes of hfuse written&lt;br /&gt;
avrdude: verifying hfuse memory against 0xD8:&lt;br /&gt;
avrdude: load data hfuse data from input file 0xD8:&lt;br /&gt;
avrdude: input file 0xD8 contains 1 bytes&lt;br /&gt;
avrdude: reading on-chip hfuse data:&lt;br /&gt;
Reading | ################################################## | 100% 0.00s&lt;br /&gt;
avrdude: verifying ...&lt;br /&gt;
avrdude: 1 bytes of hfuse verified&lt;br /&gt;
avrdude: safemode: Fuses OK&lt;br /&gt;
avrdude done.  Thank you.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Bootloader&#039;&#039;&#039; flashen&lt;br /&gt;
&#039;&#039;avrdude -p m644p -P gpio -c gpio -U flash:w:bootloader.hex&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
avrdude: AVR device initialized and ready to accept instructions&lt;br /&gt;
Reading | ################################################## | 100% 0.00s&lt;br /&gt;
avrdude: Device signature = 0x1e960a&lt;br /&gt;
avrdude: NOTE: FLASH memory has been specified, an erase cycle will be performed&lt;br /&gt;
         To disable this feature, specify the -D option.&lt;br /&gt;
avrdude: erasing chip&lt;br /&gt;
avrdude: reading input file &amp;quot;bootloader_HM-LC-Sw1PBU-FM.hex&amp;quot;&lt;br /&gt;
avrdude: input file bootloader_HM-LC-Sw1PBU-FM.hex auto detected as Intel Hex&lt;br /&gt;
avrdude: writing flash (61372 bytes):&lt;br /&gt;
Writing | ################################################## | 100% 30.86s&lt;br /&gt;
avrdude: 61372 bytes of flash written&lt;br /&gt;
avrdude: verifying flash memory against bootloader_HM-LC-Sw1PBU-FM.hex:&lt;br /&gt;
avrdude: load data flash data from input file bootloader_HM-LC-Sw1PBU-FM.hex:&lt;br /&gt;
avrdude: input file bootloader_HM-LC-Sw1PBU-FM.hex auto detected as Intel Hex&lt;br /&gt;
avrdude: input file bootloader_HM-LC-Sw1PBU-FM.hex contains 61372 bytes&lt;br /&gt;
avrdude: reading on-chip flash data:&lt;br /&gt;
Reading | ################################################## | 100% 28.95s&lt;br /&gt;
avrdude: verifying ...&lt;br /&gt;
avrdude: 61372 bytes of flash verified&lt;br /&gt;
avrdude: safemode: Fuses OK&lt;br /&gt;
avrdude done.  Thank you.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Firmware&#039;&#039;&#039; flashen (aus der Arduino-IDE)&lt;br /&gt;
&#039;&#039;avrdude -p m644p -P gpio -c gpio -U flash:w:firmware.hex&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
avrdude: AVR device initialized and ready to accept instructions&lt;br /&gt;
Reading | ################################################## | 100% 0.00s&lt;br /&gt;
avrdude: Device signature = 0x1e960a&lt;br /&gt;
avrdude: NOTE: FLASH memory has been specified, an erase cycle will be performed&lt;br /&gt;
         To disable this feature, specify the -D option.&lt;br /&gt;
avrdude: erasing chip&lt;br /&gt;
avrdude: reading input file &amp;quot;Asksin_HM_LC_Sw1PBU_FM.cpp.hex&amp;quot;&lt;br /&gt;
avrdude: input file Asksin_HM_LC_Sw1PBU_FM.cpp.hex auto detected as Intel Hex&lt;br /&gt;
avrdude: writing flash (19042 bytes):&lt;br /&gt;
Writing | ################################################## | 100% 9.79s&lt;br /&gt;
avrdude: 19042 bytes of flash written&lt;br /&gt;
avrdude: verifying flash memory against Asksin_HM_LC_Sw1PBU_FM.cpp.hex:&lt;br /&gt;
avrdude: load data flash data from input file Asksin_HM_LC_Sw1PBU_FM.cpp.hex:&lt;br /&gt;
avrdude: input file Asksin_HM_LC_Sw1PBU_FM.cpp.hex auto detected as Intel Hex&lt;br /&gt;
avrdude: input file Asksin_HM_LC_Sw1PBU_FM.cpp.hex contains 19042 bytes&lt;br /&gt;
avrdude: reading on-chip flash data:&lt;br /&gt;
Reading | ################################################## | 100% 9.28s&lt;br /&gt;
avrdude: verifying ...&lt;br /&gt;
avrdude: 19042 bytes of flash verified&lt;br /&gt;
avrdude: safemode: Fuses OK&lt;br /&gt;
avrdude done.  Thank you.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HomeMatic Components]]&lt;br /&gt;
[[Kategorie:Schalter (Sender)]]&lt;br /&gt;
[[Kategorie:Schalter (Empfänger)]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=HM-LC-Sw1PBU-FM_Alternative_Firmware_am_Raspi_bauen_u._flashen&amp;diff=17232</id>
		<title>HM-LC-Sw1PBU-FM Alternative Firmware am Raspi bauen u. flashen</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=HM-LC-Sw1PBU-FM_Alternative_Firmware_am_Raspi_bauen_u._flashen&amp;diff=17232"/>
		<updated>2016-11-13T16:53:16Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: Typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= 1fach Schaltaktor HM-LC-Sw1PBU-FM mit alternativer Firmware =&lt;br /&gt;
* Sinn und Zweck: Der Schalter bietet mit der alternativen Firmware die Möglichkeit ihn in Wechselschaltungen zu integrieren. In einer normalen Wechselschaltung ist es nicht möglich, den Schaltzustand der Lampe zu erkennen. Das Funktioniert nur wenn der Schaltzustand(Leistungsaufnahme) von Funkschalter erkannt werden kann.&lt;br /&gt;
* Vorwort: Dieser Artikel ist eigentlich nur eine Zusammenfassung dessen, was bereits in [[HM-LC-Sw1PBU-FM_Alternative_Firmware#Bootloader_flashen | HM-LC-Sw1PBU-FM_Alternative_Firmware#Bootloader_flashen]] steht! Dort stammen auch alle Tools, Hilfsprogramme und Informationen her.&lt;br /&gt;
Ich habe ledigleich alles auf das Flashen am Raspberry Pi ausgerichtet. Mein Dank gilt den Programmierern der Firmware und allen Leuten, die das Projekt mit- und weiterentwickelt haben.&lt;br /&gt;
&lt;br /&gt;
== Vorbereitung ==&lt;br /&gt;
* Windows 7 Desktop-Rechner mit Browser, Text-Editor, puTTY und WinSCP. Man kann zwar alle Schritte auch direkt auf dem Raspi durchführen - ich finde den Windows-Rechner aber praktischer&lt;br /&gt;
* Raspbian Jessie mit Pixel downloaden [https://www.raspberrypi.org/downloads/raspbian/]. Kernel 4.4 Release 2016 09 23&lt;br /&gt;
** Mit WinDiskImager auf min. 8GB SD-Karte spielen, s. auch [http://www.raspberry-projects.com/pi/pi-operating-systems/win32diskimager]&lt;br /&gt;
* Raspberry Pi 2B&lt;br /&gt;
** Die Pins des Raspi müssen nach folgendem Schema mit den Lötpads des HM-LC-Sw1PBU-FM verbunden werden. Die Messpunkte (MP) befinden sich auf der inneren, festgeschraubten, Platine des HM-Schalters&lt;br /&gt;
 [[Raspberry Pi|Raspberry]] PIN | Beschreibung | HM-LC-Sw1PBU-FM&lt;br /&gt;
 --------------|--------------|----------------&lt;br /&gt;
    Pin #17    |    3,3V      |    MP2&lt;br /&gt;
    Pin #19    |    MOSI      |    MP4&lt;br /&gt;
    Pin #21    |    MISO      |    MP5&lt;br /&gt;
    Pin #23    |    SCLK      |    MP6&lt;br /&gt;
    Pin #24    |    Reset     |    MP3&lt;br /&gt;
    Pin #25    |    GND       |    MP15&lt;br /&gt;
** Hinweis: Den Schalter während des gesamten Prozesses &#039;&#039;&#039;nicht mit 230V verbinden&#039;&#039;&#039;. Während des gesamtem Flash-Vorgangs kann die Spannungsvorsorgung aus dem Raspi genutzt werden&lt;br /&gt;
* Nachdem Raspbian sich installiert hat, geht man auf die Linux-Konsole. Entweder direkt oder per puTTY über SSH. Auf dem Raspi arbeite ich gerne als User root, deswegen vergebe ich diesem ein Passwort:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sudo passwd root&lt;br /&gt;
// user root werden&lt;br /&gt;
su - root&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Raspi OS updaten&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt-get update &amp;amp;&amp;amp; apt-get upgrade &amp;amp;&amp;amp; apt-get dist-upgrade&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Software installieren: C-Compiler, arduino-IDE&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt-get install arduino gcc-avr&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* (Optional) Über &#039;&#039;raspi-config -&amp;gt; Internationialisation Options&#039;&#039; Keyboard-Layout, Locale, Timezone anpassen&lt;br /&gt;
* Über &#039;&#039;raspi-config -&amp;gt; Advanced Options&#039;&#039; SPI, Serial, I2C ausschalten (falls aktiv)&lt;br /&gt;
* reboot&lt;br /&gt;
* Verzeichnis für Downloads auf dem Raspi erstellen und dorthin wechseln&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir /root/hm_switch&lt;br /&gt;
mkdir /root/hm_switch/flash&lt;br /&gt;
cd /root/hm_switch&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Bootloader-Umgebung herunterladen&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git clone https://github.com/jabdoa2/Asksin_OTA_Bootloader&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Firmware herunterladen&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git clone https://github.com/jabdoa2/Asksin_HM_LC_Sw1PBU_FM&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Dateien aus [https://seafile.partec.org/d/b6590a5a45/] herunterladen und auf dem Raspi in&#039;s erstellte Verzeichnis &#039;&#039;/root/hm_switch&#039;&#039; kopieren. Da ich nicht weiß, wie man per wget Dateien eines Cloud-Servers auf einer Linux-Maschine kopiert, führe ich diesen Vorgang mit WinSCP durch.&lt;br /&gt;
** Das Modul 99_Asksin_HM_LC_Sw1PBU_FM_CustomFW.pm muss in die fhem-Installation (/opt/fhem/FHEM) kopiert werden. Ansonsten wird der Schalter beim &#039;&#039;&#039;Anlernen nicht erkannt&#039;&#039;&#039;&lt;br /&gt;
* Da die Programming-Software aus dem original Repository nicht verwendet werden kann, muss die Version aus dem Dowload installiert werden&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
dpkg -i avrdude_5.10-4_armhf.deb&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* In der .conf steht die Definition der Anschlüsse für den Raspi. Diese entpacken und nach /etc kopieren&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
gunzip avrdude.conf.gz &amp;amp;&amp;amp; cp avrdude.conf /etc/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Arduino-IDE einrichten /Firmware bauen==&lt;br /&gt;
* Die IDE wird zum späteren Kompilieren der Firmware benötigt - es ist keine Arduino-Hardware erforderlich!&lt;br /&gt;
* Build-Pfad für Arduino-IDE erstellen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mkdir /home/pi/build &amp;amp;&amp;amp; chmod -R 777 /home/pi/build&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* In den Ordner &#039;&#039;/usr/share/arduino/hardware&#039;&#039; wechseln und Hardware-Board für den ATMega644 laden &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /usr/share/arduino/hardware&lt;br /&gt;
git clone https://github.com/jabdoa2/jabduino&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Um alle Pfade und Dateien zu erzeugen, muss die Arduino-IDE aufgerufen und anschließend direkt wieder geschlossen werden. Das kann man in der grafischen Umgebung des Raspis, oder über ein entferntes X-Terminal tun.&lt;br /&gt;
* In manchen Adruino-IDE Umgebungen werden Builds gelöscht, bevor sie auf die Hardware gespielt werden. Das muss verhindert werden! Bei Raspbian Jessie und dem User pi befinden sich die Voreinstellungen der IDE in &#039;&#039;/home/pi/.arduino/preferences.txt&#039;&#039;. Über die Konsole dort folgende Änderungen machen, bzw. Einträge hinzufügen&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
build.path=/home/pi/build&lt;br /&gt;
...&lt;br /&gt;
export.delete_target_folder=false&lt;br /&gt;
...&lt;br /&gt;
preproc.save_build_files=true&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Firmware-Quellen in den Sketchbook-Ordner von User &#039;&#039;pi&#039;&#039; kopieren und Rechte für alle setzen&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp -R /root/hm_switch/Asksin_HM_LC_Sw1PBU_FM/ /home/pi/sketchbook/ &amp;amp;&amp;amp; chmod -R 777 /home/pi/sketchbook/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Wieder in die grafische IDE wechseln&lt;br /&gt;
** &#039;&#039;Tools -&amp;gt; Board -&amp;gt;&#039;&#039; &amp;quot;Jabduino ATmega644A&amp;quot; auswählen &lt;br /&gt;
** &#039;&#039;File -&amp;gt; Sketchbook -&amp;gt; &#039;&#039; &amp;quot;Asksin_HM_LC_Sw1PBU_FM&amp;quot; öffnen&lt;br /&gt;
** In der Datei Asksin_HM_LC_Sw1PBU_FM den Wert in Zeile 64 eventuell &amp;quot;const unsigned long minImpulsLength = 5000;&amp;quot; ändern. Der dort eingetragene Wert gilt als Schwellwert, wann der Schalter erkennen soll, dass ein angeschlossener Wechselschalter gedrückt wurde und somit erkannt wird, dass Strom fließt. &lt;br /&gt;
** In der Datei &#039;&#039;Register.h&#039;&#039; in Zeile 22 den Wert von HMID[3] ändern. &lt;br /&gt;
Zusätzlich kann die eigene Zentrale bereits als Default-Wert in den Schalter eingetragen werden. Dadurch entfällt ein unter Umständen notwendiges Peering. Dafür muss die Zeile 347 von //#define firstLoad&#039; in &#039;#define firstLoad&#039; geändert werden In den Zeilen 354 bis 356 die Werte für die FHEM-Zentral-ID einfügen (Reading: D-HMIdOriginal 2CC71D) reg.ch_0.pairCentral[0] = 0x2C; reg.ch_0.pairCentral[1] = 0xC7; reg.ch_0.pairCentral[2] = 0x1D; Auch andere Default-Werte wie Peerings und Schaltverhalten können an dieser Stelle verändert werden. Sollte das nicht gewünscht sein, sind diese Zeilen entweder auszukommentieren oder einfach zu löschen. &lt;br /&gt;
** Beispiel (Auszug aus Register.h mit Zeilenangaben)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;16&amp;gt;/* Serial ID       10 byte */  &#039;K&#039;,&#039;E&#039;,&#039;Q&#039;,&#039;0&#039;,&#039;0&#039;,&#039;0&#039;,&#039;0&#039;,&#039;0&#039;,&#039;0&#039;,&#039;7&#039;, // serial ID, needed for pairing&lt;br /&gt;
&amp;lt;22&amp;gt;       const uint8_t  HMID[3]     = { 0x08, 0x15, 0x07 };     // 081507&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
** Die beiden geänderten Dateien speichern und mit &#039;&#039;Sketch -&amp;gt; Überprüfen / Kompilieren&#039;&#039; kompilieren. Im unteren Fenster auf Fehlermeldungen achten!&lt;br /&gt;
** Wenn dies funktioniert hat, sollte im Ordner &#039;&#039;/home/pi/build&#039;&#039; die Datei &#039;&#039;Asksin_HM_LC_Sw1PBU_FM.cpp.hex&#039;&#039; mit aktuellem Datum erzeugt worden sein.&lt;br /&gt;
&lt;br /&gt;
== Bootloader ==&lt;br /&gt;
* Datei /root/hm_switch/Asksin_OTA_Bootloader/devices/HM-LC-Sw1PBU-FM.h editieren und dabei Seriennummer, HMID und die Typ setzen. Seriennummer und HMID müssen in eurer Umgebung eindeutig sein, Typ ist: &#039;&#039;&#039;0xF0A9&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
nano /root/hm_switch/Asksin_OTA_Bootloader/devices/HM-LC-Sw1PBU-FM.h&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
** Beispiel: HMID -&amp;gt; 081507, Seriennummer: KEQ0000007&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/ The model type (not used from bootloader)&lt;br /&gt;
#define HM_TYPE              0xF0, 0xA9&lt;br /&gt;
// 10 bytes serial number. Must be unique for each device&lt;br /&gt;
#define HM_SERIAL            &#039;K&#039;, &#039;E&#039;, &#039;Q&#039;, &#039;0&#039;, &#039;0&#039;, &#039;0&#039;, &#039;0&#039;, &#039;0&#039;, &#039;0&#039;, &#039;7&#039;&lt;br /&gt;
// 3 bytes The device address (hm_id)&lt;br /&gt;
#define HM_ID                0x08, 0x15, 0x07&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Eine Verzeichnisebene höher und Bootloader bauen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cd /root/hm_switch/Asksin_OTA_Bootloader/&lt;br /&gt;
make clean HM_LC_Sw1PBU_FM_8k&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Dabei sollte die Datei &#039;&#039;bootloader_HM-LC-Sw1PBU-FM.hex&#039;&#039; herauskommen. Diese wird später auf den Schalter geflasht&lt;br /&gt;
&lt;br /&gt;
== Flashen ==&lt;br /&gt;
* Erzeugte Bootloader-Datei und Firmware in ein Verzeichnis kopieren:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /home/pi/build/Asksin_HM_LC_Sw1PBU_FM.cpp.hex /root/hm_switch/flash/firmware.hex &amp;amp;&amp;amp; cp /root/hm_switch/Asksin_OTA_Bootloader/Bootloader-AskSin-OTA-HM_LC_Sw1PBU_FM_8k.hex /root/hm_switch/flash/bootloader.hex&lt;br /&gt;
cd /root/hm_switch/flash/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Hinweis: In älteren Beschreibungen findet man häufig die Ziel-Plattform m644. Diese Unterscheidet sich praktisch in der Stromaufnahme des Chips, führt beim avrdude aber zu &#039;&#039;&#039;Fehlermeldungen&#039;&#039;&#039;, deshalb auf &#039;&#039;&#039;m6444p&#039;&#039;&#039; achten&lt;br /&gt;
* &#039;&#039;&#039;Fuses&#039;&#039;&#039; setzen&lt;br /&gt;
&#039;&#039;avrdude -p m644p -P gpio -c gpio -U lfuse:w:0xFD:m -U hfuse:w:0xD8:m -U lock:w:0x3F:m&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
avrdude: AVR device initialized and ready to accept instructions&lt;br /&gt;
Reading | ################################################## | 100% 0.00s&lt;br /&gt;
avrdude: Device signature = 0x1e960a&lt;br /&gt;
avrdude: reading input file &amp;quot;0xFD&amp;quot;&lt;br /&gt;
avrdude: writing lfuse (1 bytes):&lt;br /&gt;
Writing | ################################################## | 100% 0.00s&lt;br /&gt;
avrdude: 1 bytes of lfuse written&lt;br /&gt;
avrdude: verifying lfuse memory against 0xFD:&lt;br /&gt;
avrdude: load data lfuse data from input file 0xFD:&lt;br /&gt;
avrdude: input file 0xFD contains 1 bytes&lt;br /&gt;
avrdude: reading on-chip lfuse data:&lt;br /&gt;
Reading | ################################################## | 100% 0.00s&lt;br /&gt;
avrdude: verifying ...&lt;br /&gt;
avrdude: 1 bytes of lfuse verified&lt;br /&gt;
avrdude: reading input file &amp;quot;0xD8&amp;quot;&lt;br /&gt;
avrdude: writing hfuse (1 bytes):&lt;br /&gt;
Writing | ################################################## | 100% 0.00s&lt;br /&gt;
avrdude: 1 bytes of hfuse written&lt;br /&gt;
avrdude: verifying hfuse memory against 0xD8:&lt;br /&gt;
avrdude: load data hfuse data from input file 0xD8:&lt;br /&gt;
avrdude: input file 0xD8 contains 1 bytes&lt;br /&gt;
avrdude: reading on-chip hfuse data:&lt;br /&gt;
Reading | ################################################## | 100% 0.00s&lt;br /&gt;
avrdude: verifying ...&lt;br /&gt;
avrdude: 1 bytes of hfuse verified&lt;br /&gt;
avrdude: safemode: Fuses OK&lt;br /&gt;
avrdude done.  Thank you.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Bootloader&#039;&#039;&#039; flashen&lt;br /&gt;
&#039;&#039;avrdude -p m644p -P gpio -c gpio -U flash:w:bootloader.hex&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
avrdude: AVR device initialized and ready to accept instructions&lt;br /&gt;
Reading | ################################################## | 100% 0.00s&lt;br /&gt;
avrdude: Device signature = 0x1e960a&lt;br /&gt;
avrdude: NOTE: FLASH memory has been specified, an erase cycle will be performed&lt;br /&gt;
         To disable this feature, specify the -D option.&lt;br /&gt;
avrdude: erasing chip&lt;br /&gt;
avrdude: reading input file &amp;quot;bootloader_HM-LC-Sw1PBU-FM.hex&amp;quot;&lt;br /&gt;
avrdude: input file bootloader_HM-LC-Sw1PBU-FM.hex auto detected as Intel Hex&lt;br /&gt;
avrdude: writing flash (61372 bytes):&lt;br /&gt;
Writing | ################################################## | 100% 30.86s&lt;br /&gt;
avrdude: 61372 bytes of flash written&lt;br /&gt;
avrdude: verifying flash memory against bootloader_HM-LC-Sw1PBU-FM.hex:&lt;br /&gt;
avrdude: load data flash data from input file bootloader_HM-LC-Sw1PBU-FM.hex:&lt;br /&gt;
avrdude: input file bootloader_HM-LC-Sw1PBU-FM.hex auto detected as Intel Hex&lt;br /&gt;
avrdude: input file bootloader_HM-LC-Sw1PBU-FM.hex contains 61372 bytes&lt;br /&gt;
avrdude: reading on-chip flash data:&lt;br /&gt;
Reading | ################################################## | 100% 28.95s&lt;br /&gt;
avrdude: verifying ...&lt;br /&gt;
avrdude: 61372 bytes of flash verified&lt;br /&gt;
avrdude: safemode: Fuses OK&lt;br /&gt;
avrdude done.  Thank you.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Firmware&#039;&#039;&#039; flashen (aus der Arduino-IDE)&lt;br /&gt;
&#039;&#039;avrdude -p m644p -P gpio -c gpio -U flash:w:firmware.hex&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
avrdude: AVR device initialized and ready to accept instructions&lt;br /&gt;
Reading | ################################################## | 100% 0.00s&lt;br /&gt;
avrdude: Device signature = 0x1e960a&lt;br /&gt;
avrdude: NOTE: FLASH memory has been specified, an erase cycle will be performed&lt;br /&gt;
         To disable this feature, specify the -D option.&lt;br /&gt;
avrdude: erasing chip&lt;br /&gt;
avrdude: reading input file &amp;quot;Asksin_HM_LC_Sw1PBU_FM.cpp.hex&amp;quot;&lt;br /&gt;
avrdude: input file Asksin_HM_LC_Sw1PBU_FM.cpp.hex auto detected as Intel Hex&lt;br /&gt;
avrdude: writing flash (19042 bytes):&lt;br /&gt;
Writing | ################################################## | 100% 9.79s&lt;br /&gt;
avrdude: 19042 bytes of flash written&lt;br /&gt;
avrdude: verifying flash memory against Asksin_HM_LC_Sw1PBU_FM.cpp.hex:&lt;br /&gt;
avrdude: load data flash data from input file Asksin_HM_LC_Sw1PBU_FM.cpp.hex:&lt;br /&gt;
avrdude: input file Asksin_HM_LC_Sw1PBU_FM.cpp.hex auto detected as Intel Hex&lt;br /&gt;
avrdude: input file Asksin_HM_LC_Sw1PBU_FM.cpp.hex contains 19042 bytes&lt;br /&gt;
avrdude: reading on-chip flash data:&lt;br /&gt;
Reading | ################################################## | 100% 9.28s&lt;br /&gt;
avrdude: verifying ...&lt;br /&gt;
avrdude: 19042 bytes of flash verified&lt;br /&gt;
avrdude: safemode: Fuses OK&lt;br /&gt;
avrdude done.  Thank you.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HomeMatic Components]]&lt;br /&gt;
[[Kategorie:Schalter (Sender)]]&lt;br /&gt;
[[Kategorie:Schalter (Empfänger)]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Interfaces_f%C3%BCr_1-Wire&amp;diff=15821</id>
		<title>Interfaces für 1-Wire</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Interfaces_f%C3%BCr_1-Wire&amp;diff=15821"/>
		<updated>2016-07-13T21:54:14Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einleitung ==&lt;br /&gt;
Der &#039;&#039;&#039;1-Wire&#039;&#039;&#039; Bus mit seinen Sensoren und Aktoren ist über ein [[Interface]] an einen Computer angeschlossen. Hierzu sind folgende Typen gebräuchlich:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;DS2480(B)&#039;&#039;&#039; ist ein Bus-Master-IC, der einen kompletten 1-Wire Bus an ein serielles Signal ankoppelt, dabei Teile des Timing sowie des Suchalgorithmus übernimmt. Dieser Schaltkreis ist Bestandteil vieler anderer [[Aktives Interface|aktiver Interfaces]].&lt;br /&gt;
* &#039;&#039;&#039;DS2482&#039;&#039;&#039; ist ein Bus-Master-IC, der einen kompletten 1-Wire Bus an ein serielles Signal auf dem I2C-Bus ankoppelt, dabei Teile des Timing sowie des Suchalgorithmus übernimmt. Dieser Schaltkreis ist Bestandteil des [[CUNO und 1-wire]]&lt;br /&gt;
* &#039;&#039;&#039;DS2490&#039;&#039;&#039; ist ein Bus-Master-IC, der einen kompletten 1-Wire Bus an einen USB-Port ankoppelt, dabei Teile des Timing sowie des Suchalgorithmus übernimmt. Dieser Schaltkreis ist Bestandteil verschiedener USB-Interfaces, er ist gegenwärtig nur über die Bibliothek libusb ansteuerbar, die von OWFS unterstützt wird. Eine Ansteuerung über OWX ist in Arbeit.&lt;br /&gt;
* &#039;&#039;&#039;DS9097&#039;&#039;&#039; ist ein [[Passives Interface|passives Interface]], mit dem die 1-Wire Komponenten aus einer seriellen RS232- Schnittstelle angesteuert werden. Dabei wird eine Spannungsversorgung realisiert, indem die RTS/CTS-Signale der Schnittstelle &amp;quot;gestohlen&amp;quot; und gesammelt werden. Der 1-Wire-Suchalgorithmus muss bei dem DS9097-Interface vollständig im ansteuernden Computer realisiert werden.&lt;br /&gt;
* &#039;&#039;&#039;DS9490R&#039;&#039;&#039; ist ein aktives 1-Wire [[USB-Interface]] (Typ 2, basierend auf dem DS2490) das auch eine Versorgungsspannung für den 1-Wire Bus zur Verfügung stellt. Zusätzlich ist ein DS1420 ID-Chip integriert. Der 1-Wire-Anschluss erfolgt über einen 6-Poligen RJ11 (&amp;quot;Western&amp;quot;-)Stecker.&lt;br /&gt;
* &#039;&#039;&#039;DS9097U&#039;&#039;&#039; ist ein [[Aktives Interface|aktives Interface]] (basierend auf dem DS2480B), welches die serielle RS232-Schnittstelle eines Computers an den 1-Wire-Bus ankoppelt. Es kann durch einen zusätzlichen USB-zu-Seriell-Konverter auch an den USB-Port angeschlossen werden. Der 1-Wire-Anschluss erfolgt über einen 6-Poligen RJ11 (&amp;quot;Western&amp;quot;-)Stecker. Den DS9097U gibt es in drei Varianten (009/S09, E25), von denen 2 mit 9-poligem Anschluss und eine mit 25-poligem Anschluss an die serielle Schnittstelle versehen sind. Problematisch ist, dass bei den 9-poligen Varianten auf die RJ-11-Anschlussbuchse keine Versorgungsspannung für den 1-Wire-Bus geführt wird, dies lässt sich aber durch Öffnung des Gehäuses und Herausführung der entsprechenden Leitungen beheben.&lt;br /&gt;
* &#039;&#039;&#039;USB9097&#039;&#039;&#039; ist  aktives 1-Wire [[USB-Interface]] (Typ 1, basierend auf dem DS2480(B)). Er benötigt das Linux-Kernmodul ch341.ko&lt;br /&gt;
* &#039;&#039;&#039;LinkUSBi&#039;&#039;&#039; ist ein USB-1-Wire Adapter mit FTDI-Chip, der gegenüber den DS2480 etc. eine verbesserte Ansteuerung des 1-Wire Bus aufweist. &#039;&#039;&#039;Achtung:&#039;&#039;&#039; Dieser Adapter stellt verschiedene Funktionen für den 1-Wire Bus bereit, und emuliert den DS2480 Chip nur. Es kann daher derzeit zu Timing-Problemem kommen.&lt;br /&gt;
* &#039;&#039;&#039;[[Arduino mit OneWireFirmata]]&#039;&#039;&#039; [http://www.arduino.cc], kann als aktiver Busmaster für 1-Wire am USB-Port verwendet werden. Vorteil ist die preisgünstige Beschaffbarkeit und die einfache Integrierbarkeit in eigene Geräte (z.B. in der Version &#039;Nano&#039; die sich in übliche Lochrasterplatinen im 2,54 mm Rastermaß einfach einlöten läßt). An einem Arduino können bis zu 54 (modellabhängig) unabhängige 1-Wire-Busse angeschlossen werden. Nicht für 1-Wire benutzte Pins können für parallel für Digital- und Analog- Ein/Ausgabe benutzt werden.&lt;br /&gt;
*&#039;&#039;&#039;[[1W-IF-ETH]]&#039;&#039;&#039; ist eine Kombination aus einem kommerziell erhältlichen Ethernet-Modul und einem oder zwei DS2480(B)-Chips, mit denen ein 1-Wire-Bus direkt an ein Ethernet angeschlossen werden kann.&lt;br /&gt;
*&#039;&#039;&#039;[[1W-IF-WIFI]]&#039;&#039;&#039; ist eine Kombination aus einem kommerziell erhältichen WLAN-Modul und einem oder zwei DS2480(B)-Chips, mit denen ein 1-Wire-Bus direkt an ein Ethernet angeschlossen werden kann.&lt;br /&gt;
[[Kategorie:1-Wire]]&lt;br /&gt;
[[Kategorie:Interfaces]]&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Verkehrslage&amp;diff=15797</id>
		<title>Verkehrslage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Verkehrslage&amp;diff=15797"/>
		<updated>2016-07-05T20:05:18Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: /* Startort */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Hier wird ein Device erstellt um sich die [[Verkehrslage]] einer bestimmten Strecke anzeigen zu lassen. Das ganze beruht auf dem Modul [[HTTPMOD]]. &lt;br /&gt;
&lt;br /&gt;
== Zielsetzung ==&lt;br /&gt;
Ziel ist es, dass ein Dummy die aktuelle Verkehrslage für einen bestimmten Weg anzeigt und sich regelmäßig aktualisiert.  &lt;br /&gt;
&lt;br /&gt;
== Vorraussetzungen ==&lt;br /&gt;
Benötigt wird das Modul [[HTTPMOD]], welches standardmäßig installiert ist. Weiterhin wird ein Google Account benötigt und ein API Key um auf die Daten der Google Verkehrslage zuzugreifen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== API Key von Google beziehen ==&lt;br /&gt;
Der Google API Key ist ein Schlüssel, welcher uns berechtigt Daten von Google zu erhalten. Google hat verschiedene Programme, welche über eine API Schnittstelle zur Verfügung gestellt werden. Damit nicht jeder einfach auf diese Daten zugreifen kann, wird der Key benötigt. Um diesen zu bekommen müsst ihr als aller erstes einen Google Account erstellen auf www.google.de &lt;br /&gt;
&lt;br /&gt;
Sobald ihr dies habt, müssen wir in die Developer Console. Grund ist, dass der Zugriff auf die Daten eigentlich für Entwickler ist. Dorthin gelang ihr über diesen [https://console.developers.google.com/start?hl=de Link]. &lt;br /&gt;
&lt;br /&gt;
Als nächstes müsst ihr oben Links auf &amp;quot;Google APIs verwenden&amp;quot; klicken und ein neues Projekt erstellen, wenn ihr noch keins habt.&lt;br /&gt;
&lt;br /&gt;
Jetzt in der Übersicht beim Reiter &amp;quot;Google APIs&amp;quot; unter Google Maps API &amp;quot;Google Maps Distance Matrix API&amp;quot; auswählen und dort auf den blauen Button &amp;quot;Enable&amp;quot; klicken.  &lt;br /&gt;
&lt;br /&gt;
Unter dem Reiter &amp;quot;Nutzung&amp;quot; könnt ihr später die Häufigkeit eurer Zugriffe anzeigen lassen. Unter dem Reiter &amp;quot;Kontingente&amp;quot; seht ihr, wie viele Zugriffe ihr an diesem Tag noch tätigen könnt. Insgesamt sind 2500 Zugriffe pro Tag erlaubt. Das sind etwa 1,7 Zugriffe pro Minute. So viele sollte man eigentlich nicht brauchen. &lt;br /&gt;
&lt;br /&gt;
Auf der linken Seite unter &amp;quot;Zugangsdaten&amp;quot; kann man sich nun auch seinen Key anzeigen lassen. Diesen werden wir später für die Zugriffe benötigen. &lt;br /&gt;
&lt;br /&gt;
== Link für das Modul erstellen ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;https://maps.googleapis.com/maps/api/distancematrix/json?origins=ORT,STRASSE+NR&amp;amp;destinations=ORT,STRASSE+NR&amp;amp;mode=driving&amp;amp;language=de-DE&amp;amp;departure_time=now&amp;amp;key=APIKEY&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Den Link müssen wir mit unseren eigenen Angaben ergänzen. Starten wir zB in Frankfurt an der Friedberger Straße 291 und wollen nach Gießen in die Straße Schiffenberger Weg 115 sieht unser Link wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;https://maps.googleapis.com/maps/api/distancematrix/json?origins=Frankfurt,Friedberger%20Stra%C3%9Fe%20291&amp;amp;destinations=Gie%C3%9Fen,%20Schiffenberger%20Weg%20115&amp;amp;mode=driving&amp;amp;language=de-DE&amp;amp;departure_time=now&amp;amp;key=APIKEY&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es empfiehlt sich den Link einmal in die Browserzeile einzugeben. Dann muss auch nicht auf Leerzeichen geachtet werden und Google formatiert ihn uns automatisch, wie wir ihn brauchen. Übrigens seht ihr dann auch, wie die Seite aussieht, auf welche wir später mit dem HTTPMOD Modul zugreifen werden. &lt;br /&gt;
&lt;br /&gt;
== HTTPMOD Einrichtung ==&lt;br /&gt;
&lt;br /&gt;
=== Definieren des Device ===&lt;br /&gt;
Wenn wir nun unseren Google API Key und den Link haben, müssen wir ein neues Device mittels des [[HTTPMOD]] Moduls anlegen. In unserem Beispiel werden wir es wie folgt nennen: Verkehr.FFM.GI Verkehr für die Übersicht, FFM, weil wir ins Frankfurt am Main starten werden und GI, weil wir in Gießen enden. &lt;br /&gt;
&lt;br /&gt;
Wir geben also folgendes in unsere Kommandozeile ein: &lt;br /&gt;
&amp;lt;pre&amp;gt;define Verkehr.FFM.GI HTTPMOD Link 3600&amp;lt;/pre&amp;gt; &lt;br /&gt;
in unserem Beispiel also:&lt;br /&gt;
&amp;lt;pre&amp;gt;define Verkehr.FFM.GI HTTPMOD https://maps.googleapis.com/maps/api/distancematrix/json?origins=Frankfurt,Friedberger%20Stra%C3%9Fe%20291&amp;amp;destinations=Gie%C3%9Fen,%20Schiffenberger%20Weg%20115&amp;amp;mode=driving&amp;amp;language=de-DE&amp;amp;departure_time=now&amp;amp;key=APIKEY 3600&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zahl am Ende bestimmt die Häufigkeit der Abfrage in Sekunden. In unserem Fall also einmal die Stunde.&lt;br /&gt;
&lt;br /&gt;
=== Anlegen der Attribute ===&lt;br /&gt;
Die benötigten Daten werden nun über die Attribut readingXXName und readingXXRegex abgefragt. &lt;br /&gt;
&lt;br /&gt;
readingXXName: Hiermit geben wir dem späteren Reading einen Namen. &lt;br /&gt;
&lt;br /&gt;
readingXXRegex: Hier wird festgelegt, welcher Teil des Textes &amp;quot;herausgeschnitten&amp;quot; werden soll.&lt;br /&gt;
&lt;br /&gt;
XX: Wird durch Zahlen ersetzt, damit man eine Übersicht hat. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Als aller Erstes müssen wir uns unsere eigenen Attribute vorbereiten. Dies machen wir mit dem attr userattr wie folgt:&lt;br /&gt;
&lt;br /&gt;
==== UserReadings Attribut ====&lt;br /&gt;
Hier definieren wir die später benötigte Attribute:&lt;br /&gt;
&amp;lt;pre&amp;gt;attr Verkehr.FFM.GI userattr reading01Name reading01Regex reading02Name reading02Regex reading03Name reading03Regex reading04Name reading04Regex reading05Name reading05Regex &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mehr zu den Attributen unter [[HTTPMOD]].&lt;br /&gt;
&lt;br /&gt;
Legen wir nun unsere weiteren Attribut an:&lt;br /&gt;
&lt;br /&gt;
==== Dauer der Reise ====&lt;br /&gt;
Die Dauer der Reise greifen wir mit den Attributen: &lt;br /&gt;
&amp;lt;pre&amp;gt;attr Verkehr.FFM.GI reading01Name duration &lt;br /&gt;
attr Verkehr.FFM.GI reading01Regex &amp;quot;duration&amp;quot;\s*:\s*{\s*[&amp;quot;\w\s:,]+&amp;quot;value&amp;quot;\s*:\s*(\d+)\s*} &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Unser Reading wird später &amp;quot;duration&amp;quot; heißen. Darin wird die Dauer der Reise in Sekunden angegeben.&lt;br /&gt;
&lt;br /&gt;
==== Dauer der Reise mit aktuellem Verkehr ====&lt;br /&gt;
Die Dauer der Reise mit Verkehr greifen wir mit den Attributen: &lt;br /&gt;
&amp;lt;pre&amp;gt;attr Verkehr.FFM.GI reading02Name duration_in_traffic &lt;br /&gt;
attr Verkehr.FFM.GI reading02Regex &amp;quot;duration_in_traffic&amp;quot;\s*:\s*{\s*[&amp;quot;\w\s:,]+&amp;quot;value&amp;quot;\s*:\s*(\d+)\s*}  &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Unser Reading wird später &amp;quot;duration&amp;quot; heißen. Darin wird die Dauer der Reise in Sekunden angegeben.&lt;br /&gt;
&lt;br /&gt;
==== Entfernung ====&lt;br /&gt;
Die Entfernung greifen wir mit den Attributen:&lt;br /&gt;
&amp;lt;pre&amp;gt;attr Verkehr.FFM.GI reading03Name distance &lt;br /&gt;
attr Verkehr.FFM.GI reading03Regex &amp;quot;distance&amp;quot;\s*:\s*{\s*[&amp;quot;\w\s:,]+&amp;quot;value&amp;quot;\s*:\s*(\d+)\s*}   &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Unser Reading wird später &amp;quot;distance&amp;quot; heißen und uns die Entfernung angeben.&lt;br /&gt;
&lt;br /&gt;
==== Zielort ====&lt;br /&gt;
Den Zielort greifen wir mit den Attributen:&lt;br /&gt;
&amp;lt;pre&amp;gt;attr Verkehr.FFM.GI reading04Name destination_addresses  &lt;br /&gt;
attr Verkehr.FFM.GI reading04Regex &amp;quot;destination_addresses&amp;quot;\s*:\s*\[\s*&amp;quot;([\w\s.,-:üöäß(\)]+)&amp;quot;\s*\]   &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Unser Reading wird später &amp;quot;destination_addresses&amp;quot; heißen und uns den Zielort angeben.&lt;br /&gt;
&lt;br /&gt;
==== Startort ====&lt;br /&gt;
Den Startort greifen wir mit den Attributen:&lt;br /&gt;
&amp;lt;pre&amp;gt;attr Verkehr.FFM.GI reading05Name origin_addresses  &lt;br /&gt;
attr Verkehr.FFM.GI reading05Regex &amp;quot;origin_addresses&amp;quot;\s*:\s*\[\s*&amp;quot;([\w\s.,-:üöäß(\)]+)&amp;quot;\s*\]   &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Unser Reading wird später &amp;quot;origin_addresses&amp;quot; heißen und uns den Zielort angeben.&lt;br /&gt;
&lt;br /&gt;
==== Berechnung der Werte für die spätere Anzeige ====&lt;br /&gt;
Damit die Werte später User freundlich angezeigt werden, lassen wir sie von FHEM berechnen:&lt;br /&gt;
&amp;lt;pre&amp;gt;attr Verkehr.FFM.GI userReadings duration_hr {strftime &amp;quot;%H:%M&amp;quot;, gmtime( int( ReadingsVal(&amp;quot;$name&amp;quot;,&amp;quot;duration&amp;quot;,0) /60+0.5)*60 );}, duration_in_traffic_hr {strftime &amp;quot;%H:%M&amp;quot;, gmtime( int( ReadingsVal(&amp;quot;$name&amp;quot;,&amp;quot;duration_in_traffic&amp;quot;,0) /60+0.5)*60 );}, distance_hr:distance {int( ReadingsVal(&amp;quot;$name&amp;quot;,&amp;quot;distance&amp;quot;,0) /1000+0.5);}, duration_diff {int((ReadingsVal(&amp;quot;$name&amp;quot;,&amp;quot;duration_in_traffic&amp;quot;,0)-ReadingsVal(&amp;quot;$name&amp;quot;,&amp;quot;duration&amp;quot;,0))/60+0.5);}, duration_diff_hr {my $diff=int((ReadingsVal(&amp;quot;$name&amp;quot;,&amp;quot;duration_in_traffic&amp;quot;,0)-ReadingsVal(&amp;quot;$name&amp;quot;,&amp;quot;duration&amp;quot;,0))/60+0.5); return &amp;quot;+&amp;quot;.$diff if ($diff&amp;gt;0); return &amp;quot;+0&amp;quot;;} &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== State Anzeige ====&lt;br /&gt;
Uns als letztes noch, wie wir das ganze in State angezeigt bekommen möchten:&lt;br /&gt;
&amp;lt;pre&amp;gt;attr Verkehr.FFM.GI stateFormat duration_hr duration_diff_hr Min. (distance_hr km) &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Fertig ==&lt;br /&gt;
Fertig ist das Device, welches uns nun unseren Weg anzeigt. Natürlich könnt ihr die einzelnen Berechnungen und auch die State Anzeige für euch selbst anpassen und entsprechend ändern.&lt;br /&gt;
&lt;br /&gt;
== Anmerkung ==&lt;br /&gt;
Zwei Dinge möchte ich anmerken:&lt;br /&gt;
&lt;br /&gt;
1. Das ganze beruht auf {{Link2Forum|Topic=20151|Message=363109|LinkText=diesem}} und {{Link2Forum|Topic=20151|Message=365322|LinkText=diesem}} Beitrag. &lt;br /&gt;
&lt;br /&gt;
2. Sobald Google die Ausgabe der Website verändert, wird es vermutlich nicht mehr funktionieren. Wie ihr dem Thema im Forum entnehmen könnt, ist dies schon vorgekommen. Daher nicht wundern, sondern im Forum schauen, ob es schon eine Veränderung gibt oder selbst die Readings anpassen.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Code_Snippets]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Verkehrslage&amp;diff=15796</id>
		<title>Verkehrslage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Verkehrslage&amp;diff=15796"/>
		<updated>2016-07-05T20:04:30Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: Doppelten Abschnitt Startort gelöscht&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Hier wird ein Device erstellt um sich die [[Verkehrslage]] einer bestimmten Strecke anzeigen zu lassen. Das ganze beruht auf dem Modul [[HTTPMOD]]. &lt;br /&gt;
&lt;br /&gt;
== Zielsetzung ==&lt;br /&gt;
Ziel ist es, dass ein Dummy die aktuelle Verkehrslage für einen bestimmten Weg anzeigt und sich regelmäßig aktualisiert.  &lt;br /&gt;
&lt;br /&gt;
== Vorraussetzungen ==&lt;br /&gt;
Benötigt wird das Modul [[HTTPMOD]], welches standardmäßig installiert ist. Weiterhin wird ein Google Account benötigt und ein API Key um auf die Daten der Google Verkehrslage zuzugreifen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== API Key von Google beziehen ==&lt;br /&gt;
Der Google API Key ist ein Schlüssel, welcher uns berechtigt Daten von Google zu erhalten. Google hat verschiedene Programme, welche über eine API Schnittstelle zur Verfügung gestellt werden. Damit nicht jeder einfach auf diese Daten zugreifen kann, wird der Key benötigt. Um diesen zu bekommen müsst ihr als aller erstes einen Google Account erstellen auf www.google.de &lt;br /&gt;
&lt;br /&gt;
Sobald ihr dies habt, müssen wir in die Developer Console. Grund ist, dass der Zugriff auf die Daten eigentlich für Entwickler ist. Dorthin gelang ihr über diesen [https://console.developers.google.com/start?hl=de Link]. &lt;br /&gt;
&lt;br /&gt;
Als nächstes müsst ihr oben Links auf &amp;quot;Google APIs verwenden&amp;quot; klicken und ein neues Projekt erstellen, wenn ihr noch keins habt.&lt;br /&gt;
&lt;br /&gt;
Jetzt in der Übersicht beim Reiter &amp;quot;Google APIs&amp;quot; unter Google Maps API &amp;quot;Google Maps Distance Matrix API&amp;quot; auswählen und dort auf den blauen Button &amp;quot;Enable&amp;quot; klicken.  &lt;br /&gt;
&lt;br /&gt;
Unter dem Reiter &amp;quot;Nutzung&amp;quot; könnt ihr später die Häufigkeit eurer Zugriffe anzeigen lassen. Unter dem Reiter &amp;quot;Kontingente&amp;quot; seht ihr, wie viele Zugriffe ihr an diesem Tag noch tätigen könnt. Insgesamt sind 2500 Zugriffe pro Tag erlaubt. Das sind etwa 1,7 Zugriffe pro Minute. So viele sollte man eigentlich nicht brauchen. &lt;br /&gt;
&lt;br /&gt;
Auf der linken Seite unter &amp;quot;Zugangsdaten&amp;quot; kann man sich nun auch seinen Key anzeigen lassen. Diesen werden wir später für die Zugriffe benötigen. &lt;br /&gt;
&lt;br /&gt;
== Link für das Modul erstellen ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;https://maps.googleapis.com/maps/api/distancematrix/json?origins=ORT,STRASSE+NR&amp;amp;destinations=ORT,STRASSE+NR&amp;amp;mode=driving&amp;amp;language=de-DE&amp;amp;departure_time=now&amp;amp;key=APIKEY&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Den Link müssen wir mit unseren eigenen Angaben ergänzen. Starten wir zB in Frankfurt an der Friedberger Straße 291 und wollen nach Gießen in die Straße Schiffenberger Weg 115 sieht unser Link wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;https://maps.googleapis.com/maps/api/distancematrix/json?origins=Frankfurt,Friedberger%20Stra%C3%9Fe%20291&amp;amp;destinations=Gie%C3%9Fen,%20Schiffenberger%20Weg%20115&amp;amp;mode=driving&amp;amp;language=de-DE&amp;amp;departure_time=now&amp;amp;key=APIKEY&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es empfiehlt sich den Link einmal in die Browserzeile einzugeben. Dann muss auch nicht auf Leerzeichen geachtet werden und Google formatiert ihn uns automatisch, wie wir ihn brauchen. Übrigens seht ihr dann auch, wie die Seite aussieht, auf welche wir später mit dem HTTPMOD Modul zugreifen werden. &lt;br /&gt;
&lt;br /&gt;
== HTTPMOD Einrichtung ==&lt;br /&gt;
&lt;br /&gt;
=== Definieren des Device ===&lt;br /&gt;
Wenn wir nun unseren Google API Key und den Link haben, müssen wir ein neues Device mittels des [[HTTPMOD]] Moduls anlegen. In unserem Beispiel werden wir es wie folgt nennen: Verkehr.FFM.GI Verkehr für die Übersicht, FFM, weil wir ins Frankfurt am Main starten werden und GI, weil wir in Gießen enden. &lt;br /&gt;
&lt;br /&gt;
Wir geben also folgendes in unsere Kommandozeile ein: &lt;br /&gt;
&amp;lt;pre&amp;gt;define Verkehr.FFM.GI HTTPMOD Link 3600&amp;lt;/pre&amp;gt; &lt;br /&gt;
in unserem Beispiel also:&lt;br /&gt;
&amp;lt;pre&amp;gt;define Verkehr.FFM.GI HTTPMOD https://maps.googleapis.com/maps/api/distancematrix/json?origins=Frankfurt,Friedberger%20Stra%C3%9Fe%20291&amp;amp;destinations=Gie%C3%9Fen,%20Schiffenberger%20Weg%20115&amp;amp;mode=driving&amp;amp;language=de-DE&amp;amp;departure_time=now&amp;amp;key=APIKEY 3600&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zahl am Ende bestimmt die Häufigkeit der Abfrage in Sekunden. In unserem Fall also einmal die Stunde.&lt;br /&gt;
&lt;br /&gt;
=== Anlegen der Attribute ===&lt;br /&gt;
Die benötigten Daten werden nun über die Attribut readingXXName und readingXXRegex abgefragt. &lt;br /&gt;
&lt;br /&gt;
readingXXName: Hiermit geben wir dem späteren Reading einen Namen. &lt;br /&gt;
&lt;br /&gt;
readingXXRegex: Hier wird festgelegt, welcher Teil des Textes &amp;quot;herausgeschnitten&amp;quot; werden soll.&lt;br /&gt;
&lt;br /&gt;
XX: Wird durch Zahlen ersetzt, damit man eine Übersicht hat. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Als aller Erstes müssen wir uns unsere eigenen Attribute vorbereiten. Dies machen wir mit dem attr userattr wie folgt:&lt;br /&gt;
&lt;br /&gt;
==== UserReadings Attribut ====&lt;br /&gt;
Hier definieren wir die später benötigte Attribute:&lt;br /&gt;
&amp;lt;pre&amp;gt;attr Verkehr.FFM.GI userattr reading01Name reading01Regex reading02Name reading02Regex reading03Name reading03Regex reading04Name reading04Regex reading05Name reading05Regex &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mehr zu den Attributen unter [[HTTPMOD]].&lt;br /&gt;
&lt;br /&gt;
Legen wir nun unsere weiteren Attribut an:&lt;br /&gt;
&lt;br /&gt;
==== Dauer der Reise ====&lt;br /&gt;
Die Dauer der Reise greifen wir mit den Attributen: &lt;br /&gt;
&amp;lt;pre&amp;gt;attr Verkehr.FFM.GI reading01Name duration &lt;br /&gt;
attr Verkehr.FFM.GI reading01Regex &amp;quot;duration&amp;quot;\s*:\s*{\s*[&amp;quot;\w\s:,]+&amp;quot;value&amp;quot;\s*:\s*(\d+)\s*} &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Unser Reading wird später &amp;quot;duration&amp;quot; heißen. Darin wird die Dauer der Reise in Sekunden angegeben.&lt;br /&gt;
&lt;br /&gt;
==== Dauer der Reise mit aktuellem Verkehr ====&lt;br /&gt;
Die Dauer der Reise mit Verkehr greifen wir mit den Attributen: &lt;br /&gt;
&amp;lt;pre&amp;gt;attr Verkehr.FFM.GI reading02Name duration_in_traffic &lt;br /&gt;
attr Verkehr.FFM.GI reading02Regex &amp;quot;duration_in_traffic&amp;quot;\s*:\s*{\s*[&amp;quot;\w\s:,]+&amp;quot;value&amp;quot;\s*:\s*(\d+)\s*}  &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Unser Reading wird später &amp;quot;duration&amp;quot; heißen. Darin wird die Dauer der Reise in Sekunden angegeben.&lt;br /&gt;
&lt;br /&gt;
==== Entfernung ====&lt;br /&gt;
Die Entfernung greifen wir mit den Attributen:&lt;br /&gt;
&amp;lt;pre&amp;gt;attr Verkehr.FFM.GI reading03Name distance &lt;br /&gt;
attr Verkehr.FFM.GI reading03Regex &amp;quot;distance&amp;quot;\s*:\s*{\s*[&amp;quot;\w\s:,]+&amp;quot;value&amp;quot;\s*:\s*(\d+)\s*}   &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Unser Reading wird später &amp;quot;distance&amp;quot; heißen und uns die Entfernung angeben.&lt;br /&gt;
&lt;br /&gt;
==== Zielort ====&lt;br /&gt;
Den Zielort greifen wir mit den Attributen:&lt;br /&gt;
&amp;lt;pre&amp;gt;attr Verkehr.FFM.GI reading04Name destination_addresses  &lt;br /&gt;
attr Verkehr.FFM.GI reading04Regex &amp;quot;destination_addresses&amp;quot;\s*:\s*\[\s*&amp;quot;([\w\s.,-:üöäß(\)]+)&amp;quot;\s*\]   &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Unser Reading wird später &amp;quot;destination_addresses&amp;quot; heißen und uns den Zielort angeben.&lt;br /&gt;
&lt;br /&gt;
==== Startort ====&lt;br /&gt;
Den Startort greifen wir mit den Attributen:&lt;br /&gt;
&amp;lt;pre&amp;gt;attr Verkehr.FFM.GI reading06Name origin_addresses  &lt;br /&gt;
attr Verkehr.FFM.GI reading06Regex &amp;quot;origin_addresses&amp;quot;\s*:\s*\[\s*&amp;quot;([\w\s.,-:üöäß(\)]+)&amp;quot;\s*\]   &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Unser Reading wird später &amp;quot;origin_addresses&amp;quot; heißen und uns den Zielort angeben.&lt;br /&gt;
&lt;br /&gt;
==== Berechnung der Werte für die spätere Anzeige ====&lt;br /&gt;
Damit die Werte später User freundlich angezeigt werden, lassen wir sie von FHEM berechnen:&lt;br /&gt;
&amp;lt;pre&amp;gt;attr Verkehr.FFM.GI userReadings duration_hr {strftime &amp;quot;%H:%M&amp;quot;, gmtime( int( ReadingsVal(&amp;quot;$name&amp;quot;,&amp;quot;duration&amp;quot;,0) /60+0.5)*60 );}, duration_in_traffic_hr {strftime &amp;quot;%H:%M&amp;quot;, gmtime( int( ReadingsVal(&amp;quot;$name&amp;quot;,&amp;quot;duration_in_traffic&amp;quot;,0) /60+0.5)*60 );}, distance_hr:distance {int( ReadingsVal(&amp;quot;$name&amp;quot;,&amp;quot;distance&amp;quot;,0) /1000+0.5);}, duration_diff {int((ReadingsVal(&amp;quot;$name&amp;quot;,&amp;quot;duration_in_traffic&amp;quot;,0)-ReadingsVal(&amp;quot;$name&amp;quot;,&amp;quot;duration&amp;quot;,0))/60+0.5);}, duration_diff_hr {my $diff=int((ReadingsVal(&amp;quot;$name&amp;quot;,&amp;quot;duration_in_traffic&amp;quot;,0)-ReadingsVal(&amp;quot;$name&amp;quot;,&amp;quot;duration&amp;quot;,0))/60+0.5); return &amp;quot;+&amp;quot;.$diff if ($diff&amp;gt;0); return &amp;quot;+0&amp;quot;;} &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== State Anzeige ====&lt;br /&gt;
Uns als letztes noch, wie wir das ganze in State angezeigt bekommen möchten:&lt;br /&gt;
&amp;lt;pre&amp;gt;attr Verkehr.FFM.GI stateFormat duration_hr duration_diff_hr Min. (distance_hr km) &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Fertig ==&lt;br /&gt;
Fertig ist das Device, welches uns nun unseren Weg anzeigt. Natürlich könnt ihr die einzelnen Berechnungen und auch die State Anzeige für euch selbst anpassen und entsprechend ändern.&lt;br /&gt;
&lt;br /&gt;
== Anmerkung ==&lt;br /&gt;
Zwei Dinge möchte ich anmerken:&lt;br /&gt;
&lt;br /&gt;
1. Das ganze beruht auf {{Link2Forum|Topic=20151|Message=363109|LinkText=diesem}} und {{Link2Forum|Topic=20151|Message=365322|LinkText=diesem}} Beitrag. &lt;br /&gt;
&lt;br /&gt;
2. Sobald Google die Ausgabe der Website verändert, wird es vermutlich nicht mehr funktionieren. Wie ihr dem Thema im Forum entnehmen könnt, ist dies schon vorgekommen. Daher nicht wundern, sondern im Forum schauen, ob es schon eine Veränderung gibt oder selbst die Readings anpassen.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Code_Snippets]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Verkehrslage&amp;diff=15795</id>
		<title>Verkehrslage</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Verkehrslage&amp;diff=15795"/>
		<updated>2016-07-05T19:57:53Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: /* Definieren des Device */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Hier wird ein Device erstellt um sich die [[Verkehrslage]] einer bestimmten Strecke anzeigen zu lassen. Das ganze beruht auf dem Modul [[HTTPMOD]]. &lt;br /&gt;
&lt;br /&gt;
== Zielsetzung ==&lt;br /&gt;
Ziel ist es, dass ein Dummy die aktuelle Verkehrslage für einen bestimmten Weg anzeigt und sich regelmäßig aktualisiert.  &lt;br /&gt;
&lt;br /&gt;
== Vorraussetzungen ==&lt;br /&gt;
Benötigt wird das Modul [[HTTPMOD]], welches standardmäßig installiert ist. Weiterhin wird ein Google Account benötigt und ein API Key um auf die Daten der Google Verkehrslage zuzugreifen. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== API Key von Google beziehen ==&lt;br /&gt;
Der Google API Key ist ein Schlüssel, welcher uns berechtigt Daten von Google zu erhalten. Google hat verschiedene Programme, welche über eine API Schnittstelle zur Verfügung gestellt werden. Damit nicht jeder einfach auf diese Daten zugreifen kann, wird der Key benötigt. Um diesen zu bekommen müsst ihr als aller erstes einen Google Account erstellen auf www.google.de &lt;br /&gt;
&lt;br /&gt;
Sobald ihr dies habt, müssen wir in die Developer Console. Grund ist, dass der Zugriff auf die Daten eigentlich für Entwickler ist. Dorthin gelang ihr über diesen [https://console.developers.google.com/start?hl=de Link]. &lt;br /&gt;
&lt;br /&gt;
Als nächstes müsst ihr oben Links auf &amp;quot;Google APIs verwenden&amp;quot; klicken und ein neues Projekt erstellen, wenn ihr noch keins habt.&lt;br /&gt;
&lt;br /&gt;
Jetzt in der Übersicht beim Reiter &amp;quot;Google APIs&amp;quot; unter Google Maps API &amp;quot;Google Maps Distance Matrix API&amp;quot; auswählen und dort auf den blauen Button &amp;quot;Enable&amp;quot; klicken.  &lt;br /&gt;
&lt;br /&gt;
Unter dem Reiter &amp;quot;Nutzung&amp;quot; könnt ihr später die Häufigkeit eurer Zugriffe anzeigen lassen. Unter dem Reiter &amp;quot;Kontingente&amp;quot; seht ihr, wie viele Zugriffe ihr an diesem Tag noch tätigen könnt. Insgesamt sind 2500 Zugriffe pro Tag erlaubt. Das sind etwa 1,7 Zugriffe pro Minute. So viele sollte man eigentlich nicht brauchen. &lt;br /&gt;
&lt;br /&gt;
Auf der linken Seite unter &amp;quot;Zugangsdaten&amp;quot; kann man sich nun auch seinen Key anzeigen lassen. Diesen werden wir später für die Zugriffe benötigen. &lt;br /&gt;
&lt;br /&gt;
== Link für das Modul erstellen ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;https://maps.googleapis.com/maps/api/distancematrix/json?origins=ORT,STRASSE+NR&amp;amp;destinations=ORT,STRASSE+NR&amp;amp;mode=driving&amp;amp;language=de-DE&amp;amp;departure_time=now&amp;amp;key=APIKEY&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Den Link müssen wir mit unseren eigenen Angaben ergänzen. Starten wir zB in Frankfurt an der Friedberger Straße 291 und wollen nach Gießen in die Straße Schiffenberger Weg 115 sieht unser Link wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;https://maps.googleapis.com/maps/api/distancematrix/json?origins=Frankfurt,Friedberger%20Stra%C3%9Fe%20291&amp;amp;destinations=Gie%C3%9Fen,%20Schiffenberger%20Weg%20115&amp;amp;mode=driving&amp;amp;language=de-DE&amp;amp;departure_time=now&amp;amp;key=APIKEY&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es empfiehlt sich den Link einmal in die Browserzeile einzugeben. Dann muss auch nicht auf Leerzeichen geachtet werden und Google formatiert ihn uns automatisch, wie wir ihn brauchen. Übrigens seht ihr dann auch, wie die Seite aussieht, auf welche wir später mit dem HTTPMOD Modul zugreifen werden. &lt;br /&gt;
&lt;br /&gt;
== HTTPMOD Einrichtung ==&lt;br /&gt;
&lt;br /&gt;
=== Definieren des Device ===&lt;br /&gt;
Wenn wir nun unseren Google API Key und den Link haben, müssen wir ein neues Device mittels des [[HTTPMOD]] Moduls anlegen. In unserem Beispiel werden wir es wie folgt nennen: Verkehr.FFM.GI Verkehr für die Übersicht, FFM, weil wir ins Frankfurt am Main starten werden und GI, weil wir in Gießen enden. &lt;br /&gt;
&lt;br /&gt;
Wir geben also folgendes in unsere Kommandozeile ein: &lt;br /&gt;
&amp;lt;pre&amp;gt;define Verkehr.FFM.GI HTTPMOD Link 3600&amp;lt;/pre&amp;gt; &lt;br /&gt;
in unserem Beispiel also:&lt;br /&gt;
&amp;lt;pre&amp;gt;define Verkehr.FFM.GI HTTPMOD https://maps.googleapis.com/maps/api/distancematrix/json?origins=Frankfurt,Friedberger%20Stra%C3%9Fe%20291&amp;amp;destinations=Gie%C3%9Fen,%20Schiffenberger%20Weg%20115&amp;amp;mode=driving&amp;amp;language=de-DE&amp;amp;departure_time=now&amp;amp;key=APIKEY 3600&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zahl am Ende bestimmt die Häufigkeit der Abfrage in Sekunden. In unserem Fall also einmal die Stunde.&lt;br /&gt;
&lt;br /&gt;
=== Anlegen der Attribute ===&lt;br /&gt;
Die benötigten Daten werden nun über die Attribut readingXXName und readingXXRegex abgefragt. &lt;br /&gt;
&lt;br /&gt;
readingXXName: Hiermit geben wir dem späteren Reading einen Namen. &lt;br /&gt;
&lt;br /&gt;
readingXXRegex: Hier wird festgelegt, welcher Teil des Textes &amp;quot;herausgeschnitten&amp;quot; werden soll.&lt;br /&gt;
&lt;br /&gt;
XX: Wird durch Zahlen ersetzt, damit man eine Übersicht hat. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Als aller Erstes müssen wir uns unsere eigenen Attribute vorbereiten. Dies machen wir mit dem attr userattr wie folgt:&lt;br /&gt;
&lt;br /&gt;
==== UserReadings Attribut ====&lt;br /&gt;
Hier definieren wir die später benötigte Attribute:&lt;br /&gt;
&amp;lt;pre&amp;gt;attr Verkehr.FFM.GI userattr reading01Name reading01Regex reading02Name reading02Regex reading03Name reading03Regex reading04Name reading04Regex reading05Name reading05Regex &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mehr zu den Attributen unter [[HTTPMOD]].&lt;br /&gt;
&lt;br /&gt;
Legen wir nun unsere weiteren Attribut an:&lt;br /&gt;
&lt;br /&gt;
==== Dauer der Reise ====&lt;br /&gt;
Die Dauer der Reise greifen wir mit den Attributen: &lt;br /&gt;
&amp;lt;pre&amp;gt;attr Verkehr.FFM.GI reading01Name duration &lt;br /&gt;
attr Verkehr.FFM.GI reading01Regex &amp;quot;duration&amp;quot;\s*:\s*{\s*[&amp;quot;\w\s:,]+&amp;quot;value&amp;quot;\s*:\s*(\d+)\s*} &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Unser Reading wird später &amp;quot;duration&amp;quot; heißen. Darin wird die Dauer der Reise in Sekunden angegeben.&lt;br /&gt;
&lt;br /&gt;
==== Dauer der Reise mit aktuellem Verkehr ====&lt;br /&gt;
Die Dauer der Reise mit Verkehr greifen wir mit den Attributen: &lt;br /&gt;
&amp;lt;pre&amp;gt;attr Verkehr.FFM.GI reading02Name duration_in_traffic &lt;br /&gt;
attr Verkehr.FFM.GI reading02Regex &amp;quot;duration_in_traffic&amp;quot;\s*:\s*{\s*[&amp;quot;\w\s:,]+&amp;quot;value&amp;quot;\s*:\s*(\d+)\s*}  &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Unser Reading wird später &amp;quot;duration&amp;quot; heißen. Darin wird die Dauer der Reise in Sekunden angegeben.&lt;br /&gt;
&lt;br /&gt;
==== Entfernung ====&lt;br /&gt;
Die Entfernung greifen wir mit den Attributen:&lt;br /&gt;
&amp;lt;pre&amp;gt;attr Verkehr.FFM.GI reading03Name distance &lt;br /&gt;
attr Verkehr.FFM.GI reading03Regex &amp;quot;distance&amp;quot;\s*:\s*{\s*[&amp;quot;\w\s:,]+&amp;quot;value&amp;quot;\s*:\s*(\d+)\s*}   &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Unser Reading wird später &amp;quot;distance&amp;quot; heißen und uns die Entfernung angeben.&lt;br /&gt;
&lt;br /&gt;
==== Zielort ====&lt;br /&gt;
Den Zielort greifen wir mit den Attributen:&lt;br /&gt;
&amp;lt;pre&amp;gt;attr Verkehr.FFM.GI reading04Name destination_addresses  &lt;br /&gt;
attr Verkehr.FFM.GI reading04Regex &amp;quot;destination_addresses&amp;quot;\s*:\s*\[\s*&amp;quot;([\w\s.,-:üöäß(\)]+)&amp;quot;\s*\]   &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Unser Reading wird später &amp;quot;destination_addresses&amp;quot; heißen und uns den Zielort angeben.&lt;br /&gt;
&lt;br /&gt;
==== Startort ====&lt;br /&gt;
Den Startort greifen wir mit den Attributen: &lt;br /&gt;
&amp;lt;pre&amp;gt;attr Verkehr.FFM.GI reading05Name origin_addresses  &lt;br /&gt;
attr Verkehr.FFM.GI reading05Regex &amp;quot;origin_addresses&amp;quot;\s*:\s*\[\s*&amp;quot;([\w\s.,-:üöäß(\)]+)&amp;quot;\s*\]   &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Unser Reading wird später &amp;quot;origin_addresses&amp;quot; heißen und uns den Zielort angeben.&lt;br /&gt;
&lt;br /&gt;
==== Startort ====&lt;br /&gt;
Den Startort greifen wir mit den Attributen:&lt;br /&gt;
&amp;lt;pre&amp;gt;attr Verkehr.FFM.GI reading06Name origin_addresses  &lt;br /&gt;
attr Verkehr.FFM.GI reading06Regex &amp;quot;origin_addresses&amp;quot;\s*:\s*\[\s*&amp;quot;([\w\s.,-:üöäß(\)]+)&amp;quot;\s*\]   &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Unser Reading wird später &amp;quot;origin_addresses&amp;quot; heißen und uns den Zielort angeben.&lt;br /&gt;
&lt;br /&gt;
==== Berechnung der Werte für die spätere Anzeige ====&lt;br /&gt;
Damit die Werte später User freundlich angezeigt werden, lassen wir sie von FHEM berechnen:&lt;br /&gt;
&amp;lt;pre&amp;gt;attr Verkehr.FFM.GI userReadings duration_hr {strftime &amp;quot;%H:%M&amp;quot;, gmtime( int( ReadingsVal(&amp;quot;$name&amp;quot;,&amp;quot;duration&amp;quot;,0) /60+0.5)*60 );}, duration_in_traffic_hr {strftime &amp;quot;%H:%M&amp;quot;, gmtime( int( ReadingsVal(&amp;quot;$name&amp;quot;,&amp;quot;duration_in_traffic&amp;quot;,0) /60+0.5)*60 );}, distance_hr:distance {int( ReadingsVal(&amp;quot;$name&amp;quot;,&amp;quot;distance&amp;quot;,0) /1000+0.5);}, duration_diff {int((ReadingsVal(&amp;quot;$name&amp;quot;,&amp;quot;duration_in_traffic&amp;quot;,0)-ReadingsVal(&amp;quot;$name&amp;quot;,&amp;quot;duration&amp;quot;,0))/60+0.5);}, duration_diff_hr {my $diff=int((ReadingsVal(&amp;quot;$name&amp;quot;,&amp;quot;duration_in_traffic&amp;quot;,0)-ReadingsVal(&amp;quot;$name&amp;quot;,&amp;quot;duration&amp;quot;,0))/60+0.5); return &amp;quot;+&amp;quot;.$diff if ($diff&amp;gt;0); return &amp;quot;+0&amp;quot;;} &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== State Anzeige ====&lt;br /&gt;
Uns als letztes noch, wie wir das ganze in State angezeigt bekommen möchten:&lt;br /&gt;
&amp;lt;pre&amp;gt;attr Verkehr.FFM.GI stateFormat duration_hr duration_diff_hr Min. (distance_hr km) &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Fertig ==&lt;br /&gt;
Fertig ist das Device, welches uns nun unseren Weg anzeigt. Natürlich könnt ihr die einzelnen Berechnungen und auch die State Anzeige für euch selbst anpassen und entsprechend ändern.&lt;br /&gt;
&lt;br /&gt;
== Anmerkung ==&lt;br /&gt;
Zwei Dinge möchte ich anmerken:&lt;br /&gt;
&lt;br /&gt;
1. Das ganze beruht auf {{Link2Forum|Topic=20151|Message=363109|LinkText=diesem}} und {{Link2Forum|Topic=20151|Message=365322|LinkText=diesem}} Beitrag. &lt;br /&gt;
&lt;br /&gt;
2. Sobald Google die Ausgabe der Website verändert, wird es vermutlich nicht mehr funktionieren. Wie ihr dem Thema im Forum entnehmen könnt, ist dies schon vorgekommen. Daher nicht wundern, sondern im Forum schauen, ob es schon eine Veränderung gibt oder selbst die Readings anpassen.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Code_Snippets]]&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Diskussion:Color&amp;diff=15611</id>
		<title>Diskussion:Color</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Diskussion:Color&amp;diff=15611"/>
		<updated>2016-06-21T19:04:19Z</updated>

		<summary type="html">&lt;p&gt;Kaihs: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Funktioniert die Syntax&lt;br /&gt;
attr &amp;lt;device&amp;gt; devStateIcon {Color_devStateIcon(ReadingsVal($name,&amp;quot;rgb&amp;quot;,&amp;quot;000000&amp;quot;))}&lt;br /&gt;
nicht nur dann, wenn $name zum Zeitpunkt der Auswertung des Ausdrucks auch definiert ist?&lt;br /&gt;
&lt;br /&gt;
Das mag ja in einigen Modulen durchaus der Fall sein, aber dass es die Variable $name überhaupt gibt ist doch nur eine Konvention und nicht garantiert.&lt;br /&gt;
&lt;br /&gt;
Zumindest gab es dadurch in einem Modul in das ich Color.pm eingebaut habe Probleme und es funktionierte so nicht.&lt;/div&gt;</summary>
		<author><name>Kaihs</name></author>
	</entry>
</feed>