<?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=Binford6000</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=Binford6000"/>
	<link rel="alternate" type="text/html" href="http://wiki.fhem.de/wiki/Spezial:Beitr%C3%A4ge/Binford6000"/>
	<updated>2026-04-30T15:53:51Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.43.6</generator>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=HOMEMODE&amp;diff=32273</id>
		<title>HOMEMODE</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=HOMEMODE&amp;diff=32273"/>
		<updated>2020-01-03T07:42:14Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* HomeCMDfhemSAVE */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{&lt;br /&gt;
Infobox Modul&lt;br /&gt;
|ModPurpose=Das Modul wurde entworfen um den gesamten Heim-/Hausstatus in einem Gerät abzubilden und viele grundlegende Automationen durch Hinzufügen weiterer Geräte bereitzustellen.&lt;br /&gt;
|ModType=h&lt;br /&gt;
|ModCmdRef=HOMEMODE&lt;br /&gt;
|ModFTopic=64317&lt;br /&gt;
|ModForumArea=Automatisierung&lt;br /&gt;
|ModTechName=22_HOMEMODE.pm&lt;br /&gt;
|ModOwner=DeeSPe&lt;br /&gt;
}}&lt;br /&gt;
Diese Seite beschreibt die Konfiguration und Verwendung des Moduls &#039;&#039;22_HOMEMODE.pm&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
=Allgemeines=&lt;br /&gt;
Das Modul &#039;&#039;22_HOMEMODE.pm&#039;&#039; wurde entworfen um den gesamten Heim-/Hausstatus in einem Gerät abzubilden.&amp;lt;br&amp;gt;&lt;br /&gt;
Die hier aufgeführte Anleitung entspricht dem Modul in Version 1.4.2.&lt;br /&gt;
&lt;br /&gt;
Viele allgemein typische Automationen sind bereits fertig integriert.&lt;br /&gt;
&lt;br /&gt;
Die jeweils per Event auszuführenden Befehle können in den entsprechenden &#039;&#039;HomeCMD...&#039;&#039; Atributen hinterlegt werden und so in der Detail Ansicht des HOMEMODE Geräts übersichtlich angezeigt und bearbeitet werden.&lt;br /&gt;
&lt;br /&gt;
Das Anlegen vieler notify/DOIF ist durch den Einsatz von &#039;&#039;HOMEMODE&#039;&#039; unnötig.&lt;br /&gt;
&lt;br /&gt;
Zusätzlich wurde das Modul für die Verwendung mit HomeKit als GUI optimiert. Alle möglichen Mappings für Homebridge sind bereits enthalten und können über einen set Befehl aktualisiert werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:HOMEMODE_Device.png|800px]]&lt;br /&gt;
&lt;br /&gt;
==Voraussetzungen==&lt;br /&gt;
Um Modul &#039;&#039;22_HOMEMODE.pm&#039;&#039; benutzen zu können benötigt man als Mindestvoraussetzung ein bereits angelegtes RESIDENTS Gerät mit entsprechenden ROOMMATE/GUEST Geräten.&lt;br /&gt;
&lt;br /&gt;
==Mögliche Automationen==&lt;br /&gt;
Alle Automationen sind optional.&lt;br /&gt;
&lt;br /&gt;
Hier ein paar Beispiele:&lt;br /&gt;
*Änderung des Zustands von ROOMMATE/GUEST Geräten anhand von PRESENCE Geräten&lt;br /&gt;
*Bereitstellung von CMD Attributen für mögliche Events rund um den Heim-/Hausstatus&lt;br /&gt;
*Bereitstellung von Platzhaltern innerhalb der CMD Attribute, z.B. %MODE%, %SEASON% oder %PREVMODE% für die Werte der Readings mode, season und prevMode&lt;br /&gt;
*Einbindung von Kontakt Sensoren, für z.B. Offen-Warnungen nach bestimmten Zeitraum oder Alarm Meldungen in bestimmten Alarm Modus - kann pro Kontakt Sensor konfiguriert werden&lt;br /&gt;
*Einbindung von Bewegungs Sensoren, für z.B. automatische Licht Schaltungen oder Alarm Meldungen in bestimmten Alarm Modus - kann pro Bewegungs Sensor konfiguriert werden&lt;br /&gt;
*Darstellungen und Auslösen von Sabotage Alarmen der eingebundenen Kontakt- und Bewegungssensoren&lt;br /&gt;
*Einbindung von jeweils einem Temperatur und Luftfeuchtigkeitssensor&lt;br /&gt;
*Einbindung eines lokalen Wetter Devices zur Ermittlung und Ausgabe der lokalen Wetterdaten und Erzeugung der Wettervorhersage&lt;br /&gt;
*Einbindung von Power und Energy Sensoren zur Ermittlung der Gesamtmengen&lt;br /&gt;
*Einbindung von Calendar/holiday Devices für spezielle im HOMEMODE Device verfügbar zu machende Events&lt;br /&gt;
*von Uhrzeit abhängiger Anwesend-Modus&lt;br /&gt;
*Bewohner unabhängige Tageszeit-Modus&lt;br /&gt;
*Alarm-Modus&lt;br /&gt;
*DND-Modus&lt;br /&gt;
*Überwachung von Batteriewerten&lt;br /&gt;
&lt;br /&gt;
=HOMEMODE-Gerät=&lt;br /&gt;
==Definition==&lt;br /&gt;
Das HOMEMODE Gerät - hier mit dem Namen &#039;&#039;Home&#039;&#039; versehen - selbst wird über&lt;br /&gt;
 define Home HOMEMODE&lt;br /&gt;
bei Vorhandensein nur eines RESIDENTS Geräts definiert.&lt;br /&gt;
&lt;br /&gt;
Bei Verwendung mehrerer RESIDENTS Geräte muss das Master RESIDENTS Gerät beim Definieren mit angegeben werden&lt;br /&gt;
 define Home HOMEMODE rgr_Residents&lt;br /&gt;
Dieses Modul verwendet das globale Attribut &#039;&#039;language&#039;&#039; zur Bestimmung der Anzeigedaten (Standard: EN=english). Für deutsche Ausgabedaten kann das Attribut&lt;br /&gt;
 attr global language DE&lt;br /&gt;
gesetzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Alternativ kann auch nur das HOMEMODE Gerät auf deutsch geändert werden&lt;br /&gt;
 attr Home HomeLanguage DE&lt;br /&gt;
&lt;br /&gt;
==Set-Befehle==&lt;br /&gt;
&#039;&#039;set &amp;lt;required&amp;gt; [optional]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 set Home anyoneElseAtHome &amp;lt;on/off&amp;gt;&lt;br /&gt;
einschalten wenn jemand anderes zu Hause ist der kein registrierter ROOMMATE/GUEST ist, z.B. Hund/Katze oder unregistrierte Gäste&amp;lt;br&amp;gt;&lt;br /&gt;
wenn eingeschaltet, dann wird der Alarm Mode beim Verlassen statt auf armaway nur auf armhome gestellt&amp;lt;br&amp;gt;&lt;br /&gt;
schaltet man ein und hat schon Haus/Wohnung verlassen, so wird der Alarm Mode von armaway auf armhome gestellt&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%AEAH%&#039;&#039;&#039; ist in allen HomeCMD Attributen verfügbar&lt;br /&gt;
&lt;br /&gt;
 set Home dnd &amp;lt;on/off&amp;gt;&lt;br /&gt;
schaltet den &amp;quot;Bitte nicht stören&amp;quot; Modus ein&amp;lt;br&amp;gt;&lt;br /&gt;
z.B. um Benachrichtigungen zu deaktivieren&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%DND%&#039;&#039;&#039; ist in allen HomeCMD Attributen verfügbar&lt;br /&gt;
&lt;br /&gt;
 set Home dnd-for-minutes &amp;lt;MINUTES&amp;gt;&lt;br /&gt;
schaltet den &amp;quot;Bitte nicht stören&amp;quot; Modus für die angegebenen Minuten ein&amp;lt;br&amp;gt;&lt;br /&gt;
kehrt danach zum vorherigen (tageszeitabhängigen) Modus zurück&lt;br /&gt;
&lt;br /&gt;
 set Home deviceDisable &amp;lt;DEVICE&amp;gt;&lt;br /&gt;
deaktiviert das Gerät für sämtliche HOMEMODE Automationen&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%DISABLED%&#039;&#039;&#039; ist in allen HomeCMD Attributen verfügbar&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%DEVICE%&#039;&#039;&#039; und &#039;&#039;&#039;%ALIAS%&#039;&#039;&#039; sind in allen HomeCMD Attributen verfügbar&lt;br /&gt;
&lt;br /&gt;
 set Home deviceEnable &amp;lt;DEVICE&amp;gt;&lt;br /&gt;
reaktiviert das Gerät für sämtliche HOMEMODE Automationen&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%DISABLED%&#039;&#039;&#039; ist in allen HomeCMD Attributen verfügbar&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%DEVICE%&#039;&#039;&#039; und &#039;&#039;&#039;%ALIAS%&#039;&#039;&#039; sind in allen HomeCMD Attributen verfügbar&lt;br /&gt;
&lt;br /&gt;
 set Home location &amp;lt;arrival/home/bed/underway/wayhome&amp;gt;&lt;br /&gt;
manueller Ortswechsel&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%LOCATION%&#039;&#039;&#039; ist in allen HomeCMD Attributen verfügbar&lt;br /&gt;
&lt;br /&gt;
 set Home mode &amp;lt;morning/day/afternoon/evening/night/gotosleep/asleep/absent/gone/home&amp;gt;&lt;br /&gt;
manueller Moduswechsel&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%MODE%&#039;&#039;&#039; und &#039;&#039;&#039;%PREVMODE%&#039;&#039;&#039; sind in allen HomeCMD Attributen verfügbar&lt;br /&gt;
&lt;br /&gt;
 set Home modeAlarm &amp;lt;armaway/armhome/armnight/disarm&amp;gt;&lt;br /&gt;
schaltet den angegebenen Alarm Modus ein&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%AMODE%&#039;&#039;&#039; und &#039;&#039;&#039;%PREVAMODE%&#039;&#039;&#039; sind in allen HomeCMD Attributen verfügbar&lt;br /&gt;
&lt;br /&gt;
 set Home modeAlarm-for-minutes &amp;lt;armaway/armhome/armnight/disarm&amp;gt; &amp;lt;MINUTES&amp;gt;&lt;br /&gt;
schaltet den angegebenen Alarm Modus für die angegebenen Minuten ein&lt;br /&gt;
kehrt danach zum vorherigen Alarm Modus zurück&lt;br /&gt;
&lt;br /&gt;
 set Home updateHomebridgeMapping&lt;br /&gt;
aktualisiert das Attribut homebridgeMapping des HOMEMODDE Device abhängig von den verfügbaren Informationen&lt;br /&gt;
&lt;br /&gt;
 set Home updateInternalForce&lt;br /&gt;
führt eine Aktualisierung der Internals des HOMEMODE Device aus&amp;lt;br&amp;gt;&lt;br /&gt;
das sollte manuell benutzt werden nachdem das Modul aktualisiert und nur ein reload statt restart gemacht wurde&amp;lt;br&amp;gt;&lt;br /&gt;
auch wenn man überwachte/kontrollierte Geräte ändert sollte man diesen Befehl manuell ausführen, z.B. neue ROOMMATE/GUEST im RESIDENTS Device hinzufügt, oder Geräte in FHEM hinzufügt die dem selben Devspec wie bisher entsprechen (Steckdosen, Sensoren)&lt;br /&gt;
&lt;br /&gt;
==Get-Befehle==&lt;br /&gt;
&#039;&#039;get &amp;lt;required&amp;gt; [optional]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 get Home contactsOpen &amp;lt;all/doorsinside/doorsoutside/doorsmain/outside/windows&amp;gt;&lt;br /&gt;
Liste von all/doorsinside/doorsoutside/doorsmain/outside/windows offenen Kontakten&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%OPEN%&#039;&#039;&#039;, &#039;&#039;&#039;%OPENCT%&#039;&#039;&#039; und &#039;&#039;&#039;%OPENHR%&#039;&#039;&#039; sind in allen HomeCMD Attributen verfügbar&lt;br /&gt;
&lt;br /&gt;
 get Home devicesDisabled&lt;br /&gt;
Anzeige der für HOMEMODE deaktivierten Geräte&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%DISABLED%&#039;&#039;&#039; ist in allen HomeCMD Attributen verfügbar&lt;br /&gt;
&lt;br /&gt;
 get Home mode&lt;br /&gt;
Anzeige von mode&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%MODE%&#039;&#039;&#039; ist in allen HomeCMD Attributen verfügbar&lt;br /&gt;
&lt;br /&gt;
 get Home modeAlarm&lt;br /&gt;
Anzeige von modeAlarm&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%AMODE%&#039;&#039;&#039; und &#039;&#039;&#039;%MODEALARM%&#039;&#039;&#039; sind in allen HomeCMD Attributen verfügbar&lt;br /&gt;
&lt;br /&gt;
 get Home publicIP&lt;br /&gt;
holen der öffentlichen IP Adresse&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%IP%&#039;&#039;&#039; ist in allen HomeCMD Attributen verfügbar&lt;br /&gt;
&lt;br /&gt;
 get Home sensorsTampered&lt;br /&gt;
Liste aller sabotierten Sensoren&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%TAMPERED%&#039;&#039;&#039;, &#039;&#039;&#039;%TAMPEREDCT%&#039;&#039;&#039; und &#039;&#039;&#039;%TAMPEREDHR%&#039;&#039;&#039; sind in allen HomeCMD Attributen verfügbar&lt;br /&gt;
&lt;br /&gt;
 get Home weather &amp;lt;long/short&amp;gt;&lt;br /&gt;
Wetterinfo im angegebenen Format anzeigen&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%WEATHER%&#039;&#039;&#039; und &#039;&#039;&#039;%WEATHERLONG%&#039;&#039;&#039; sind in allen HomeCMD Attributen verfügbar&lt;br /&gt;
&lt;br /&gt;
 get Home weatherForecast [TAG]&lt;br /&gt;
Wettervorhersage für angegebenen Tag&amp;lt;br&amp;gt;&lt;br /&gt;
wenn kein Tag angegeben wird, so wird die Vorhersage für morgen (2) ausgegeben&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%FORECAST%&#039;&#039;&#039; (morgen) und &#039;&#039;&#039;%FORECASTTODAY%&#039;&#039;&#039; (heute) sind in allen HomeCMD Attributen verfügbar&lt;br /&gt;
&lt;br /&gt;
==webCmd==&lt;br /&gt;
Die Schaltmöglichkeiten sind absichtlich gering gehalten, denn im normalen Betrieb sollte nicht mehr benötigt werden als die hier gebotenen.&amp;lt;br&amp;gt;&lt;br /&gt;
Es lässt sich der Alarm Mode manuell umschalten und beim Klick auf das devStateIcon wird der DND Mode an- und ausgeschaltet.&lt;br /&gt;
&lt;br /&gt;
=Konfiguration=&lt;br /&gt;
&lt;br /&gt;
==Grundkonfiguration==&lt;br /&gt;
&lt;br /&gt;
Diese Grundkonfiguration sollte immer als erstes erfolgen um entsprechend darauf weiter aufzubauen. Als zweiter Schritt ist dann die erweiterte Konfiguration angedacht.&lt;br /&gt;
&lt;br /&gt;
Bei der Namensvergabe der Attribute vom HOMEMODE Device wurde nach einem möglichst kurzem Prefix gesucht und nach vielen Tests wurde sich für das Prefix &amp;quot;Home&amp;quot; entschieden. Das hat den Vorteil, dass alle Attribute beisammen stehen und diese auch (durch den Großbuchstaben am Anfang) ziemlich weit oben in der Liste der Attribute stehen. Ebenso wurde bei der Namensvergabe versucht, selbsterklärende Namen zu wählen. Das hat den Vorteil, dass man relativ einfach genau erkennen kann wofür das Attribut steht, allerdings auch den Nachteil, dass einige Attributnamen ganz schön lang werden.&lt;br /&gt;
&lt;br /&gt;
===Attribute===&lt;br /&gt;
&lt;br /&gt;
====HomeAdvancedUserAttr====&lt;br /&gt;
Als Erstes wird empfohlen, gerade für Anfänger, das Attribut &amp;quot;HomeAdvancedUserAttr&amp;quot; auf 1 zu setzen. Dadurch werden viel mehr HomeCMD Attribute freigeschaltet. Diese werden im Attribut userattr des HOMEMODE Device hinzugefügt.&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: 0&lt;br /&gt;
&lt;br /&gt;
====HomeAutoAlarmModes====&lt;br /&gt;
Als Nächstes sollte man sich entscheiden, ob die Alarm Modus evtl. nicht automatisch zum jeweiligen Modus des HOMEMODE Device geschaltet werden sollen. Standardmäßig werden die Alarm Modus automatisch gesteuert. Ist das nicht erwünscht, so ist der Wert dieses Attributs auf 0 zu setzen.&amp;lt;br&amp;gt;&lt;br /&gt;
Bei Modus &amp;quot;absent&amp;quot; des HOMEMODE Device wird automatisch auf &amp;quot;armaway&amp;quot; geschaltet.&amp;lt;br&amp;gt;&lt;br /&gt;
Bei Modus &amp;quot;home&amp;quot; des HOMEMODE Device wird automatisch auf &amp;quot;disarm&amp;quot; geschaltet.&amp;lt;br&amp;gt;&lt;br /&gt;
Bei Modus &amp;quot;asleep&amp;quot; des HOMEMODE Device wird automatisch auf &amp;quot;armnight&amp;quot; geschaltet.&amp;lt;br&amp;gt;&lt;br /&gt;
Alarm Modus &amp;quot;armhome&amp;quot; kann nur manuell gesetzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: 0 oder 1&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: 1&lt;br /&gt;
&lt;br /&gt;
====HomeAutoArrival====&lt;br /&gt;
Ist hier ein Wert größer 0 angegeben, so wird bei Ankunft jedes ROOMMATE/GUEST die location des jeweiligen ROOMMATE/GUEST für die hier angegeben Zeit in Minuten auf &amp;quot;arrival&amp;quot; gesetzt. Beim ersten nach Hause kommenden ROOMMATE/GUEST wird zusätzlich die location des HOMEMODE Device für die hier eingestellte Zeit in Minuten auf &amp;quot;arrival&amp;quot; gesetzt.&amp;lt;br&amp;gt;&lt;br /&gt;
Nach Ablauf der hier eingestellten Minuten wechselt das jeweilige Device von &amp;quot;arrival&amp;quot; auf &amp;quot;home&amp;quot;, sofern es noch die location &amp;quot;arrival&amp;quot; hat.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: 0 bis 5999.9&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: 0&lt;br /&gt;
&lt;br /&gt;
====HomeAutoAsleep====&lt;br /&gt;
Ist hier ein Wert größer 0 angegeben, so wird beim Schlafengehen (gotosleep) jedes ROOMMATE/GUEST ein Timer gestartet, der den jeweiligen ROOMMATE/GUEST nach der hier angegeben Zeit in Minuten auf &amp;quot;asleep&amp;quot; setzt.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: 0 bis 5999.9&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: 0&lt;br /&gt;
&lt;br /&gt;
====HomeAutoAwoken====&lt;br /&gt;
Ist hier ein Wert größer 0 angegeben, so wird beim Erwachen (&amp;quot;awoken&amp;quot; oder &amp;quot;home nach asleep&amp;quot;) jedes ROOMMATE/GUEST dieser auf &amp;quot;awoken&amp;quot; gesetzt und ein Timer gestartet, der den jeweiligen ROOMMATE/GUEST nach der hier angegeben Zeit in Minuten auf &amp;quot;home&amp;quot; setzt.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: 0 bis 5999.9&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: 0&lt;br /&gt;
&lt;br /&gt;
====HomeAutoDaytime====&lt;br /&gt;
Standardmäßig wird mode anhand der Tageszeit automatisch gesetzt. Ist das nicht gewünscht, kann das über den Wert 0 deaktiviert werden. Dann stehen allerdings tageszeitabhängigen mode(s) nicht mehr zur Verfügung.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: 0 oder 1&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: 1&lt;br /&gt;
&lt;br /&gt;
====HomeResidentCmdDelay====&lt;br /&gt;
Normalerweise werden die Events der ROOMMATE/GUEST vor denen des HOMEMODE Device ausgeführt. Um das zu ändern wird die Ausführung der ROOMMATE/GUEST HomeCMD Attribute um die hier eingestellte Zeit in Sekunden verzögert.&amp;lt;br&amp;gt;&lt;br /&gt;
Je genauer der Name des jeweiligen HomeCMD Attributs beschrieben wird, desto später wird dieser ausgeführt.&amp;lt;br&amp;gt;&lt;br /&gt;
Das heißt z.B. dass HomeCMDmode vor HomeCMDmode-absent und dieser wiederrum vor HomeCMDmode-absent-ROOMMATE/GUEST-NAME ausgeführt wird usw.&amp;lt;br&amp;gt;&lt;br /&gt;
Um das normale Verhalten wiederherzustellen ist der Wert dieses Attributs auf 0 zu setzen. Dann wird HomeCMDmode-absent-ROOMMATE/GUEST-NAME vor HomeCMDmode-absent und vor HomeCMDmode ausgeführt.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: 0 bis unendlich in Sekunden&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: 1&lt;br /&gt;
&lt;br /&gt;
==Konfiguration Presence Devices (automatische anwesend/abwesend Umschaltung von ROOMMATE/GUEST)==&lt;br /&gt;
Damit die automatische Zuordnung der Presence Devices zu ihren ROOMMATE/GUEST Devices zuverlässig funktioniert, ist es nötig dass der Hauptteil des Namens des ROOMMATE/GUEST innerhalb des Namens des zugehörigen PRESENCE Device(s) vorkommt.&amp;lt;br&amp;gt;&lt;br /&gt;
Im Attribut HomePresenceDeviceType kann man den zu suchenden TYPE von Presence Device vorgeben.&amp;lt;br&amp;gt;&lt;br /&gt;
Per Default werden nur Devices vom TYPE PRESENCE gesucht und versucht den ROOMMATE/GUEST zuzuweisen.&amp;lt;br&amp;gt;&lt;br /&gt;
Falls man z.B. auch Devices vom TYPE dummy zur Anwesenheitssteuerung benutzt, kann man diese im Attribut HomePresenceDeviceType mit hinzunehmen. Es sind alles Device TYPEn möglich die ein &amp;quot;presence&amp;quot; Reading mit den Werten &amp;quot;present/appeared&amp;quot; und &amp;quot;absent/disappeared&amp;quot; bereitstellen. Mehrere TYPEn sind möglich da in diesem Attribut ein Regex erwartet wird. z.B.: dummy oder PRESENCE|dummy oder PRESENCE|dummy|ONKYO_AVR.&lt;br /&gt;
&lt;br /&gt;
===Beispiel===&lt;br /&gt;
Der Device Name meines ROOMMATE ist &amp;quot;rr_Dan&amp;quot;.&amp;lt;br&amp;gt;&lt;br /&gt;
Auf der Suche nach dem zugehörigen Presence Device wird der erste Teil (rr_ oder rg_) weggeschnitten und der Rest in Kleinbuchstaben umgewandelt.&amp;lt;br&amp;gt;&lt;br /&gt;
Mit dem was übrig bleibt, bei mir also nur dan, werden die möglichen Presence Devices versucht zu erkennen.&amp;lt;br&amp;gt;&lt;br /&gt;
Mein zugehöriges Presence Device heißt, historisch gewachsen, PRESENCE_rr_Dan und würde somit problemlos zugeordnet werden können.&amp;lt;br&amp;gt;&lt;br /&gt;
Die Namen der zugehörigen Presence Devives könnten in ihrer kürzesten Form auch wie folgt sein um meinen ROOMMATE/GUEST Device zugeordnet zu werden:&amp;lt;br&amp;gt;&lt;br /&gt;
 pdan&lt;br /&gt;
 danp&lt;br /&gt;
 ZDan&lt;br /&gt;
 DANZ&lt;br /&gt;
 wenndannsonst&lt;br /&gt;
Aber Achtung, es funktioniert nicht mehr wenn die Namen nicht eindeutig sind. Wenn es z.B. eine rr_Dana geben würde mit Presence Device Name &amp;quot;pdani&amp;quot;, dann würde dieser Name auch bei mir (dan) passen. Das könnte man aber auch bewußt nutzen um mit einem Presence Device 2 ROOMMATE/GUEST Devices gleichzeitig zu steuern.&amp;lt;br&amp;gt;&lt;br /&gt;
Wenn die Namen wirklich absolut eindeutig sind, dann könnte man den Regex im Attribut HomePresenceDeviceType sogar auf &amp;quot;.*&amp;quot; setzen.&lt;br /&gt;
&lt;br /&gt;
Werden pro ROOMMATE/GUEST mehrere Presence Devices gefunden und zugeordnet, so wird automatisch dass Attribut HomePresenceDeviceAbsentCount-&amp;lt;NAME-ROOMMATE/GUEST&amp;gt; auf die Anzahl der gefundenen Presence Devices gesetzt, so dass der/die jeweilige ROOMMATE/GUEST immer erst als abwesend gewertet wird sobald alle zugehörigen Presence Devices abwesend sind. Analog dazu gibt es noch das Attribut HomePresenceDevicePresentCount-&amp;lt;NAME-ROOMMATE/GUEST&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Attribute===&lt;br /&gt;
&lt;br /&gt;
====HomeAutoPresence====&lt;br /&gt;
Ist dieses Attribut auf 1 gesetzt, so werden die ROOMMATE/GUEST Devices automatisch zum Status ihrer zugehörigen PRESENCE Devices geschaltet.&amp;lt;br&amp;gt;&lt;br /&gt;
PRESENCE Device present - ROOMMATE/GUEST home&amp;lt;br&amp;gt;&lt;br /&gt;
PRESENCE Device absent - ROOMMATE/GUEST absent&amp;lt;br&amp;gt;&lt;br /&gt;
Falls es sich bei den von Euch benutzen PRESENCE Devices nicht um Devices vom TYPE PRESENCE handeln sollte, sondern z.B. um PRESENCE und dummy, so kann dieses im Attribut HomePresenceDeviceType als Regex konfiguriert werden! z.B.: PRESENCE|dummy&amp;lt;br&amp;gt;&lt;br /&gt;
Damit ein Device als Presence Device erkannt werden kann, muss dieses über ein presence Reading verfügen.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: 0 oder 1&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: 0&lt;br /&gt;
&lt;br /&gt;
====HomeAutoPresenceSuppressState====&lt;br /&gt;
unterdrücke Anwesenheitsänderung in angegebenen State(s) der RESIDENTS&amp;lt;br&amp;gt;&lt;br /&gt;
z.B. für &amp;quot;mysteriös&amp;quot; verschwindende Anwesenheitsgeräte in der Nacht&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: asleep|awoken|gotosleep&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomePresenceDeviceType====&lt;br /&gt;
Regex des TYPEs/der TYPEn von Presence Devices&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: Regex der Device TYPEn&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: PRESENCE&lt;br /&gt;
&lt;br /&gt;
==Erweiterte Konfiguration==&lt;br /&gt;
Um das HOMEMODE Device vollumfänglich zu benutzen ist es sinnvoll weitere Devices (zur Überwachung) hinzuzufügen.&lt;br /&gt;
&lt;br /&gt;
Die bereits möglichen hinzuzufügenden Devices werden hier folgend nach Attributnamen erklärt.&lt;br /&gt;
&lt;br /&gt;
===Attribute zum Hinzufügen weiterer Geräte===&lt;br /&gt;
&lt;br /&gt;
====HomeEventsCalendarDevices====&lt;br /&gt;
Hier ist ein Devspec von holiday/Calendar Device(s) anzugeben.&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;Es wird empfohlen die holiday/Calendar Namen in Großbuchstaben anzulegen, da dann die daraus resultierenden Platzhalter ebenfalls Großbuchstaben sind und somit zu den anderen Platzhaltern passen.&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Es werden alle Typen von holiday Events (1,2,3,4,5) unterstützt.&amp;lt;br&amp;gt;&lt;br /&gt;
Bei Calendar sind auch gleichzeitig startende/laufende Events möglich, sie müssen nur unterschiedliche Titel haben (summary).&amp;lt;br&amp;gt;&lt;br /&gt;
Der jeweilige Event Text kann auch Leerzeichen enthalten, welche in den HomeCMD Attributen durch Bindestriche (-) ersetzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Diese Devices stellen zusätzlich die Platzhalter &#039;&#039;&#039;%CALENDAR%&#039;&#039;&#039;, &#039;&#039;&#039;%EVENT%&#039;&#039;&#039; und &#039;&#039;&#039;%PREVEVENT%&#039;&#039;&#039; in den HomeCMDevent Attributen zur Verfügung. &#039;&#039;&#039;%CALENDAR%&#039;&#039;&#039; wird dann durch den Namen, &#039;&#039;&#039;%EVENT%&#039;&#039;&#039; durch das aktuelle Event und &#039;&#039;&#039;%PREVEVENT%&#039;&#039;&#039; durch das vorherige Event des jeweiligen Kalenders ersetzt.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Devspec von holiday/Calendar Geräten&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomeEventsHolidayDevices====&lt;br /&gt;
Hier ist ein Devspec von holiday/Calendar Device(s) anzugeben.&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;Es wird empfohlen die holiday/Calendar Namen in Großbuchstaben anzulegen, da dann die daraus resultierenden Platzhalter ebenfalls Großbuchstaben sind und somit zu den anderen Platzhaltern passen.&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Es werden alle Typen von holiday Events (1,2,3,4,5) unterstützt.&amp;lt;br&amp;gt;&lt;br /&gt;
Bei Calendar sind auch gleichzeitig startende/laufende Events möglich, sie müssen nur unterschiedliche Titel haben (summary).&amp;lt;br&amp;gt;&lt;br /&gt;
Der jeweilige Event Text kann auch Leerzeichen enthalten, welche in den HomeCMD Attributen durch Bindestriche (-) ersetzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Diese Devices stellen zusätzlich die Platzhalter &#039;&#039;&#039;%CALENDAR%&#039;&#039;&#039;, &#039;&#039;&#039;%EVENT%&#039;&#039;&#039; und &#039;&#039;&#039;%PREVEVENT%&#039;&#039;&#039; in den HomeCMDevent Attributen zur Verfügung. &#039;&#039;&#039;%CALENDAR%&#039;&#039;&#039; wird dann durch den Namen, &#039;&#039;&#039;%EVENT%&#039;&#039;&#039; durch das aktuelle Event und &#039;&#039;&#039;%PREVEVENT%&#039;&#039;&#039; durch das vorherige Event des jeweiligen Kalenders ersetzt.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Devspec von holiday/Calendar Geräten&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomeSensorAirpressure====&lt;br /&gt;
Luftdrucksensor aussen&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Name des Sensors&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomeSensorHumidityOutside====&lt;br /&gt;
Hier ist der Name des (Haupt)Aussensensors für Luftfeuchtigkeit anzugeben. Dieser muss ein Reading humidity besitzen.&amp;lt;br&amp;gt;&lt;br /&gt;
Falls der Sensor für (Aussen)Luftfeuchtigkeit und Aussentemperatur ein und der selbe ist, so muss dieser nur einmalig im Attribut HomeSensorTemperatureOutside hinterlegt werden. Dieser muss dann die beiden Readings humidity und temperature haben. Im Bedarfsfall können diese Readings auch vorher entsprechend durch eigene userReadings erstellt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Dieser Sensor stellt den Platzhalter &#039;&#039;&#039;%HUMIDITY%&#039;&#039;&#039; für den Wert des Readings humidity zur Verfügung.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Device Name mit Reading humidity&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomeSensorTemperatureOutside====&lt;br /&gt;
Hier ist der Name des (Haupt)Aussentemperatursensors anzugeben. Dieser muss mindestens ein Reading temperature besitzen.&amp;lt;br&amp;gt;&lt;br /&gt;
Falls der Sensor für Aussentemperatur auch ein Reading humidity besitzen sollte und dieses auch der Sensor für die Aussenlufteuchtigkeit ist, so muss dieser nur einmalig hier in diesem Attribut hinterlegt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Dieser Sensor stellt den Platzhalter &#039;&#039;&#039;%TEMPERATURE%&#039;&#039;&#039; für den Wert des Readings temperature zur Verfügung.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Device Name mit Reading temperature und optional humidity&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsContact====&lt;br /&gt;
Hier können alle Kontakt Sensoren als Devspec hinterlegt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Diese Devices stellen zusätzlich die Platzhalter &#039;&#039;&#039;%ALIAS%&#039;&#039;&#039;, &#039;&#039;&#039;%SENSOR%&#039;&#039;&#039; und &#039;&#039;&#039;%STATE%&#039;&#039;&#039; in den HomeCMDcontact Attributen zur Verfügung. &#039;&#039;&#039;%ALIAS%&#039;&#039;&#039; wird dann durch den Alias, &#039;&#039;&#039;%SENSOR%&#039;&#039;&#039; durch den Namen und &#039;&#039;&#039;%STATE%&#039;&#039;&#039; durch den aktuellen state des zuletzt ausgelösten Kontakts ersetzt.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Devspec&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;In meinem Falle sind das optische und magnetische Kontaktsensoren vom HomeMatic. HM-SEC-SCO und HM-SEC-SC-2.&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;Darum ist bei mir als Devspec &#039;&#039;&#039;model=HM-SEC-SC(O|-2)&#039;&#039;&#039; eingetragen um alle diese Kontaktsensoren zu erfassen.&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Nach Übernehmen des Attributs werden alle gefundenen Kontaktsensoren mit ihren Namen im Internal SENSORSCONTACT des HOMEMODE Device einzeln aufgelistet und können dort auch direkt angeklickt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Des weiteren werden beim Übernehmen dieses Attributs jedem Kontaktsensor folgende Attribute im Attribut userattr hinzugefügt:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====HomeContactType=====&lt;br /&gt;
Typ des Kontakts - wird versucht anhand des Namen/Alias beim Hinzufügen zum HOMEMODE Device zu ermitteln, sollte jedoch für jeden Kontaktsensor einzeln überprüft werden&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: doorinside,dooroutside,doormain,window&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: vorgegebene Werteauswahl&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: window&lt;br /&gt;
&lt;br /&gt;
=====HomeModeAlarmActive=====&lt;br /&gt;
Regex der Alarm Mode(s) in denen der Kontaktsensor eine erfolgte Öffnung als Alarm melden soll.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: armaway|armhome|armnight&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Regex von Alarm Modes&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: armaway&lt;br /&gt;
&lt;br /&gt;
=====HomeOpenDontTriggerModes=====&lt;br /&gt;
Regex der Mode(s) des HOMEMODE Device in denen keine Offen Warnungen erfolgen sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Ist ein Kontakt geöffnet während die hier eingestellten Mode(s) eintreten, so wird der noch bestehende Timer abgebrochen. Entgegengesetzt startet er wieder sobal die hier eingestellten Mode(s) verlassen werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Ist hier z.B. &amp;quot;gotosleep|asleep&amp;quot; eingestellt, so kann man z.B. das Fenster schon vor dem Auslösen von gotosleep oder asleep öffnen und der bestehende Offenwarnung-Timer wird dann abgebrochen. Sobald man am Morgen z.B. awoken oder home auslöst, so wird ein neuer Timer gestartet der einen dann an das noch offene Fenster erinnert.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: alle Modes des HOMEMODE Device&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Regex von Modes&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
=====HomeOpenDontTriggerModesResidents=====&lt;br /&gt;
Devspec der ROOMMATE/GUEST Devices deren Status statt der Modes des HOMEMODE Device für Attribut HomeOpenDontTriggerModes benutzt werden soll.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: alle überwachten ROOMMATE/GUEST&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Devspec&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
=====HomeOpenMaxTrigger=====&lt;br /&gt;
Maximale Anzahl an Warnmeldungen&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: 0 bis ~&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: ganze Zahl&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
=====HomeOpenTimes=====&lt;br /&gt;
Leerzeichenseparierte Liste von Offen Warnung Zeiten in Minuten.&amp;lt;br&amp;gt;&lt;br /&gt;
Der erste Wert entspricht der ersten Zeit, der zweite Wert der zweiten Zeit usw.&amp;lt;br&amp;gt;&lt;br /&gt;
Die Anzahl sollte dem Wert im Attribut HomeOpenMaxTrigger entsprechen. Wenn hier weniger Zeiten vorgegeben werden, so wird für weitere Offen Warnungen immer die letzte hier angegebene Zeit verwendet.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: leerzeichenseparierte Liste von Zahlen mit einer Kommmastelle, z.B. 2.5&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: 10&lt;br /&gt;
&lt;br /&gt;
=====HomeOpenTimesDividers=====&lt;br /&gt;
Leerzeichenseparierte Liste von Offenwarnzeit Teilern.&amp;lt;br&amp;gt;&lt;br /&gt;
Es müssen so viele Werte angegeben werden wie in HomeSeasons Jahreszeiten hinterlegt worden sind (Default 4).&amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer normalen Offenwarnzeit von 10 Minuten und den hier anzugebenen Teilern z.B. &amp;quot;2 1 2 3&amp;quot; ergeben sich für Frühling und Herbst Offenwarnzeiten von jeweils 5 Minuten und im Winter 3.3 Minuten.&amp;lt;br&amp;gt;&lt;br /&gt;
Die hier eingetragenen Werte überschreiben die Werte aus dem Attribut HomeSensorsContactOpenTimeDividers des HOMEMODE Device.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: leerzeichenseparierte Liste von Zahlen mit einer Kommmastelle, z.B. 2 1 2 2.5&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
=====HomeReadings=====&lt;br /&gt;
Zwei leerzeichenseparierte Readings für open und sabotage Status.&amp;lt;br&amp;gt;&lt;br /&gt;
Die hier eingetragenen Readings überschreiben die Werte aus dem Attribut HomeSensorsContactReadings des HOMEMODE Device.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: zwei Wörter&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: state sabotageError&lt;br /&gt;
&lt;br /&gt;
=====HomeValues=====&lt;br /&gt;
Regex der Werte die für offen und sabotiert stehen.&amp;lt;br&amp;gt;&lt;br /&gt;
Die hier eingetragenen Werte überschreiben die Werte aus dem Attribut HomeSensorsContactValues des HOMEMODE Device.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Regex&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: open|tilted|on&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsContactReadings====&lt;br /&gt;
Zwei leerzeichenseparierte Readings für open und sabotage Status.&amp;lt;br&amp;gt;&lt;br /&gt;
Die hier eingetragenen Readings sind global für alle Kontaktsensoren, können aber durch setzen des Attributs HomeReadings in jedem Sensor überschrieben werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: zwei Wörter&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: state sabotageError&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsContactValues====&lt;br /&gt;
Regex der Werte die für offen und sabotiert stehen.&amp;lt;br&amp;gt;&lt;br /&gt;
Die hier eingetragenen Werte sind global für alle Kontaktsensoren, können aber durch setzen des Attributs HomeValues in jedem Sensor überschrieben werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Regex&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: open|tilted|on&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsContactOpenTimeDividers====&lt;br /&gt;
Leerzeichenseparierte Liste von Offenwarnzeit Teilern.&amp;lt;br&amp;gt;&lt;br /&gt;
Es müssen so viele Werte angegeben werden wie in HomeSeasons Jahreszeiten hinterlegt worden sind (Default 4).&amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer normalen Offenwarnzeit von 10 Minuten und den hier anzugebenen Teilern z.B. &amp;quot;2 1 2 3&amp;quot; ergeben sich für Frühling und Herbst Offenwarnzeiten von jeweils 5 Minuten und im Winter 3.3 Minuten.&amp;lt;br&amp;gt;&lt;br /&gt;
Die hier eingetragenen Werte sind global für alle Kontaktsensoren, können aber durch setzen des Attributs HomeOpenTimesDividers in jedem Sensor überschrieben werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: leerzeichenseparierte Liste von Zahlen mit max. einer Kommmastelle, z.B. 2 1 2 2.5 (für 4 Jahreszeiten)&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsContactOpenTimeMin====&lt;br /&gt;
Minimale Zeit in Minuten die mindestens für eine Offenwarnung gewartet werden soll - im Falle dass sich durch den Teiler evtl. zu kleine Werte ergeben.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: eine Zahle mit max. einer Kommmastelle, z.B. 2.5&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsContactOpenTimes====&lt;br /&gt;
Leerzeichenseparierte Liste von Offen Warnung Zeiten in Minuten.&amp;lt;br&amp;gt;&lt;br /&gt;
Der erste Wert entspricht der ersten Zeit, der zweite Wert der zweiten Zeit usw.&amp;lt;br&amp;gt;&lt;br /&gt;
Die Anzahl sollte dem Wert im Attribut HomeOpenMaxTrigger entsprechen. Wenn hier weniger Zeiten vorgegeben werden, so wird für weitere Offen Warnungen immer die letzte hier angegebene Zeit verwendet.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: leerzeichenseparierte Liste von Zahlen mit max. einer Kommmastelle, z.B. 7.5&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: 10&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsLuminance====&lt;br /&gt;
Devspec von (Innen-)Lichtsensoren deren Durchschnittswert berechnet werden soll&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Devspec&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsMotion====&lt;br /&gt;
Hier können alle Bewegungs Sensoren als Devspec hinterlegt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Diese Devices stellen zusätzlich die Platzhalter &#039;&#039;&#039;%ALIAS%&#039;&#039;&#039;, &#039;&#039;&#039;%SENSOR%&#039;&#039;&#039; und &#039;&#039;&#039;%STATE%&#039;&#039;&#039; in den HomeCMDmotion Attributen zur Verfügung. &#039;&#039;&#039;%ALIAS%&#039;&#039;&#039; wird dann durch den Alias, &#039;&#039;&#039;%SENSOR%&#039;&#039;&#039; durch den Namen und &#039;&#039;&#039;%STATE%&#039;&#039;&#039; durch den aktuellen state des zuletzt ausgelösten Kontakts ersetzt.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Devspec&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;In meinem Falle sind das Fibaro Motion Sensor Gen4/5.&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;Darum ist bei mir als Devspec &#039;&#039;&#039;modelId=010f-0801-1001|010f-0800-1001&#039;&#039;&#039; eingetragen um alle diese Bewegungssensoren zu erfassen.&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;Damit bei den Gen5 Sensoren auch das open im reading state steht, habe ich mir bei diesen Sensoren ein userReading angelegt.&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Nach Übernehmen des Attributs werden alle gefundenen Bewegungssensoren mit ihren Namen im Internal SENSORSMOTION des HOMEMODE Device einzeln aufgelistet und können dort auch direkt angeklickt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Des weiteren werden beim Übernehmen dieses Attributs jedem Bewegungssensor folgende Attribute im Attribut userattr hinzugefügt:&lt;br /&gt;
&lt;br /&gt;
=====HomeModeAlarmActive=====&lt;br /&gt;
Regex der Alarm Mode(s) in denen der Bewegungssensor eine erfolgte Öffnung als Alarm melden soll.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: armaway|armhome|armnight&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Regex von Alarm Modes&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: armaway&lt;br /&gt;
&lt;br /&gt;
=====HomeReadings=====&lt;br /&gt;
2 leerzeichenseparierte Readings für open und sabotage.&amp;lt;br&amp;gt;&lt;br /&gt;
Die hier eingetragenen Readings überschreiben die Werte aus dem Attribut HomeSensorsMotionReadings des HOMEMODE Device.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: zwei Wörter&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: state sabotageError&lt;br /&gt;
&lt;br /&gt;
=====HomeSensorLocation=====&lt;br /&gt;
Standort des Bewegungssensors (außen oder innen) - wird standardmäßig beim Hinzufügen zum HOMEMODE Device auf &amp;quot;inside&amp;quot; gesetzt, sollte jedoch für jeden Kontaktsensor einzeln überprüft werden&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: inside,outside&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: vorgegebene Werteauswahl&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: inside&lt;br /&gt;
&lt;br /&gt;
=====HomeValues=====&lt;br /&gt;
Regex der Werte die für offen und sabotiert stehen.&amp;lt;br&amp;gt;&lt;br /&gt;
Die hier eingetragenen Werte überschreiben die Werte aus dem Attribut HomeSensorsMotionValues des HOMEMODE Device.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Regex&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: open|on&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsMotionReadings====&lt;br /&gt;
2 leerzeichenseparierte Readings für open und sabotage.&amp;lt;br&amp;gt;&lt;br /&gt;
Die hier eingetragenen Readings sind global für alle Kontaktsensoren, können aber durch setzen des Attributs HomeReadings in jedem Sensor überschrieben werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: zwei Wörter&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: state sabotageError&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsMotionValues====&lt;br /&gt;
Regex der Werte die für offen und sabotiert stehen.&amp;lt;br&amp;gt;&lt;br /&gt;
Die hier eingetragenen Werte sind global für alle Kontaktsensoren, können aber durch setzen des Attributs HomeValues in jedem Sensor überschrieben werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Regex&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: open|on&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsPowerEnergy====&lt;br /&gt;
Hier können alle Energie Sensoren als Devspec hinterlegt werden. Diese müssen die beiden Readings power und energy besitzen.&amp;lt;br&amp;gt;&lt;br /&gt;
Anhand dieser Readings wird dann der Gesamtverbrauch und die derzeitige gesamte Leistungsaufnahme berechnet.&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;In meinem Falle sind das Fibaro Wall Plugs Gen4/5.&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;Darum ist bei mir als Devspec &#039;&#039;&#039;modelId=010f-0600-1000|010f-0602-1001&#039;&#039;&#039; eingetragen um alle diese Energie Sensoren zu erfassen.&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Devspec mit vorhandenen energy und power Readings&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsSmoke====&lt;br /&gt;
Devspec mit Rauchmeldern&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Devspec&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomeSensorWindspeed====&lt;br /&gt;
Sensor für Windgeschwindigkeit&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Name des Sensors und Reading der Windgeschwindigkeit separiert mit : (z.B. ga_Windsensor:wind)&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsBattery====&lt;br /&gt;
Devspec von Batteriesensoren mit einem Reading &amp;quot;battery&amp;quot;&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Devspec&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomeTriggerAnyoneElseAtHome====&lt;br /&gt;
auslösendes Gerät für anyoneElseAtHome&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: device:reading:valueOn:valueOff&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomeTriggerPanic====&lt;br /&gt;
auslösendes Gerät für Panikalarm&amp;lt;br&amp;gt;&lt;br /&gt;
valueOff ist optional, wird es weggelassen, so fungiert valueOn als toggle&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: device:reading:valueOn[:valueOff]&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomeTwilightDevice====&lt;br /&gt;
Hier ist der Name des lokalen Twilight Device anzugeben.&amp;lt;br&amp;gt;&lt;br /&gt;
Diese Device stellt zusätzlich die Platzhalter &#039;&#039;&#039;%LIGHT%&#039;&#039;&#039;, &#039;&#039;&#039;%TWILIGHT%&#039;&#039;&#039; und &#039;&#039;&#039;%TWILIGHTEVENT%&#039;&#039;&#039; in den HomeCMD Attributen zur Verfügung. &#039;&#039;&#039;%LIGHT%&#039;&#039;&#039; wird dann durch das Reading light, &#039;&#039;&#039;%TWILIGHT%&#039;&#039;&#039; durch das Reading twilight und &#039;&#039;&#039;%TWILIGHTEVENT%&#039;&#039;&#039; durch das aktuelle Twilight Event ersetzt.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Devspec&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomeUWZ====&lt;br /&gt;
Hier ist der Name des lokalen UWZ Geräts anzugeben.&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%UWZ%&#039;&#039;&#039;, &#039;&#039;&#039;%UWZSHORT%&#039;&#039;&#039; und &#039;&#039;&#039;%UWZLONG%&#039;&#039;&#039; sind verfügbar in allen HomeCMD Attributen&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Name des UWZ Geräts&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomeWeatherDevice====&lt;br /&gt;
Hier ist der Name des lokalen Weather Geräts anzugeben.&amp;lt;br&amp;gt;&lt;br /&gt;
Diese Device stellt zusätzlich einige Platzhalter zur Verfügung. Für die genaue Beschreibung derer siehe &amp;quot;Platzhalter&amp;quot;.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Devspec&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
===HomeText Attribute===&lt;br /&gt;
Die HomeText Attribute sind größtenteils zur Übersetzung einiger benötigter Begriffe gedacht.&amp;lt;br&amp;gt;&lt;br /&gt;
In den speziellen Attributen die mit HomeTextWeather anfangen, sind ganze Texte mit entsprechenden Platzhaltern einzufügen.&lt;br /&gt;
&lt;br /&gt;
====HomeTextAndAreIs====&lt;br /&gt;
Übersetzung für &amp;quot;and&amp;quot;, &amp;quot;are&amp;quot; und &amp;quot;is&amp;quot;&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar separiert mit |&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Wort/Wörter&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: and|are|is&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 und|sind|ist&lt;br /&gt;
&lt;br /&gt;
====HomeTextClosedOpen====&lt;br /&gt;
Übersetzung für &amp;quot;closed&amp;quot; und &amp;quot;open&amp;quot;&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar separiert mit |&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Wort&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: closed|open&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 geschlossen|geöffnet&lt;br /&gt;
&lt;br /&gt;
====HomeTextNosmokeSmoke====&lt;br /&gt;
Übersetzung für &amp;quot;no smoke&amp;quot; und &amp;quot;smoke&amp;quot;&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar separiert mit |&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Wort&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: no smoke|smoke&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 kein Rauch|Rauch&lt;br /&gt;
&lt;br /&gt;
====HomeTextRisingConstantFalling====&lt;br /&gt;
Übersetzung für &amp;quot;rising&amp;quot;, &amp;quot;constant&amp;quot; und &amp;quot;falling&amp;quot;&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar separiert mit |&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Wort&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: rising|constant|falling&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 steigend|gleichbleibend|fallend&lt;br /&gt;
&lt;br /&gt;
====HomeTextTodayTomorrowAfterTomorrow====&lt;br /&gt;
Übersetzung für &amp;quot;today&amp;quot;, &amp;quot;tomorrow&amp;quot; und &amp;quot;day after tomorrow&amp;quot;&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar separiert mit |&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Wort&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: today|tomorrow|day after tomorrow&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 Heute|Morgen|Übermorgen&lt;br /&gt;
&lt;br /&gt;
====HomeTextWeatherNoForecast====&lt;br /&gt;
Übersetzung für &amp;quot;No forecast available&amp;quot; - Text wenn keine Wettervorhersage verfügbar ist&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Text&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: No forecast available&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 Es ist leider keine Wettervorhersage für den angegebenen Tag verfügbar!&lt;br /&gt;
&lt;br /&gt;
====HomeTextWeatherForecastInSpecDays====&lt;br /&gt;
Text mit Platzhaltern für Wettervorhersage in 4-10 Tagen&amp;lt;br&amp;gt;&lt;br /&gt;
spezielle Platzhalter die nur in diesem Attribut gültig sind: &#039;&#039;&#039;%CONDITION%&#039;&#039;&#039;, &#039;&#039;&#039;%DAY%&#039;&#039;&#039;, &#039;&#039;&#039;%HIGH%&#039;&#039;&#039; und &#039;&#039;&#039;%LOW%&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Text mit Platzhaltern&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 In %DAY% Tagen %CONDITION% bei Temperaturen von %LOW% bis %HIGH%°C.&lt;br /&gt;
&lt;br /&gt;
====HomeTextWeatherForecastToday====&lt;br /&gt;
Text mit Platzhaltern für Wettervorhersage für heute&amp;lt;br&amp;gt;&lt;br /&gt;
spezielle Platzhalter die nur in diesem Attribut gültig sind: &#039;&#039;&#039;%CONDITION%&#039;&#039;&#039;, &#039;&#039;&#039;%DAY%&#039;&#039;&#039;, &#039;&#039;&#039;%HIGH%&#039;&#039;&#039; und &#039;&#039;&#039;%LOW%&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Text mit Platzhaltern&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 %DAY% %CONDITION% bei Temperaturen von %LOW% bis %HIGH%°C. Aktuelle Temperatur %TEMPERATURE%°C bei einer Luftfeuchtigkeit von %HUMIDITY%%. Die gefühlte Temperatur ist %WINDCHILL%°C bei einer Windgeschwindigkeit von %WIND%km/h.&lt;br /&gt;
&lt;br /&gt;
====HomeTextWeatherForecastTomorrow====&lt;br /&gt;
Text mit Platzhaltern für Wettervorhersage für morgen/übermorgen&amp;lt;br&amp;gt;&lt;br /&gt;
spezielle Platzhalter die nur in diesem Attribut gültig sind: &#039;&#039;&#039;%CONDITION%&#039;&#039;&#039;, &#039;&#039;&#039;%DAY%&#039;&#039;&#039;, &#039;&#039;&#039;%HIGH%&#039;&#039;&#039; und &#039;&#039;&#039;%LOW%&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Text mit Platzhaltern&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 %DAY% %CONDITION% bei Temperaturen von %LOW% bis %HIGH%°C.&lt;br /&gt;
&lt;br /&gt;
====HomeTextWeatherLong====&lt;br /&gt;
Langer Text mit Platzhaltern für aktuelle Wetterdaten&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Text mit Platzhaltern&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 Es %TOBE% %CONDITION% bei %TEMPERATURE%°C und %HUMIDITY%% Luftfeuchtigkeit. Die gefühlte Temperatur ist %WINDCHILL%°C bei einer Windgeschwindigkeit von %WIND%km/h. Der Luftdruck liegt bei %PRESSURE%hPa.&lt;br /&gt;
&lt;br /&gt;
====HomeTextWeatherShort====&lt;br /&gt;
Kurzer Text mit Platzhaltern für aktuelle Wetterdaten&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Text mit Platzhaltern&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 %CONDITION%, %TEMPERATURE%°C, %HUMIDITY%% Luftfeuchtigkeit, Luftdruck %PRESSURE%hPa&lt;br /&gt;
&lt;br /&gt;
===weitere Attribute===&lt;br /&gt;
Viele weitere Dinge lassen sich anpassen.&lt;br /&gt;
&lt;br /&gt;
====HomeAdvancedDetails====&lt;br /&gt;
mehr Details anzeigen, abhängig von den zu HOMEMODE hinzugefügten Geräten&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: none, detail, both, room&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Auswahlliste&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: none&lt;br /&gt;
&lt;br /&gt;
====HomeDaytimes====&lt;br /&gt;
Eigene Tageszeiten als Paare aus Zeit|Wort&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: Zeit|Wort Paare separiert mit Leerzeichen&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Zeit|Wort&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: 05:00|morning 10:00|day 14:00|afternoon 18:00|evening 23:00|night&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 00:00|Mitternacht&lt;br /&gt;
 00:05|Nacht&lt;br /&gt;
 06:30|Morgen&lt;br /&gt;
 10:00|Vormittag&lt;br /&gt;
 13:00|Mittag&lt;br /&gt;
 14:30|Nachmittag&lt;br /&gt;
 17:30|Vorabend&lt;br /&gt;
 19:00|Abend&lt;br /&gt;
 23:00|Spätabend&lt;br /&gt;
&lt;br /&gt;
====HomeIcewarningOnOffTemps====&lt;br /&gt;
2 leerzeichenseparierte Temperaturen für das Ein- und Ausschalten der Eiswarnung.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: zwei leerzeichenseparierte Temperaturen mit maximal einer Kommastelle&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: 2 3&lt;br /&gt;
&lt;br /&gt;
====HomeModeAlarmArmDelay====&lt;br /&gt;
Zeit in Sekunden um das aktivieren der Alarmschaltung zu verzögern.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: 0 bis 99999&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: einzelne Zahl (gleiche Verzögerung für alle modeAlarm) oder 3 leerzeichenseparierte Zahlen für jeden modeAlarm (Reihenfolge: armaway armnight armhome)&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: 0&lt;br /&gt;
&lt;br /&gt;
====HomeAtTmpRoom====&lt;br /&gt;
Diesen Raum zu temporäre at(s) hinzufügen die von HOMEMODE generiert werden&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Wort&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomePresenceDeviceAbsentCount-&amp;lt;ROOMMATE/GUEST&amp;gt;====&lt;br /&gt;
Anzahl der dem ROOMMATE/GUEST zugeordneten Presence Geräte um den jeweiligen ROOMMATE/GUEST auf &amp;quot;absent&amp;quot; zu setzen&amp;lt;br&amp;gt;&lt;br /&gt;
Das Attribut ist nur verfügbar wenn mehr als ein Presence Gerät pro ROOMMATE/GUEST gefunden/zugeordnet wurde&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: 0 bis ~&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: einzelne Zahl&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: maximale Anzahl von verfügbaren Presence Geräten für jeden ROOMMATE/GUEST&lt;br /&gt;
&lt;br /&gt;
====HomePresenceDevicePresentCount-&amp;lt;ROOMMATE/GUEST&amp;gt;====&lt;br /&gt;
Anzahl der dem ROOMMATE/GUEST zugeordneten Presence Geräte um den jeweiligen ROOMMATE/GUEST auf &amp;quot;present&amp;quot; zu setzen&amp;lt;br&amp;gt;&lt;br /&gt;
Das Attribut ist nur verfügbar wenn mehr als ein Presence Gerät pro ROOMMATE/GUEST gefunden/zugeordnet wurde&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: 0 bis ~&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: einzelne Zahl&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: 1&lt;br /&gt;
&lt;br /&gt;
====HomePublicIpCheckInterval====&lt;br /&gt;
Interval in Minuten für die Überprüfung der öffentlichen IP-Adresse&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: 0 bis 99999&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: einzelne Zahl&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: 0 (deaktiviert)&lt;br /&gt;
&lt;br /&gt;
====HomeSeasons====&lt;br /&gt;
Eigene Jahreszeiten als Paare aus Datum|Wort&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: Datum|Wort Paare separiert mit Leerzeichen&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Datum|Wort&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: 03.01|spring 06.01|summer 09.01|autumn 12.01|winter&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 03.01|Frühling&lt;br /&gt;
 06.01|Sommer&lt;br /&gt;
 09.01|Herbst&lt;br /&gt;
 12.01|Winter&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsBatteryLowPercentage====&lt;br /&gt;
Prozentsatz um einen Batteriesensor mit geringer Batterie anzuzeigen (nur bei Sensoren die ihren Batteriewert prozentual angeben)&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Zahl&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: 50&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsBatteryReading====&lt;br /&gt;
Reading der Batteriesensoren welches statt &amp;quot;battery&amp;quot; benutzt werden soll&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: einzelnes Wort&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: battery&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsLuminanceReading====&lt;br /&gt;
Reading der Lichtsensoren welches statt &amp;quot;luminance&amp;quot; benutzt werden soll&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: einzelnes Wort&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: luminance&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsPowerEnergyReadings====&lt;br /&gt;
Readings der Power/Energy Sensoren welche statt &amp;quot;power&amp;quot; und &amp;quot;energy&amp;quot; benutzt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: 2 leerzeichenseparierte Wörter&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: power energy&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsSmokeReading====&lt;br /&gt;
Readings der Rauchmelder welche statt &amp;quot;state&amp;quot; benutzt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: ein Wort&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: state&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsSmokeValue====&lt;br /&gt;
Regex der Auslösewerte von Rauchmeldern&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: RegEx&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: on&lt;br /&gt;
&lt;br /&gt;
====HomeSpecialLocation====&lt;br /&gt;
Hier können eigene zusätzliche location(s) als kommaseparierte Liste angegeben werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Diese können dann über &amp;quot;set &amp;lt;HOMEMODE&amp;gt; location &amp;lt;LOCATION&amp;gt;&amp;quot; gesetzt werden. Dazu passend werden HomeCMD Attribute erstellt.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: kommaseparierte Liste von Wörtern&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomeSpecialModes====&lt;br /&gt;
Hier können eigene zusätzliche mode(s) als kommaseparierte Liste angegeben werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Diese können dann über &amp;quot;set &amp;lt;HOMEMODE&amp;gt; mode &amp;lt;MODE&amp;gt;&amp;quot; gesetzt werden. Dazu passend werden HomeCMD Attribute erstellt.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: kommaseparierte Liste von Wörtern&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomeTrendCalcAge====&lt;br /&gt;
Zeit in Sekunden für das Maximalalter des vorherigen Wertes für die Trendberechnung&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Zeit in Sekunden&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: 900&lt;br /&gt;
&lt;br /&gt;
Ein weiterer Teil der Konfiguration ist das Befüllen der HomeCMD Attribute. Da dieses durch die Vermischung von FHEM Code, Perl Code und zusätzlichen Platzhaltern erst einmal sehr befremdlich sein kann, habe ich bei der Beschreibung der HomeCMD Attribute teilweise Beispiele hinzugefügt um den Einstieg weiter zu erleichtern.&lt;br /&gt;
&lt;br /&gt;
==HomeCMD Attribute (mit Beispielen)==&lt;br /&gt;
Die HomeCMD Attribute sind zum Festlegen der jeweiligen Schaltaktionen gedacht und können damit evtl. vorhandene notify/DOIF ablösen. Sie können mit FHEM-Code, Perl-Code oder aber auch mit beidem vermischt befüllt werden (wovon ich allerdings abrate). Zusätzlich sind noch diverse Platzhalter (siehe Platzhalter) verfügbar.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Bei Perl-Code innerhalb der HomeCMD Attribute gibt es hier Besonderheiten.&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
*Im Gegensatz zur FHEM-Eingabezeile müssen hier keine Semikolon verdoppelt werden&lt;br /&gt;
*Kommetarzeilen sind zulässig&lt;br /&gt;
*Kommentare am Ende einer Perl-Zeile sind nicht zulässig&lt;br /&gt;
&lt;br /&gt;
Typischer Weise werden in den HomeCMD Attributen weitere Module angesprochen.&amp;lt;br&amp;gt;&lt;br /&gt;
Z.B. benutze ich für jegliche Form der Benachrichtigung den msg Befehl.&lt;br /&gt;
&lt;br /&gt;
Keines der HomeCMD Attribute hat einen Standardwert. Es müssen alle Befehle selbst programmiert werden.&lt;br /&gt;
&lt;br /&gt;
Platzhalter die Text(e) (string) beinhalten, müssen im Perl-Code in Anführungszeichen gesetzt werden (Beispiel %SENSOR%).&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter die Zahlen beinhalten (int,float) sollten nicht in Anführungszeichen gesetzt werden damit Zahlenvergleiche (mittels ==, &amp;lt;=, &amp;gt;=, &amp;gt;, &amp;lt;) funktionieren (Beispiel %LIGHT%, %ICE% oder %TEMPERATURE%).&lt;br /&gt;
&lt;br /&gt;
====HomeCMDalarmSmoke====&lt;br /&gt;
Befehle die beim Anfang/Ende eines Rauchalarms ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====HomeCMDalarmSmoke-off====&lt;br /&gt;
Befehle die beim Ende eines Rauchalarms ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Ende Rauchalarm eines beliebigen (von HOMEMODE überwachten) Rauchmelders&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 msg push ENTWARNUNG: Alle Rauchalarme sind beendet!&lt;br /&gt;
&lt;br /&gt;
====HomeCMDalarmSmoke-on====&lt;br /&gt;
Befehle die bei einem Rauchalarm ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Rauchalarm eines beliebigen (von HOMEMODE überwachten) Rauchmelders&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   my $is = &amp;quot;meldet&amp;quot;;&lt;br /&gt;
   $is = &amp;quot;melden&amp;quot; if (%SMOKECT% &amp;gt; 1);&lt;br /&gt;
   fhem &amp;quot;msg push ACHTUNG: %SMOKEHR% $is Rauchalarm!&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDalarmTampered====&lt;br /&gt;
Befehle die beim Anfang/Ende eines Sabotage Alarms ausgeführt werden sollen.&lt;br /&gt;
&lt;br /&gt;
====HomeCMDalarmTampered-off====&lt;br /&gt;
Befehle die beim Ende eines Sabotage Alarms ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Ende Sabotage Alarm eines beliebigen (von HOMEMODE überwachten) Kontakt-/Bewegungs-Sensors&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 msg push ENTWARNUNG: Alle Manipulationen wurden beseitigt!&lt;br /&gt;
&lt;br /&gt;
====HomeCMDalarmTampered-on====&lt;br /&gt;
Befehle die bei einem Sabotage Alarm ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Sabotage Alarm eines beliebigen (von HOMEMODE überwachten) Kontakt-/Bewegungs-Sensors&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   my $is = &amp;quot;ist&amp;quot;;&lt;br /&gt;
   $is = &amp;quot;sind&amp;quot; if (%TAMPEREDCT% &amp;gt; 1);&lt;br /&gt;
   fhem &amp;quot;msg push ACHTUNG: %TAMPEREDHR% $is sabotiert!&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDalarmTriggered====&lt;br /&gt;
Befehle die beim Anfang/Ende eines Alarms ausgeführt werden sollen.&lt;br /&gt;
&lt;br /&gt;
====HomeCMDalarmTriggered-off====&lt;br /&gt;
Befehle die beim Ende eines Alarms ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Ende Alarm eines beliebigen (von HOMEMODE überwachten) Kontakt-/Bewegungs-Sensors&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 msg ENTWARNUNG: Alle Alarme sind beendet!&lt;br /&gt;
&lt;br /&gt;
====HomeCMDalarmTriggered-on====&lt;br /&gt;
Befehle die bei einem Alarm ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Alarm eines beliebigen (von HOMEMODE überwachten) Kontakt-/Bewegungs-Sensors&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   my $is = &amp;quot;ist&amp;quot;;&lt;br /&gt;
   $is = &amp;quot;sind&amp;quot; if (%ALARMCT% &amp;gt; 1);&lt;br /&gt;
   fhem &amp;quot;msg audio,push,light 3 !!! ALARM !!! %ALARMHR% $is ausgelöst!&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDanyoneElseAtHome====&lt;br /&gt;
Befehle die beim on/off von anyoneElseAtHome ausgeführt werden sollen.&lt;br /&gt;
&lt;br /&gt;
====HomeCMDanyoneElseAtHome-off====&lt;br /&gt;
Befehle die ausgeführt werden sollen sobald anyoneElseAtHome deaktiviert wird.&amp;lt;br&amp;gt;&lt;br /&gt;
Bei Abwesenheit und nicht deaktiviertem HomeAutoAlarmModes wird der Alarm Mode von &amp;quot;armaway&amp;quot; auf &amp;quot;armhome&amp;quot; umgeschaltet damit evtl. vorhandene Bewegungsmelder keinen Alarm mehr melden.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: anyoneElseAtHome on&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 msg HINWEIS: Es ist nun niemand anderes mehr zu Hause!&lt;br /&gt;
&lt;br /&gt;
====HomeCMDanyoneElseAtHome-on====&lt;br /&gt;
Befehle die ausgeführt werden sollen sobald anyoneElseAtHome aktiviert wird.&amp;lt;br&amp;gt;&lt;br /&gt;
Bei Abwesenheit und nicht deaktiviertem HomeAutoAlarmModes wird der Alarm Mode von &amp;quot;armhome&amp;quot; auf &amp;quot;armaway&amp;quot; umgeschaltet damit evtl. vorhandene Bewegungsmelder wieder Alarme melden können.&amp;lt;br&amp;gt;&lt;br /&gt;
Wird anyoneElseAtHome bei Anwesenheit und nicht deaktiviertem HomeAutoAlarmModes aktiviert, so passiert erst einmal nichts, ausser dass die hier angegebenen Befehle ausgeführt werden. Wird dann später die Abwesenheit erkannt, schaltet der Alarm Mode auf &amp;quot;armhome&amp;quot; statt auf &amp;quot;armaway&amp;quot; damit evtl. vorhandene Bewegungsmelder keinen Alarm mehr melden.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: anyoneElseAtHome off&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 msg HINWEIS: Es ist nun noch jemand anderes zu Hause!&lt;br /&gt;
&lt;br /&gt;
====HomeCMDbatteryLow====&lt;br /&gt;
Befehle die ausgeführt werden sollen sobald ein Sensor einen niedrigen Batteriewert meldet.&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   my $msg;&lt;br /&gt;
   $msg = &amp;quot;Die Batterien von %BATTERYLOW% gehen zur Neige und sollten ausgetauscht werden!&amp;quot; if (%BATTERYLOWCT% == 1);&lt;br /&gt;
   $msg = &amp;quot;Die Batterien bei folgenden Geräten sollten ausgetauscht werden: %BATTERYLOWALL%&amp;quot; if (%BATTERYLOWCT% &amp;gt; 1);&lt;br /&gt;
   fhem &amp;quot;msg push $msg&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDcontact====&lt;br /&gt;
Befehle die ausgeführt werden sollen sobald ein Kontaktsensor open/tilted/closed meldet.&amp;lt;br&amp;gt;&lt;br /&gt;
Die speziellen Platzhalter %ALIAS%, %SENSOR% und %STATE% können in diesem Attribut benutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Kontaktsensor open/tilted/closed&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   my $a = &amp;quot;%ALIAS%&amp;quot;;&lt;br /&gt;
   $a =~ s/d/D/;&lt;br /&gt;
   fhem &amp;quot;msg $a ist nun %STATE%!&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDcontactClosed====&lt;br /&gt;
Befehle die ausgeführt werden sollen sobald ein Kontaktsensor geschlossen meldet.&amp;lt;br&amp;gt;&lt;br /&gt;
Die speziellen Platzhalter %ALIAS%, %SENSOR% und %STATE% können in diesem Attribut benutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Kontaktsensor closed&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   my $a = &amp;quot;%ALIAS%&amp;quot;;&lt;br /&gt;
   $a =~ s/d/D/;&lt;br /&gt;
   fhem &amp;quot;msg $a ist nun geschlossen!&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDcontactOpen====&lt;br /&gt;
Befehle die ausgeführt werden sollen sobald ein Kontaktsensor offen meldet.&amp;lt;br&amp;gt;&lt;br /&gt;
Die speziellen Platzhalter &#039;&#039;&#039;%ALIAS%&#039;&#039;&#039;, &#039;&#039;&#039;%SENSOR%&#039;&#039;&#039; und &#039;&#039;&#039;%STATE%&#039;&#039;&#039; können in diesem Attribut benutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Kontaktsensor open/tilted&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   my $a = &amp;quot;%ALIAS%&amp;quot;;&lt;br /&gt;
   $a =~ s/d/D/;&lt;br /&gt;
   fhem &amp;quot;msg $a ist nun offen!&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDcontactDoormain====&lt;br /&gt;
Befehle die ausgeführt werden sollen sobald ein Kontaktsensor des Types doormain open/tilted/closed meldet.&amp;lt;br&amp;gt;&lt;br /&gt;
Die speziellen Platzhalter %ALIAS%, %SENSOR% und %STATE% können in diesem Attribut benutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Kontaktsensor Type doormain open/tilted/closed&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   my $a = &amp;quot;%ALIAS%&amp;quot;;&lt;br /&gt;
   $a =~ s/d/D/;&lt;br /&gt;
   fhem &amp;quot;msg $a ist nun %STATE%!&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDcontactDoormainClosed====&lt;br /&gt;
Befehle die ausgeführt werden sollen sobald ein Kontaktsensor des Types doormain closed meldet.&amp;lt;br&amp;gt;&lt;br /&gt;
Die speziellen Platzhalter &#039;&#039;&#039;%ALIAS%&#039;&#039;&#039;, &#039;&#039;&#039;%SENSOR%&#039;&#039;&#039; und &#039;&#039;&#039;%STATE%&#039;&#039;&#039; können in diesem Attribut benutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Kontaktsensor vom Typ doormain wird geschlossen&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 { &lt;br /&gt;
   # Wenn es Ankommende gibt&lt;br /&gt;
   if (&amp;quot;%ARRIVERS%&amp;quot;)&lt;br /&gt;
   {&lt;br /&gt;
     # Zusammenstellen der Begrüßung&lt;br /&gt;
     my $msg = &amp;quot;Gute&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
     # &amp;quot;n&amp;quot; anhängen wenn Tageszeit nicht Nacht ist&lt;br /&gt;
     $msg .= &amp;quot;n&amp;quot; if (&amp;quot;%DAYTIME%&amp;quot; ne &amp;quot;Nacht&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
     # Leerzeichen einfügen&lt;br /&gt;
     $msg .= &amp;quot; &amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
     # den Feiertag der Tageszeit voranstellen wenn ein Feiertag im Kalender FEIERTAG ist&lt;br /&gt;
     $msg .= &amp;quot;%FEIERTAG%-&amp;quot; if (&amp;quot;%FEIERTAG%&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
     # Tageszeit einfügen&lt;br /&gt;
     $msg .= &amp;quot;%DAYTIME% &amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
     # bei ROOMMATE &amp;quot;zu Hause&amp;quot; in Begrüßung einfügen&lt;br /&gt;
     $msg .= &amp;quot;zu Hause &amp;quot; if (&amp;quot;%RESIDENT%&amp;quot; =~ /^rr_/);&lt;br /&gt;
 &lt;br /&gt;
     # Ankommende einfügen&lt;br /&gt;
     $msg .= &amp;quot;%ARRIVERS%&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
     # Begrüßung am Sonos im Flur ausgeben bei Abwesenheit über 60 min&lt;br /&gt;
     fhem &amp;quot;msg audio \@fl_Sonos $msg!&amp;quot; if (%DURABSENCELAST% &amp;gt; 60);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDcontactDoormainOpen====&lt;br /&gt;
Befehle die ausgeführt werden sollen sobald ein Kontaktsensor des Types doormain open/tilted meldet.&amp;lt;br&amp;gt;&lt;br /&gt;
Die speziellen Platzhalter &#039;&#039;&#039;%ALIAS%&#039;&#039;&#039;, &#039;&#039;&#039;%SENSOR%&#039;&#039;&#039; und &#039;&#039;&#039;%STATE%&#039;&#039;&#039; können in diesem Attribut benutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Kontaktsensor vom Typ doormain geöffnet&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   my $a = &amp;quot;%ALIAS%&amp;quot;;&lt;br /&gt;
   $a =~ s/d/D/;&lt;br /&gt;
   fhem &amp;quot;msg $a ist nun geöffnet!&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDcontactOpenWarning1====&lt;br /&gt;
Befehle die ausgeführt werden sollen sobald ein Kontaktsensor die erste Offenwarnzeit erreicht hat.&amp;lt;br&amp;gt;&lt;br /&gt;
Die speziellen Platzhalter &#039;&#039;&#039;%ALIAS%&#039;&#039;&#039;, &#039;&#039;&#039;%SENSOR%&#039;&#039;&#039; und &#039;&#039;&#039;%STATE%&#039;&#039;&#039; können in diesem Attribut benutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: erste Offenwarnzeit des Kontakts erreicht&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 msg audio %ALIAS% steht noch offen!&lt;br /&gt;
&lt;br /&gt;
====HomeCMDcontactOpenWarning2====&lt;br /&gt;
Befehle die ausgeführt werden sollen sobald ein Kontaktsensor die zweite Offenwarnzeit erreicht hat.&amp;lt;br&amp;gt;&lt;br /&gt;
Die speziellen Platzhalter &#039;&#039;&#039;%ALIAS%&#039;&#039;&#039;, &#039;&#039;&#039;%SENSOR%&#039;&#039;&#039; und &#039;&#039;&#039;%STATE%&#039;&#039;&#039; können in diesem Attribut benutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: ab Erreichen der zweiten Offenwarnzeit des Kontakts&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 msg audio %ALIAS% steht immer noch offen!&lt;br /&gt;
&lt;br /&gt;
====HomeCMDcontactOpenWarningLast====&lt;br /&gt;
Befehle die ausgeführt werden sollen sobald ein Kontaktsensor die letzte Offenwarnzeit erreicht hat.&amp;lt;br&amp;gt;&lt;br /&gt;
Die speziellen Platzhalter &#039;&#039;&#039;%ALIAS%&#039;&#039;&#039;, &#039;&#039;&#039;%SENSOR%&#039;&#039;&#039; und &#039;&#039;&#039;%STATE%&#039;&#039;&#039; können in diesem Attribut benutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Erreichen der letzten Offenwarnzeit des Kontakts&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 msg audio Das ist der letzte Hinweis %ALIAS% endlich zu schliessen!&lt;br /&gt;
&lt;br /&gt;
====HomeCMDdaytime====&lt;br /&gt;
Befehle die ausgeführt werden sollen sobald sich die Tageszeit (daytime) auf einen beliebigen Wert ändert.&amp;lt;br&amp;gt;&lt;br /&gt;
Um die jeweilige eingetretene Tageszeit zu ermitteln ist der Platzhalter &#039;&#039;&#039;%DAYTIME%&#039;&#039;&#039; vorgesehen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung der Tageszeit (daytime)&lt;br /&gt;
&lt;br /&gt;
====HomeCMDdaytime-&amp;amp;lt;DAYTIME&amp;amp;gt;====&lt;br /&gt;
Befehle die ausgeführt werden sollen sobald die jeweilige Tageszeit (daytime) erreicht ist.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung der Tageszeit (daytime) auf bestimmten Wert&amp;lt;br&amp;gt;&lt;br /&gt;
Bei &amp;quot;night&amp;quot; könnte man z.B. die Heizung bewohnerunabhängig ausschalten, bei &amp;quot;morning&amp;quot; wieder ein.&lt;br /&gt;
&lt;br /&gt;
====HomeCMDdeviceDisable====&lt;br /&gt;
Befehle die ausgeführt werden sollen sobald ein Gerät deaktiviert wird.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: &#039;set deviceDisable &amp;amp;lt;DEVICE&amp;amp;gt;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   speak &amp;quot;Das Gerät %ALIAS% ist nun deaktiviert!&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
   # optional wirklich attr disable für Device setzen und Konfig speichern&lt;br /&gt;
   #fhem &amp;quot;attr %DEVICE%:FILTER=disable!=1 disable 1; save&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
   # ROOMMATE/GUEST auf gone/none setzen wenn Presence Devices deaktiviert werden&lt;br /&gt;
   if (&amp;quot;%DEVICE%&amp;quot; =~ /^PRESENCE\d?_(r[rg]_.*)/)&lt;br /&gt;
   {&lt;br /&gt;
     my $resident = $1;&lt;br /&gt;
     my $gone = $resident =~ /^rr_/ ? &amp;quot;gone&amp;quot; : &amp;quot;none&amp;quot;;&lt;br /&gt;
     fhem &amp;quot;set $resident:FILTER=state!=$gone state $gone&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDdeviceEnable====&lt;br /&gt;
Befehle die ausgeführt werden sollen sobald ein Gerät aktiviert wird.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: &#039;set deviceEnable &amp;amp;lt;DEVICE&amp;amp;gt;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   speak &amp;quot;Das Gerät %ALIAS% ist nun aktiviert!&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
   # optional attr disable für Device entfernen und Konfig speichern&lt;br /&gt;
   #fhem &amp;quot;deleteattr %DEVICE%:FILTER=disable=1 disable; save&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
   # ROOMMATE/GUEST auf home setzen wenn Presence Devices aktiviert werden und anwesend sind&lt;br /&gt;
   if (&amp;quot;%DEVICE%&amp;quot; =~ /^PRESENCE\d?_(r[rg]_.*)/)&lt;br /&gt;
   {&lt;br /&gt;
     fhem &amp;quot;set $1:FILTER=state!=home state home&amp;quot; if (ReadingsVal(&amp;quot;%DEVICE%&amp;quot;,&amp;quot;presence&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;present&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDdnd====&lt;br /&gt;
Befehle die beim Anfang/Ende des DND Modus ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Ende des DND Modus&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   if (%DND%)&lt;br /&gt;
   {&lt;br /&gt;
     fhem &amp;quot;msg audio Der DND Modus ist nun eingeschaltet!&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
   else&lt;br /&gt;
   {&lt;br /&gt;
     fhem &amp;quot;msg audio Der DND Modus ist nun beendet!&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDdnd-off====&lt;br /&gt;
Befehle die beim Ende des DND Modus ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Ende des DND Modus&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 msg audio Der DND Modus ist nun beendet!&lt;br /&gt;
&lt;br /&gt;
====HomeCMDdnd-on====&lt;br /&gt;
Befehle die beim Beginn des DND Modus ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Beginn des DND Modus&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 msg audio Der DND Modus ist nun eingeschaltet!&lt;br /&gt;
&lt;br /&gt;
====HomeCMDevent====&lt;br /&gt;
Befehle die beim Beginn eines beliebigen (holiday)Kalender Events ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Beginn eines beliebigen (holiday)Kalender Events&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%CALENDAR%&#039;&#039;&#039;, &#039;&#039;&#039;%EVENT%&#039;&#039;&#039; und &#039;&#039;&#039;%PREVEVENT%&#039;&#039;&#039; können zusätzlich verwendet werden&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   fhem &amp;quot;set Weihnachten on&amp;quot; if (&amp;quot;%EVENT%&amp;quot; eq &amp;quot;Weihnachten&amp;quot;);&lt;br /&gt;
   fhem &amp;quot;set Weihnachten off&amp;quot; if (&amp;quot;%PREVEVENT%&amp;quot; eq &amp;quot;Weihnachten&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDevent-&amp;amp;lt;KALENDER&amp;amp;gt;-each====&lt;br /&gt;
Befehle die beim Beginn/Ende eines beliebigen (holiday)Kalender Events eines bestimmten KALENDERs ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Beginn eines beliebigen (holiday)Kalender Events eines bestimmten KALENDERs&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%EVENT%&#039;&#039;&#039; und &#039;&#039;&#039;%PREVEVENT%&#039;&#039;&#039; können zusätzlich verwendet werden&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel für &amp;quot;HomeCMDevent-FEIERTAGE-each&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   fhem &amp;quot;set Weihnachten off&amp;quot; if (&amp;quot;%PREVEVENT%&amp;quot; eq &amp;quot;Weihnachten&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&#039;&#039;&#039;Beispiel für &amp;quot;HomeCMDevent-URLAUBDAN-each&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   if (&amp;quot;%EVENT%&amp;quot; =~ /urlaub/i)&lt;br /&gt;
   {&lt;br /&gt;
     speak &amp;quot;Dan hat jetzt Urlaub!!!&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
   elsif (&amp;quot;%PREVEVENT%&amp;quot; =~ /urlaub/i)&lt;br /&gt;
   {&lt;br /&gt;
     speak &amp;quot;Der Urlaub von Dan ist nun zu Ende!!!&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel für &amp;quot;HomeCMDevent-WOHNUNG-each&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   # Heizung an/aus schalten&lt;br /&gt;
   my $heiz = &amp;quot;([bksw]z|ku)_Thermostat&amp;quot;;&lt;br /&gt;
   if (&amp;quot;%EVENT%&amp;quot; =~ /^heizung(..+)?$/i)&lt;br /&gt;
   {&lt;br /&gt;
     my $zeit = $1;&lt;br /&gt;
     if (&amp;quot;%SEASON%&amp;quot; ne &amp;quot;Sommer&amp;quot;)&lt;br /&gt;
     {&lt;br /&gt;
 &lt;br /&gt;
       # morgens nicht alle Thermostaten schalten&lt;br /&gt;
       $heiz = &amp;quot;([bks]z|ku)_Thermostat&amp;quot; if ($zeit &amp;amp;&amp;amp; $zeit =~ /morgens?$/i);&lt;br /&gt;
       fhem &amp;quot;set $heiz:FILTER=controlMode!=day controlMode day&amp;quot;&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
   elsif (&amp;quot;%PREVEVENT%&amp;quot; =~ /^heizung/i)&lt;br /&gt;
   {&lt;br /&gt;
     fhem &amp;quot;set $heiz:FILTER=controlMode!=night controlMode night&amp;quot; if (&amp;quot;%SEASON%&amp;quot; ne &amp;quot;Sommer&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   # WLAN an/aus schalten&lt;br /&gt;
   elsif (&amp;quot;%EVENT%&amp;quot; =~ /^wlan|wifi|wi-fi/i)&lt;br /&gt;
   {&lt;br /&gt;
     fhem &amp;quot;set Router wifi off&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
   elsif (&amp;quot;%PREVEVENT%&amp;quot; =~ /^wlan|wifi|wi-fi/i)&lt;br /&gt;
   {&lt;br /&gt;
     fhem &amp;quot;set Router wifi on&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   # G-Tag für Putzfrau (de)aktivieren&lt;br /&gt;
   elsif (&amp;quot;%EVENT%&amp;quot; =~ /^putz/i)&lt;br /&gt;
   {&lt;br /&gt;
     fhem &amp;quot;set %NAME% deviceEnable PRESENCE_rg_Inge&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
   elsif (&amp;quot;%PREVEVENT%&amp;quot; =~ /^putz/i)&lt;br /&gt;
   {&lt;br /&gt;
     fhem &amp;quot;set %NAME% deviceDisable PRESENCE_rg_Inge&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   # G-Tag für Gast (de)aktivieren&lt;br /&gt;
   elsif (&amp;quot;%EVENT%&amp;quot; =~ /g([aä]|ae)st/i)&lt;br /&gt;
   {&lt;br /&gt;
     fhem &amp;quot;set %NAME% deviceEnable PRESENCE_rg_Gast&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
   elsif (&amp;quot;%PREVEVENT%&amp;quot; =~ /g([aä]|ae)st/i)&lt;br /&gt;
   {&lt;br /&gt;
     fhem &amp;quot;set %NAME% deviceDisable PRESENCE_rg_Gast&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDevent-&amp;amp;lt;KALENDER&amp;amp;gt;-&amp;amp;lt;EVENT&amp;amp;gt;-begin====&lt;br /&gt;
Befehle die beim Beginn eines bestimmten (holiday)Kalender EVENTs eines bestimmten KALENDERs ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Beginn eines bestimmten (holiday)Kalender EVENTs eines bestimmten KALENDERs&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%PREVEVENT%&#039;&#039;&#039; kann zusätzlich verwendet werden&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel für &amp;quot;HomeCMDevent-FEIERTAGE-Neujahr-begin&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
 set %SENSORSENERGY% meterReset&lt;br /&gt;
&lt;br /&gt;
====HomeCMDevent-&amp;amp;lt;KALENDER&amp;amp;gt;-&amp;amp;lt;EVENT&amp;amp;gt;-end====&lt;br /&gt;
Befehle die bei Ende der (holiday)Kalender EVENTs eines bestimmten KALENDERs ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Ende der (holiday)Kalender EVENTs eines bestimmten KALENDERs&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%PREVEVENT%&#039;&#039;&#039; kann zusätzlich verwendet werden&lt;br /&gt;
&lt;br /&gt;
====HomeCMDfhemDEFINED====&lt;br /&gt;
Befehle die ausgeführt werden sollen wenn ein neues Gerät angelegt wird (define)&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   # Jedem neu definierten Gerät den Geräte-TYPE auch als Raum im Menüpunkt Module zuweisen&lt;br /&gt;
   fhem &amp;quot;attr %DEFINED% room Module-&amp;gt;&amp;quot;.InternalVal(&amp;quot;%DEFINED%&amp;quot;,&amp;quot;TYPE&amp;quot;,&amp;quot;default&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDfhemINITIALIZED====&lt;br /&gt;
Befehle die ausgeführt werden sollen wenn FHEM gestartet wurde&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 msg FHEM Home wurde gestartet...&lt;br /&gt;
&lt;br /&gt;
====HomeCMDfhemSAVE====&lt;br /&gt;
Befehle die ausgeführt werden sollen wenn in FHEM die Konfigurationsdatei gespeichert wird&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel (Backup von fhem.cfg und fhem.state):&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   # Datum/Uhrzeit&lt;br /&gt;
   my $now = TimeNow();&lt;br /&gt;
   # Leerzeichen durch Unterstriche ersetzen&lt;br /&gt;
   $now =~ s/ /_/g;&lt;br /&gt;
   # Backup der Datei fhem.cfg&lt;br /&gt;
   `cp $attr{global}{configfile} ./backup/fhem.cfg.$now`;&lt;br /&gt;
   # Log-Ausgabe der gespeicherten Datei&lt;br /&gt;
   Log3 undef,3,&amp;quot;saved ./backup/fhem.cfg.$now&amp;quot;;&lt;br /&gt;
   # Backup der Datei fhem.state&lt;br /&gt;
   `cp $attr{global}{statefile} ./backup/fhem.state.$now`;&lt;br /&gt;
   # Log-Ausgabe der gespeicherten Datei&lt;br /&gt;
   Log3 undef,3,&amp;quot;saved ./backup/fhem.state.$now&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDfhemUPDATE====&lt;br /&gt;
Befehle die ausgeführt werden sollen wenn das Update von FHEM ausgeführt wurde&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 msg audio Das Update für FHEM ist beendet!&lt;br /&gt;
&lt;br /&gt;
====HomeCMDicewarning====&lt;br /&gt;
Befehle die bei Anfang/Ende der Eiswarnung ausgeführt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: icewarning 0/1&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   if (%ICE%)&lt;br /&gt;
   {&lt;br /&gt;
     fhem &amp;quot;msg push ACHTUNG!!! Es sind nur noch %TEMPERATURE%°C! Somit könnte es glatt werden!&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
   else&lt;br /&gt;
   {&lt;br /&gt;
     fhem &amp;quot;msg audio Es sind wieder %TEMPERATURE%°C! Die Glättewarnung ist damit beendet!.&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDicewarning-off====&lt;br /&gt;
Befehle die bei Ende der Eiswarnung ausgeführt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: icewarning 0&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 msg audio Es sind wieder %TEMPERATURE%°C! Die Glättewarnung ist damit beendet!&lt;br /&gt;
&lt;br /&gt;
====HomeCMDicewarning-on====&lt;br /&gt;
Befehle die bei Beginn der Eiswarnung ausgeführt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: icewarning 1&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 msg audio ACHTUNG!!! Es sind nur noch %TEMPERATURE%°C! Somit könnte es glatt werden!&lt;br /&gt;
&lt;br /&gt;
====HomeCMDlocation====&lt;br /&gt;
Befehle die beim Ändern der location ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung location&lt;br /&gt;
&lt;br /&gt;
====HomeCMDlocation-&amp;amp;lt;LOCATION&amp;amp;gt;====&lt;br /&gt;
Befehle die bei Änderung auf eine bestimmte location ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung auf bestimmte location&lt;br /&gt;
&lt;br /&gt;
====HomeCMDmode====&lt;br /&gt;
Befehle die beim Ändern von mode ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung mode&lt;br /&gt;
&lt;br /&gt;
====HomeCMDmode-absent-belated====&lt;br /&gt;
Befehle die nachträglich zur Abwesenheit ausgeführt werden sollen, die Zeit kann im Atteribut &amp;quot;HomeModeAbsentBelatedTime&amp;quot; eingestellt werden&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Abwesenheit + XX min&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 set Heizungen [FILTER=controlManu!=off] controlMode night&lt;br /&gt;
&lt;br /&gt;
====HomeCMDmode-&amp;amp;lt;MODE&amp;amp;gt;====&lt;br /&gt;
Befehle die bei Änderung auf einen bestimmten mode ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung auf bestimmten mode&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel für &amp;quot;HomeCMDmode-absent&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
 set HarmonyHub:FILTER=activity!=PowerOff activity PowerOff;&lt;br /&gt;
 set wz_Ventilator:FILTER=speed!=0 speed 0;&lt;br /&gt;
 set TYPE=SONOSPLAYER:FILTER=Volume&amp;gt;0 Volume 0;&lt;br /&gt;
 set Sonos stopAll;&lt;br /&gt;
 sleep 3;&lt;br /&gt;
 set Wohnung [FILTER=state!=off] off&amp;quot;&lt;br /&gt;
&#039;&#039;&#039;Beispiel für &amp;quot;HomeCMDmode-asleep&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
 define atTmp_wz_Media_aus_%SELF% at +01:00:00 set HarmonyHub:FILTER=currentActivity!=PowerOff activity PowerOff;&lt;br /&gt;
 define atTmp_wz_Venti_aus_%SELF% at +01:00:00 set wz_Ventilator:FILTER=speed!=0 speed 0;&lt;br /&gt;
 define atTmp_wzLS_aus_%SELF% at +00:30:00 set wz_LS scene aus;&lt;br /&gt;
 define atTmp_all_Sonos_vol_down_%SELF% at +00:02:00 set TYPE=SONOSPLAYER:FILTER=Volume!=0 Volume 0 1;&lt;br /&gt;
 define atTmp_all_Sonos_off_%SELF% at +00:02:30 set Sonos stopAll;&lt;br /&gt;
 set [sw]z_Auto(Music|Light):FILTER=state!=off off;&lt;br /&gt;
 set Heizungen [FILTER=controlManu!=off] controlMode night&lt;br /&gt;
&#039;&#039;&#039;Beispiel für &amp;quot;HomeCMDmode-awoken&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
 set [sw]z_Auto(Music|Light):FILTER=state!=on on&lt;br /&gt;
&#039;&#039;&#039;Beispiel für &amp;quot;HomeCMDmode-gone&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
 set Heizungen [FILTER=controlManu!=off] controlManu off&lt;br /&gt;
&lt;br /&gt;
====HomeCMDmode-&amp;amp;lt;MODE&amp;amp;gt;-resident====&lt;br /&gt;
Befehle die bei Änderung auf einen bestimmten mode, ausgelöst durch einen beliebigen Resident, ausgeführt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung mode von beliebigem Resident ausgelöst&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel für &amp;quot;HomeCMDmode-asleep-resident&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
 msg audio @%AUDIO% Guten Nacht und schlaf&#039; gut %ALIAS%!&lt;br /&gt;
&#039;&#039;&#039;Beispiel für &amp;quot;HomeCMDmode-awoken-resident&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   my $msg = &amp;quot;Guten&amp;quot;;&lt;br /&gt;
   $msg .= &amp;quot; %FEIERTAG%&amp;quot; if (&amp;quot;%FEIERTAG%&amp;quot;);&lt;br /&gt;
   $msg .= &amp;quot; Morgen %ALIAS%&amp;quot;;&lt;br /&gt;
   fhem &amp;quot;msg audio \@%AUDIO% $msg&amp;quot;;&lt;br /&gt;
   fhem &amp;quot;defmod atTmp_wetter_%RESIDENT%_%SELF% at +00:07:00 msg audio Wettervorhersage für heute: %FORECASTTODAY%&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDmode-&amp;amp;lt;MODE&amp;amp;gt;-&amp;amp;lt;ROOMMATE/GUEST&amp;amp;gt;====&lt;br /&gt;
Befehle die bei Änderung auf einen bestimmten mode, ausgelöst durch einen bestimmten Resident, ausgeführt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung mode von bestimmten Resident ausgelöst&lt;br /&gt;
&lt;br /&gt;
====HomeCMDmodeAlarm====&lt;br /&gt;
Befehle die beim Ändern von modeAlarm ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung modeAlarm&lt;br /&gt;
&lt;br /&gt;
====HomeCMDmodeAlarm-&amp;amp;lt;armaway/armhome/armnight/disarm&amp;amp;gt;====&lt;br /&gt;
Befehle die bei Änderung auf einen bestimmten modeAlarm ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung auf bestimmten modeAlarm&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel für &amp;quot;HomeCMDmodeAlarm-armaway&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   if (&amp;quot;%PREVAMODE%&amp;quot; eq &amp;quot;disarm&amp;quot;)&lt;br /&gt;
   {&lt;br /&gt;
     # Alarmanlage einschalten&lt;br /&gt;
     fhem &amp;quot;set AA_Arm:FILTER=level!=100 alarmLevel armAll&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
     # Nachricht zusammensetzen&lt;br /&gt;
     my $msg;&lt;br /&gt;
     $msg .= &amp;quot;Die Alarmanlage ist nun scharf geschaltet!&amp;quot; if (&amp;quot;%RESIDENT%&amp;quot; ne &amp;quot;rr_Dan&amp;quot;);&lt;br /&gt;
     my $is = &amp;quot;%ALARMHR%&amp;quot; =~ /und/ ? &amp;quot;sind&amp;quot; : &amp;quot;ist&amp;quot;;&lt;br /&gt;
     $msg .= &amp;quot; &amp;quot; if ($msg);&lt;br /&gt;
     $msg .= &amp;quot;ACHTUNG: %ALARMHR% $is noch offen!!!&amp;quot; if (%ALARMCT%);&lt;br /&gt;
 &lt;br /&gt;
     # Nachricht an ROOMMATE/GUEST senden&lt;br /&gt;
     fhem &amp;quot;msg \@%RESIDENT% $msg&amp;quot; if ($msg);&lt;br /&gt;
 &lt;br /&gt;
     # Eingangstür abschließen falls noch nicht geschehen&lt;br /&gt;
     fhem &amp;quot;set fl_Tuerschloss:FILTER=state!=locked lock&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&#039;&#039;&#039;Beispiel für &amp;quot;HomeCMDmodeAlarm-armhome&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
 AA_Arm:FILTER=level!=25 alarmLevel armExtSens;&lt;br /&gt;
 set fl_Tuerschloss:FILTER=state!=locked lock&lt;br /&gt;
&#039;&#039;&#039;Beispiel für &amp;quot;HomeCMDmodeAlarm-armnight&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
 AA_Arm:FILTER=level!=25 alarmLevel armExtSens;&lt;br /&gt;
 set fl_Tuerschloss:FILTER=state!=locked lock&lt;br /&gt;
&#039;&#039;&#039;Beispiel für &amp;quot;HomeCMDmodeAlarm-disarm&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   # Alarmanlage ausschalten&lt;br /&gt;
   fhem &amp;quot;set AA_Arm:FILTER=level!=0 alarmLevel disarmed&amp;quot;;&lt;br /&gt;
   my $prio = &amp;quot;&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
   # Nachrichtenpriorität auf 1 setzen bei Ankunft (höhere Lautstärke beim Abspielen damit man das auch vor der Tür hört)&lt;br /&gt;
   $prio = &amp;quot; 1&amp;quot; if (&amp;quot;%LOCATION%&amp;quot; eq &amp;quot;arrival&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
   # Nachricht an ROOMMATE/GUEST senden wenn der vorherige alarmMode nicht &amp;quot;armnight&amp;quot; ist&lt;br /&gt;
   fhem &amp;quot;msg audio \@fl_Sonos$prio Die Alarmanlage ist nun ausgeschaltet %ALIAS%!&amp;quot; if (&amp;quot;%PREVAMODE%&amp;quot; ne &amp;quot;armnight&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDmotion====&lt;br /&gt;
Befehle die bei Statusänderung eines beliebigen Bewegungsmelders ausgeführt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: öffnen/schließen eines beliebigen Bewegungsmelders&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   # Raum aus Sensornamen ermitteln, z.B. bz_Sensor&lt;br /&gt;
   my $room = (split /_/,&amp;quot;%SENSOR%&amp;quot;)[0];&lt;br /&gt;
 &lt;br /&gt;
   # Status des structure aller Lichter dieses Raums&lt;br /&gt;
   my $lichter = Value($room.&amp;quot;_Lichter&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
   # Status des dummy Tageslicht&lt;br /&gt;
   my $tl = Value(&amp;quot;Tageslicht&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
   if (&amp;quot;%STATE%&amp;quot; eq &amp;quot;geöffnet&amp;quot;)&lt;br /&gt;
   {&lt;br /&gt;
     # Lichtwert des Sensors&lt;br /&gt;
     my $lum = ReadingsNum(&amp;quot;%SENSOR%&amp;quot;,&amp;quot;luminance&amp;quot;,100);&lt;br /&gt;
 &lt;br /&gt;
     # Löschen des evtl. schon vorhandenen &amp;quot;at&amp;quot;&lt;br /&gt;
     fhem &amp;quot;delete atTmp_Bewegungsmelder_Licht_aus_&amp;quot;.$room.&amp;quot;_%SELF%&amp;quot; if (IsDevice(&amp;quot;atTmp_Bewegungsmelder_Licht_aus_&amp;quot;.$room.&amp;quot;_%SELF%&amp;quot;));&lt;br /&gt;
 &lt;br /&gt;
     # Licht nur wenn kein Tageslicht oder Lichtwert des Sensors kleiner als 10 und AutoLight eingeschaltet und modeAlarm nicht armaway&lt;br /&gt;
     if (($tl eq &amp;quot;off&amp;quot; || $lum &amp;lt; 10) &amp;amp;&amp;amp; $lichter eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; Value($room.&amp;quot;_AutoLight&amp;quot;) eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; &amp;quot;%AMODE%&amp;quot; ne &amp;quot;armaway&amp;quot;)&lt;br /&gt;
     {&lt;br /&gt;
       my $scene;&lt;br /&gt;
 &lt;br /&gt;
       # verschiedene Szenen für verschiedene Modus bzw. Aussenlichtstärken&lt;br /&gt;
       if (&amp;quot;%MODE%&amp;quot; eq &amp;quot;gotosleep&amp;quot;)&lt;br /&gt;
       {&lt;br /&gt;
         $scene = &amp;quot;Abend&amp;quot;;&lt;br /&gt;
       }&lt;br /&gt;
       elsif (&amp;quot;%MODE%&amp;quot; eq &amp;quot;asleep&amp;quot;)&lt;br /&gt;
       {&lt;br /&gt;
         $scene = &amp;quot;Nacht&amp;quot;;&lt;br /&gt;
       }&lt;br /&gt;
       elsif (%LIGHT% &amp;gt; 3)&lt;br /&gt;
       {&lt;br /&gt;
         $scene = &amp;quot;viel&amp;quot;;&lt;br /&gt;
       }&lt;br /&gt;
       elsif (%LIGHT% &amp;lt; 4)&lt;br /&gt;
       {&lt;br /&gt;
         $scene = &amp;quot;mittel&amp;quot;;&lt;br /&gt;
       }&lt;br /&gt;
 &lt;br /&gt;
       # Schalten der entsprechenden Szene (Modul LightScene)&lt;br /&gt;
       fhem &amp;quot;set &amp;quot;.$room.&amp;quot;_LS scene $scene&amp;quot; if ($scene);&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
   else&lt;br /&gt;
   {&lt;br /&gt;
     # unterschiedliche Ausschaltzeiten für unterschiedliche Räume&lt;br /&gt;
     my $t = 3;&lt;br /&gt;
     $t = 15 if ($room eq &amp;quot;wz&amp;quot;);&lt;br /&gt;
     $t = 2 if ($room eq &amp;quot;bz&amp;quot; || ($room =~ /wz|ku/ &amp;amp;&amp;amp; &amp;quot;%MODE%&amp;quot; =~ /sleep/));&lt;br /&gt;
     $t = 1 if ($room eq &amp;quot;fl&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
     # Zahl in Minuten umrechnen in einen Zeitpunkt für das &amp;quot;at&amp;quot;&lt;br /&gt;
     my $d = HOMEMODE_hourMaker($t);&lt;br /&gt;
 &lt;br /&gt;
     # Anlegen des &amp;quot;at&amp;quot; zum Ausschalten des Lichts wenn die Lichter angeschaltet sind und auch AutoLight eingeschaltet ist&lt;br /&gt;
     if ($lichter ne &amp;quot;off&amp;quot; &amp;amp;&amp;amp; Value($room.&amp;quot;_AutoLight&amp;quot;) eq &amp;quot;on&amp;quot;)&lt;br /&gt;
     {&lt;br /&gt;
       my $cmd = &amp;quot;set &amp;quot;.$room.&amp;quot;_LS scene aus&amp;quot;;&lt;br /&gt;
       fhem &amp;quot;defmod atTmp_Bewegungsmelder_Licht_aus_&amp;quot;.$room.&amp;quot;_%SELF% at +$d $cmd&amp;quot;;&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDmotion-off====&lt;br /&gt;
Befehle die bei Ende der Bewegung eines beliebigen Bewegungsmelders ausgeführt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Ende der Bewegung eines beliebigen Bewegungsmelders&lt;br /&gt;
&lt;br /&gt;
====HomeCMDmotion-on====&lt;br /&gt;
Befehle die bei Beginn der Bewegung eines beliebigen Bewegungsmelders ausgeführt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Beginn der Bewegung eines beliebigen Bewegungsmelders&lt;br /&gt;
&lt;br /&gt;
====HomeCMDpresence-&amp;amp;lt;absent/present&amp;amp;gt;====&lt;br /&gt;
Befehle die bei Änderung von presence ausgeführt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung presence&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel für &amp;quot;HomeCMDpresence-present&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
 set w_Steckdosen [FILTER=state!=on] on;&lt;br /&gt;
 set Heizungen [FILTER=controlManu!=off] controlMode auto&lt;br /&gt;
&lt;br /&gt;
====HomeCMDpresence-&amp;amp;lt;absent/present&amp;amp;gt;-device====&lt;br /&gt;
Befehle die bei Änderung von presence, ausgelöst durch ein beliebiges Presence Device, ausgeführt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung presence, ausgelöst durch beliebiges Presence Device&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel für &amp;quot;HomeCMDpresence-present-device&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   # mindestens 1x täglich den Batteriewert des PRESENCE Geräts bei erkannter Anwesenheit holen&lt;br /&gt;
   fhem &#039;&amp;quot;sudo /opt/fhem/scripts/GTag-bat.sh %DEVICE% %ADDRESS% &amp;amp;&amp;quot;&#039;&lt;br /&gt;
     if (&amp;quot;%DEVICE%&amp;quot; =~ /^PRESENCE_/ &amp;amp;&amp;amp; (!defined ReadingsVal(&amp;quot;%DEVICE%&amp;quot;,&amp;quot;battery&amp;quot;,undef) || ReadingsAge(&amp;quot;%DEVICE%&amp;quot;,&amp;quot;battery&amp;quot;,0) &amp;gt; 64800));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDpresence-&amp;amp;lt;absent/present&amp;amp;gt;-resident====&lt;br /&gt;
Befehle die bei Änderung von presence, ausgelöst durch einen beliebigen Resident, ausgeführt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung presence, ausgelöst durch beliebigen Resident&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel für &amp;quot;HomeCMDpresence-absent-resident&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   # Mich benachrichtigen wenn ich nicht zu hause bin und jemand anderes die Wohnung verlässt&lt;br /&gt;
   fhem &amp;quot;msg push \@rr_Dan %ALIAS% hat gerade die Wohnung verlassen!&amp;quot;&lt;br /&gt;
     if (&amp;quot;%RESIDENT%&amp;quot; ne &amp;quot;rr_Dan&amp;quot; &amp;amp;&amp;amp; ReadingsVal(&amp;quot;rr_Dan&amp;quot;,&amp;quot;presence&amp;quot;,&amp;quot;&amp;quot;) ne &amp;quot;present&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
   # Verabschiedungsnachricht zusammensetzen&lt;br /&gt;
   my $msg;&lt;br /&gt;
 &lt;br /&gt;
   # Alle außer mich selbst verabschieden&lt;br /&gt;
   $msg .= &amp;quot;Bis bald und auf Wiedersehen %ALIAS%...&amp;quot; if (&amp;quot;%RESIDENT%&amp;quot; ne &amp;quot;rr_Dan&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
   # Glättewarnung wenn nötig&lt;br /&gt;
   $msg .= &amp;quot; ACHTUNG!!! Es ist %TEMPERATURE%°C kalt! Somit könnte es glatt werden!&amp;quot; if (%ICE%);&lt;br /&gt;
 &lt;br /&gt;
   # Nachricht senden wenn vorhanden&lt;br /&gt;
   fhem &amp;quot;msg \@%RESIDENT% $msg&amp;quot; if ($msg);&lt;br /&gt;
 }&lt;br /&gt;
&#039;&#039;&#039;Beispielcode für &amp;quot;HomeCMDpresence-present-resident&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   # alle Ankommenden außer mir selbst&lt;br /&gt;
   if (&amp;quot;%RESIDENT%&amp;quot; ne &amp;quot;rr_Dan&amp;quot;)&lt;br /&gt;
   {&lt;br /&gt;
     # Benachrichtigung wenn jemand kommt&lt;br /&gt;
     fhem &amp;quot;msg audio %ALIAS% kommt gerade!&amp;quot; if (&amp;quot;%LOCATION%&amp;quot; ne &amp;quot;arrival&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
     # Nachricht an Ankommende(n) zusammensetzen&lt;br /&gt;
     my $g = &amp;quot;gute&amp;quot;;&lt;br /&gt;
     $g .= &amp;quot;n&amp;quot; if (&amp;quot;%DAYTIME%&amp;quot; ne &amp;quot;Nacht);&lt;br /&gt;
 &lt;br /&gt;
     # Nachricht an Ankommende(n) senden &lt;br /&gt;
     fhem &amp;quot;msg \@%RESIDENT% Willkommen und $g %DAYTIME% %ALIAS%!&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDpresence-&amp;amp;lt;absent/present&amp;amp;gt;-&amp;amp;lt;ROOMMATE/GUEST&amp;amp;gt;====&lt;br /&gt;
Befehle die bei Änderung von presence, ausgelöst durch einen bestimmten Resident, ausgeführt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung presence, ausgelöst durch bestimmten Resident&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====HomeCMDpresence-&amp;amp;lt;absent/present&amp;amp;gt;-&amp;amp;lt;ROOMMATE/GUEST&amp;amp;gt;-&amp;amp;lt;DEVICE&amp;amp;gt;====&lt;br /&gt;
Befehle die bei Änderung von presence, ausgelöst durch ein bestimmtes Presence Device eines bestimmten Resident, ausgeführt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Dieses Attribut ist nur verfügbar wenn ein Resident mehr als ein Presence Device hat&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung presence, ausgelöst durch bestimmtes Presence Device eines bestimmten Resident&lt;br /&gt;
&lt;br /&gt;
====HomeCMDseason====&lt;br /&gt;
Befehle die bei Änderung der Jahreszeit ausgeführt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung Jahreszeit&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   my $t = &amp;quot;%SEASON%&amp;quot;;&lt;br /&gt;
   $t .= &amp;quot;s&amp;quot; if ($t eq &amp;quot;Frühling&amp;quot;);&lt;br /&gt;
   fhem &amp;quot;msg push Die Wohnung ist nun im $t-Modus!&amp;quot;;&lt;br /&gt;
   fhem &amp;quot;set Heizungen [FILTER=controlMode!=auto] controlMode auto&amp;quot; if ($t ne &amp;quot;Sommer&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDseason-&amp;amp;lt;SEASON&amp;amp;gt;====&lt;br /&gt;
Befehle die bei Änderung der Jahreszeit in eine bestimmte Jahreszeit ausgeführt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung bestimmte Jahreszeit&lt;br /&gt;
&lt;br /&gt;
====HomeCMDtwilight====&lt;br /&gt;
Befehle die bei Änderung der Dämmerung ausgeführt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung Dämmerung&lt;br /&gt;
&lt;br /&gt;
====HomeCMDtwilight-&amp;amp;lt;sr/sr_astro/sr_civil/sr_indoor/sr_weather/ss/ss_astro/ss_civil/ss_indoor/ss_weather&amp;amp;gt;====&lt;br /&gt;
Befehle die bei Änderung zu bestimmter Dämmerung ausgeführt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung zu bestimmter Dämmerung&lt;br /&gt;
&lt;br /&gt;
====HomeCMDuwz-warn====&lt;br /&gt;
Befehle die bei Beginn/Ende der UWZ Warnungen ausgeführt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Beginn/Ende der UWZ Warnungen&lt;br /&gt;
&lt;br /&gt;
====HomeCMDuwz-warn-begin====&lt;br /&gt;
Befehle die bei Beginn der UWZ Warnungen ausgeführt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Beginn der UWZ Warnungen&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 msg %UWZLONG%&lt;br /&gt;
&lt;br /&gt;
====HomeCMDuwz-warn-end====&lt;br /&gt;
Befehle die beim Ende der UWZ Warnungen ausgeführt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Ende der UWZ Warnungen&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 msg Alle Unwetterwarnungen sind nun beendet!&lt;br /&gt;
&lt;br /&gt;
=Platzhalter=&lt;br /&gt;
==verfügbar in allen HomeCMD Attributen==&lt;br /&gt;
===%ADDRESS%===&lt;br /&gt;
MAC Adresse des zuletzt ausgelösten Presence Geräts&lt;br /&gt;
&lt;br /&gt;
===%ALARM%===&lt;br /&gt;
Liste mit Namen der ausgelösten Alarm Geräte&amp;lt;br&amp;gt;&lt;br /&gt;
Wert ist 0 wenn kein Alarm Device ausgelöst ist&lt;br /&gt;
&lt;br /&gt;
===%ALARMCT%===&lt;br /&gt;
Anzahl der ausgelösten Alarm Geräte&lt;br /&gt;
&lt;br /&gt;
===%ALARMHR%===&lt;br /&gt;
Liste mit (human readable) Namen der ausgelösten Alarm Geräte&amp;lt;br&amp;gt;&lt;br /&gt;
Wert ist 0 wenn kein Alarm Device ausgelöst ist&amp;lt;br&amp;gt;&lt;br /&gt;
kann z.B. für msg benutzt werden&lt;br /&gt;
&lt;br /&gt;
===%ALIAS%===&lt;br /&gt;
Alias des zuletzt ausgelösten Resident&lt;br /&gt;
&lt;br /&gt;
===%AMODE%===&lt;br /&gt;
aktueller Alarm Mode&lt;br /&gt;
&lt;br /&gt;
===%AEAH%===&lt;br /&gt;
Wert von anyoneElseAtHome&amp;lt;br&amp;gt;&lt;br /&gt;
Wert ist 1 wenn on und 0 wenn off&lt;br /&gt;
&lt;br /&gt;
===%ARRIVERS%===&lt;br /&gt;
Alias-Liste der ROOMMATE/GUEST deren location auf arrival steht&amp;lt;br&amp;gt;&lt;br /&gt;
kann z.B. dafür benutzt werden um Residents zu begrüßen&amp;lt;br&amp;gt;&lt;br /&gt;
z.B. Peter, Paul und Marry&lt;br /&gt;
&lt;br /&gt;
===%AUDIO%===&lt;br /&gt;
Audio Device des zuletzt ausgelösten ROOMMATE/GUEST (Attribut msgContactAudio)&amp;lt;br&amp;gt;&lt;br /&gt;
wenn das Attribut msgContactAudio des jeweiligen Resident keinen Wert hat, so wird versucht den Wert des Attributs aus dem globalMsg (sofern vorhanden) auszulesen&amp;lt;br&amp;gt;&lt;br /&gt;
kann z.B. dafür benutzt werden um Resident spezifische msg(s) vom Typ audio zu senden, z.B. Nacht/Morgen Grüße/Wünsche&lt;br /&gt;
&lt;br /&gt;
===%BATTERYLOW%===&lt;br /&gt;
Alias des zu letzt gemeldeten Geräts mit niedrigem Batteriestand&lt;br /&gt;
&lt;br /&gt;
===%BATTERYLOWALL%===&lt;br /&gt;
Wert des Reading batteryLow_hr&lt;br /&gt;
&lt;br /&gt;
===%BATTERYLOWCT%===&lt;br /&gt;
Wert des Reading batteryLow_ct&lt;br /&gt;
&lt;br /&gt;
===%CONDITION%===&lt;br /&gt;
Wert des Reading condition des überwachten weather Device&amp;lt;br&amp;gt;&lt;br /&gt;
kann z.B. für Wetter(vorhersage) benutzt werden&lt;br /&gt;
&lt;br /&gt;
===%CONTACT%===&lt;br /&gt;
Wert des Reading lastContact (Name des zuletzt geöffneten Kontakt Sensor)&amp;lt;br&amp;gt;&lt;br /&gt;
kann z.B. dafür benutzt werden um msg zu versenden&lt;br /&gt;
&lt;br /&gt;
===%DAYTIME%===&lt;br /&gt;
Wert des Reading daytime&amp;lt;br&amp;gt;&lt;br /&gt;
kann z.B. dafür benutzt werden um Tageszeit spezifische Aktionen zu schalten&lt;br /&gt;
&lt;br /&gt;
===%DEVICE%===&lt;br /&gt;
Name des zuletzt ausgelösten Presence Gerät&lt;br /&gt;
&lt;br /&gt;
===%DEVICEA%===&lt;br /&gt;
Wert des Reading lastAbsentByPresenceDevice&lt;br /&gt;
&lt;br /&gt;
===%DEVICEP%===&lt;br /&gt;
Wert des Reading lastPresentByPresenceDevice&lt;br /&gt;
&lt;br /&gt;
===%DISABLED%===&lt;br /&gt;
Wert des Reading devicesDisabled&lt;br /&gt;
&lt;br /&gt;
===%DND%===&lt;br /&gt;
DND Status&amp;lt;br&amp;gt;&lt;br /&gt;
1 wenn an, 0 wenn aus&lt;br /&gt;
&lt;br /&gt;
===%DURABSENCE%===&lt;br /&gt;
Wert des Reading durTimerAbsence_cr des zu letzt ausgelösten ROOMMATE/GUEST&lt;br /&gt;
&lt;br /&gt;
===%DURABSENCELAST%===&lt;br /&gt;
Wert des Reading lastDurAbsence_cr des zu letzt ausgelösten ROOMMATE/GUEST&lt;br /&gt;
&lt;br /&gt;
===%DURPRESENCE%===&lt;br /&gt;
Wert des Reading durTimerPresence_cr des zu letzt ausgelösten ROOMMATE/GUEST&lt;br /&gt;
&lt;br /&gt;
===%DURPRESENCELAST%===&lt;br /&gt;
Wert des Reading lastDurPresence_cr des zu letzt ausgelösten ROOMMATE/GUEST&lt;br /&gt;
&lt;br /&gt;
===%DURSLEEP%===&lt;br /&gt;
Wert des Reading durTimerSleep_cr des zu letzt ausgelösten ROOMMATE/GUEST&lt;br /&gt;
&lt;br /&gt;
===%DURSLEEPLAST%===&lt;br /&gt;
Wert des Reading lastDurSleep_cr des zu letzt ausgelösten ROOMMATE/GUEST&lt;br /&gt;
&lt;br /&gt;
===%&amp;lt;CALENDARNAME&amp;gt;%===&lt;br /&gt;
Event des benannten Kalenders&amp;lt;br&amp;gt;&lt;br /&gt;
0 wenn kein gerade kein Event ist&lt;br /&gt;
&lt;br /&gt;
===%&amp;lt;CALENDARNAME-EVENTNAME&amp;gt;%===&lt;br /&gt;
0 wenn das benannte Event nicht aktiv ist&amp;lt;br&amp;gt;&lt;br /&gt;
1 wenn das benannte Event aktiv ist&lt;br /&gt;
&lt;br /&gt;
===%FORECAST%===&lt;br /&gt;
Wettervorhersage für morgen&lt;br /&gt;
&lt;br /&gt;
===%FORECASTTODAY%===&lt;br /&gt;
Wettervorhersage für heute&lt;br /&gt;
&lt;br /&gt;
===%HUMIDITY%===&lt;br /&gt;
Wert des Reading humidity von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%HUMIDITYTREND%===&lt;br /&gt;
Wert des Reading humidityTrend von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%ICE%===&lt;br /&gt;
0 wenn keine Eiswarnung besteht&amp;lt;br&amp;gt;&lt;br /&gt;
1 wenn Eiswarnung besteht&lt;br /&gt;
&lt;br /&gt;
===%IP%===&lt;br /&gt;
Wert des Reading publicIP von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%LIGHT%===&lt;br /&gt;
Wert des Reading light von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%LOCATION%===&lt;br /&gt;
Wert des Reading location von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%LOCATIONR%===&lt;br /&gt;
Wert des Reading location des zu letzt ausgelösten ROOMMATE/GUEST&lt;br /&gt;
&lt;br /&gt;
===%LUMINANCE%===&lt;br /&gt;
Wert des Reading luminance von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%LUMINANCETREND%===&lt;br /&gt;
Wert des Reading luminanceTrend von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%MODE%===&lt;br /&gt;
gerade aktiver Modus von HOMEMODE (Reading mode)&lt;br /&gt;
&lt;br /&gt;
===%MODEALARM%===&lt;br /&gt;
aktueller Alarm Mode (wie %AMODE%)&lt;br /&gt;
&lt;br /&gt;
===%MOTION%===&lt;br /&gt;
Wert des Reading lastMotion von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%NAME%===&lt;br /&gt;
Name des HOMEMODE Geräts selbst (identisch zu %SELF%)&lt;br /&gt;
&lt;br /&gt;
===%OPEN%===&lt;br /&gt;
Wert des Reading contactsOutsideOpen von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%OPENCT%===&lt;br /&gt;
Wert des Reading contactsOutsideOpen_ct von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%OPENHR%===&lt;br /&gt;
Wert des Reading contactsOutsideOpen_hr von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%PANIC%===&lt;br /&gt;
0 wenn panic ausgeschaltet ist&amp;lt;br&amp;gt;&lt;br /&gt;
1 wenn panic eingeschaltet ist&lt;br /&gt;
&lt;br /&gt;
===%RESIDENT%===&lt;br /&gt;
Name des zu letzt ausgelösten ROOMMATE/GUEST&lt;br /&gt;
&lt;br /&gt;
===%PRESENT%===&lt;br /&gt;
presence von HOMEMODE&lt;br /&gt;
0 wenn absent&lt;br /&gt;
1 wenn present&lt;br /&gt;
&lt;br /&gt;
===%PRESENTR%===&lt;br /&gt;
presence des zu letzt ausgelösten ROOMMATE/GUEST&lt;br /&gt;
0 wenn absent&lt;br /&gt;
1 wenn present&lt;br /&gt;
&lt;br /&gt;
===%PRESSURE%===&lt;br /&gt;
Wert des Reading pressure von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%PREVAMODE%===&lt;br /&gt;
vorheriger modeAlarm von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%PREVCONTACT%===&lt;br /&gt;
vorheriger geöffneter Kontaktsensor&lt;br /&gt;
&lt;br /&gt;
===%PREVMODE%===&lt;br /&gt;
vorheriger mode von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%PREVMODER%===&lt;br /&gt;
vorheriger state des zu letzt ausgelösten ROOMMATE/GUEST&lt;br /&gt;
&lt;br /&gt;
===%PREVMOTION%===&lt;br /&gt;
vorheriger geöffneter Bewegungsmelder&lt;br /&gt;
&lt;br /&gt;
===%SEASON%===&lt;br /&gt;
Wert des Reading season von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%SELF%===&lt;br /&gt;
Name des HOMEMODE Geräts selbst (identisch zu %NAME%)&lt;br /&gt;
&lt;br /&gt;
===%SENSORSBATTERY%===&lt;br /&gt;
Liste aus Internal SENSORSBATTERY&lt;br /&gt;
&lt;br /&gt;
===%SENSORSCONTACT%===&lt;br /&gt;
Liste aus Internal SENSORSCONTACT&lt;br /&gt;
&lt;br /&gt;
===%SENSORSENERGY%===&lt;br /&gt;
Liste aus Internal SENSORSENERGY&lt;br /&gt;
&lt;br /&gt;
===%SENSORSMOTION%===&lt;br /&gt;
Liste aus Internal SENSORSMOTION&lt;br /&gt;
&lt;br /&gt;
===%SENSORSSMOKE%===&lt;br /&gt;
Liste aus Internal SENSORSSMOKE&lt;br /&gt;
&lt;br /&gt;
===%SMOKE%===&lt;br /&gt;
Wert des Reading alarmSmoke von HOMEMODE&lt;br /&gt;
0 wenn kein Alarm&lt;br /&gt;
&lt;br /&gt;
===%SMOKECT%===&lt;br /&gt;
Wert des Reading alarmSmoke_ct von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%SMOKEHR%===&lt;br /&gt;
Wert des Reading alarmSmoke_hr von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%TAMPERED%===&lt;br /&gt;
Wert des Reading sensorsTampered von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%TAMPEREDCT%===&lt;br /&gt;
Wert des Reading sensorsTampered_ct von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%TAMPEREDHR%===&lt;br /&gt;
Wert des Reading sensorsTampered_hr von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%TEMPERATURE%===&lt;br /&gt;
Wert des Reading temperature von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%TEMPERATURETREND%===&lt;br /&gt;
Wert des Reading temperatureTrend von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%TOBE%===&lt;br /&gt;
are/sind oder is/ist der Wetterkondition&lt;br /&gt;
&lt;br /&gt;
===%TWILIGHT%===&lt;br /&gt;
Wert des Reading twilight von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%TWILIGHTEVENT%===&lt;br /&gt;
aktuelles twilight Event&lt;br /&gt;
&lt;br /&gt;
===%UWZ%===&lt;br /&gt;
UWZ Warnlevel&lt;br /&gt;
&lt;br /&gt;
===%UWZLONG%===&lt;br /&gt;
alle aktuellen UWZ Warnungen (lange Version)&lt;br /&gt;
&lt;br /&gt;
===%UWZSHORT%===&lt;br /&gt;
alle aktuellen UWZ Warnungen (kurze Version)&lt;br /&gt;
&lt;br /&gt;
===%WEATHER%===&lt;br /&gt;
Wert von &amp;quot;get &amp;lt;HOMEMODE&amp;gt; weather short&amp;quot;&lt;br /&gt;
&lt;br /&gt;
===%WEATHERLONG%===&lt;br /&gt;
Wert von &amp;quot;get &amp;lt;HOMEMODE&amp;gt; weather long&amp;quot;&lt;br /&gt;
&lt;br /&gt;
===%WIND%===&lt;br /&gt;
Wert des Reading wind von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%WINDCHILL%===&lt;br /&gt;
Wert des Reading wind_chill vom eingebundenen Wetter Gerät&lt;br /&gt;
&lt;br /&gt;
==verfügbar in den HomeCMDcontact, HomeCMDmotion und HomeCMDalarm Attributen==&lt;br /&gt;
===%ALIAS%===&lt;br /&gt;
alias des zuletzt ausgelösten Kontakt/Bewegungs/Rauchsensors&lt;br /&gt;
&lt;br /&gt;
===%SENSOR%===&lt;br /&gt;
name des zuletzt ausgelösten Kontakt/Bewegungs/Rauchsensors&lt;br /&gt;
&lt;br /&gt;
===%STATE%===&lt;br /&gt;
state des zuletzt ausgelösten Kontakt/Bewegungs/Rauchsensors&lt;br /&gt;
&lt;br /&gt;
==verfügbar in den HomeTextWeatherForecast Attributen==&lt;br /&gt;
===%CONDITION%===&lt;br /&gt;
Wert des Readings condition des eather Geräts&lt;br /&gt;
&lt;br /&gt;
===%DAY%===&lt;br /&gt;
Tag der Wettervorhersage (1 - heute, 2 - morgen)&lt;br /&gt;
&lt;br /&gt;
===%HIGH%===&lt;br /&gt;
maximale Temperatur der Wettervorhersage&lt;br /&gt;
&lt;br /&gt;
===%LOW%===&lt;br /&gt;
minimale Temperatur der Wettervorhersage&lt;br /&gt;
&lt;br /&gt;
==verfügbar in den HomeCMDevent Attributen==&lt;br /&gt;
===%CALENDAR%===&lt;br /&gt;
Name der Kalenders&lt;br /&gt;
&lt;br /&gt;
===%DESCRIPTION%===&lt;br /&gt;
Beschreibung des aktuellen Event des Kalenders (nicht verfügbar bei holiday Geräten)&lt;br /&gt;
&lt;br /&gt;
===%EVENT%===&lt;br /&gt;
Name/Titel des aktuellen Event des Kalenders&lt;br /&gt;
&lt;br /&gt;
===%PREVEVENT%===&lt;br /&gt;
Name/Titel des vorherigen Event des Kalenders&lt;br /&gt;
&lt;br /&gt;
==verfügbar in den HomeCMDdevice Attributen==&lt;br /&gt;
===%DEVICE%===&lt;br /&gt;
name der deaktivierten Geräts&lt;br /&gt;
&lt;br /&gt;
===%ALIAS%===&lt;br /&gt;
alias der deaktivierten Geräts&lt;br /&gt;
&lt;br /&gt;
=Benötigte Events=&lt;br /&gt;
Folgende Events werden von HOMEMODE ausgewertet bzw. werden benötigt damit HOMEMODE vollumfänglich funktionieren kann.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;b&amp;gt;DEVICE-TYPE&amp;lt;/b&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;b&amp;gt;EVENT&amp;lt;/b&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;RESIDENTS&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;state&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;presence&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;ROOMMATE,GUEST&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;state&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;presence&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;wayhome&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;{SENSORSCONTACT}&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;state&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;sabotageError&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;quot;HomeReadings&amp;quot;&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;quot;HomeSensorsContactReadings&amp;quot;&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;{SENSORSMOTION}&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;state&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;sabotageError&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;quot;HomeReadings&amp;quot;&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;quot;HomeSensorsMotionReadings&amp;quot;&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;{SENSORSLUMINANCE}&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;luminance&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;quot;HomeSensorsLuminanceReading&amp;quot;&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;{SENSORSENERGY}&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;power&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;energy&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;quot;HomeSensorsPowerEnergyReadings&amp;quot;&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;{SENSORSBATTERY}&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;battery&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;quot;HomeSensorsBatteryReading&amp;quot;&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;quot;HomePresenceDeviceType&amp;quot;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;presence&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;quot;HomeWeatherDevice&amp;quot;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;humidity&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;temperature&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;wind&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;pressure&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;quot;HomeTwilightDevice&amp;quot;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;light&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;twilight&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;aktEvent&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;pressure&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;quot;HomeSensorTemperatureOutside&amp;quot;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;temperature&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;humidity&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;quot;HomeSensorHumidityOutside&amp;quot;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;humidity&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;quot;HomeSensorWindspeed&amp;quot;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;quot;HomeSensorWindspeed&amp;quot;&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;quot;HomeSensorAirpressure&amp;quot;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;quot;HomeSensorAirpressure&amp;quot;&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;quot;HomeEventsHolidayDevices&amp;quot;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;state&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;quot;HomeUWZ&amp;quot;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;WarnCount&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=HOMEMODE&amp;diff=31002</id>
		<title>HOMEMODE</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=HOMEMODE&amp;diff=31002"/>
		<updated>2019-07-16T08:41:00Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{&lt;br /&gt;
Infobox Modul&lt;br /&gt;
|ModPurpose=Das Modul wurde entworfen um den gesamten Heim-/Hausstatus in einem Gerät abzubilden und viele grundlegende Automationen durch Hinzufügen weiterer Geräte bereitzustellen.&lt;br /&gt;
|ModType=h&lt;br /&gt;
|ModCmdRef=HOMEMODE&lt;br /&gt;
|ModFTopic=64317&lt;br /&gt;
|ModForumArea=Automatisierung&lt;br /&gt;
|ModTechName=22_HOMEMODE.pm&lt;br /&gt;
|ModOwner=DeeSPe&lt;br /&gt;
}}&lt;br /&gt;
Diese Seite beschreibt die Konfiguration und Verwendung des Moduls &#039;&#039;22_HOMEMODE.pm&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
=Allgemeines=&lt;br /&gt;
Das Modul &#039;&#039;22_HOMEMODE.pm&#039;&#039; wurde entworfen um den gesamten Heim-/Hausstatus in einem Gerät abzubilden.&amp;lt;br&amp;gt;&lt;br /&gt;
Die hier aufgeführte Anleitung entspricht dem Modul in Version 1.4.2.&lt;br /&gt;
&lt;br /&gt;
Viele allgemein typische Automationen sind bereits fertig integriert.&lt;br /&gt;
&lt;br /&gt;
Die jeweils per Event auszuführenden Befehle können in den entsprechenden &#039;&#039;HomeCMD...&#039;&#039; Atributen hinterlegt werden und so in der Detail Ansicht des HOMEMODE Geräts übersichtlich angezeigt und bearbeitet werden.&lt;br /&gt;
&lt;br /&gt;
Das Anlegen vieler notify/DOIF ist durch den Einsatz von &#039;&#039;HOMEMODE&#039;&#039; unnötig.&lt;br /&gt;
&lt;br /&gt;
Zusätzlich wurde das Modul für die Verwendung mit HomeKit als GUI optimiert. Alle möglichen Mappings für Homebridge sind bereits enthalten und können über einen set Befehl aktualisiert werden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:HOMEMODE_Device.png|800px]]&lt;br /&gt;
&lt;br /&gt;
==Voraussetzungen==&lt;br /&gt;
Um Modul &#039;&#039;22_HOMEMODE.pm&#039;&#039; benutzen zu können benötigt man als Mindestvoraussetzung ein bereits angelegtes RESIDENTS Gerät mit entsprechenden ROOMMATE/GUEST Geräten.&lt;br /&gt;
&lt;br /&gt;
==Mögliche Automationen==&lt;br /&gt;
Alle Automationen sind optional.&lt;br /&gt;
&lt;br /&gt;
Hier ein paar Beispiele:&lt;br /&gt;
*Änderung des Zustands von ROOMMATE/GUEST Geräten anhand von PRESENCE Geräten&lt;br /&gt;
*Bereitstellung von CMD Attributen für mögliche Events rund um den Heim-/Hausstatus&lt;br /&gt;
*Bereitstellung von Platzhaltern innerhalb der CMD Attribute, z.B. %MODE%, %SEASON% oder %PREVMODE% für die Werte der Readings mode, season und prevMode&lt;br /&gt;
*Einbindung von Kontakt Sensoren, für z.B. Offen-Warnungen nach bestimmten Zeitraum oder Alarm Meldungen in bestimmten Alarm Modus - kann pro Kontakt Sensor konfiguriert werden&lt;br /&gt;
*Einbindung von Bewegungs Sensoren, für z.B. automatische Licht Schaltungen oder Alarm Meldungen in bestimmten Alarm Modus - kann pro Bewegungs Sensor konfiguriert werden&lt;br /&gt;
*Darstellungen und Auslösen von Sabotage Alarmen der eingebundenen Kontakt- und Bewegungssensoren&lt;br /&gt;
*Einbindung von jeweils einem Temperatur und Luftfeuchtigkeitssensor&lt;br /&gt;
*Einbindung eines lokalen Wetter Devices zur Ermittlung und Ausgabe der lokalen Wetterdaten und Erzeugung der Wettervorhersage&lt;br /&gt;
*Einbindung von Power und Energy Sensoren zur Ermittlung der Gesamtmengen&lt;br /&gt;
*Einbindung von Calendar/holiday Devices für spezielle im HOMEMODE Device verfügbar zu machende Events&lt;br /&gt;
*von Uhrzeit abhängiger Anwesend-Modus&lt;br /&gt;
*Bewohner unabhängige Tageszeit-Modus&lt;br /&gt;
*Alarm-Modus&lt;br /&gt;
*DND-Modus&lt;br /&gt;
*Überwachung von Batteriewerten&lt;br /&gt;
&lt;br /&gt;
=HOMEMODE-Gerät=&lt;br /&gt;
==Definition==&lt;br /&gt;
Das HOMEMODE Gerät - hier mit dem Namen &#039;&#039;Home&#039;&#039; versehen - selbst wird über&lt;br /&gt;
 define Home HOMEMODE&lt;br /&gt;
bei Vorhandensein nur eines RESIDENTS Geräts definiert.&lt;br /&gt;
&lt;br /&gt;
Bei Verwendung mehrerer RESIDENTS Geräte muss das Master RESIDENTS Gerät beim Definieren mit angegeben werden&lt;br /&gt;
 define Home HOMEMODE rgr_Residents&lt;br /&gt;
Dieses Modul verwendet das globale Attribut &#039;&#039;language&#039;&#039; zur Bestimmung der Anzeigedaten (Standard: EN=english). Für deutsche Ausgabedaten kann das Attribut&lt;br /&gt;
 attr global language DE&lt;br /&gt;
gesetzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Alternativ kann auch nur das HOMEMODE Gerät auf deutsch geändert werden&lt;br /&gt;
 attr Home HomeLanguage DE&lt;br /&gt;
&lt;br /&gt;
==Set-Befehle==&lt;br /&gt;
&#039;&#039;set &amp;lt;required&amp;gt; [optional]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 set Home anyoneElseAtHome &amp;lt;on/off&amp;gt;&lt;br /&gt;
einschalten wenn jemand anderes zu Hause ist der kein registrierter ROOMMATE/GUEST ist, z.B. Hund/Katze oder unregistrierte Gäste&amp;lt;br&amp;gt;&lt;br /&gt;
wenn eingeschaltet, dann wird der Alarm Mode beim Verlassen statt auf armaway nur auf armhome gestellt&amp;lt;br&amp;gt;&lt;br /&gt;
schaltet man ein und hat schon Haus/Wohnung verlassen, so wird der Alarm Mode von armaway auf armhome gestellt&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%AEAH%&#039;&#039;&#039; ist in allen HomeCMD Attributen verfügbar&lt;br /&gt;
&lt;br /&gt;
 set Home dnd &amp;lt;on/off&amp;gt;&lt;br /&gt;
schaltet den &amp;quot;Bitte nicht stören&amp;quot; Modus ein&amp;lt;br&amp;gt;&lt;br /&gt;
z.B. um Benachrichtigungen zu deaktivieren&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%DND%&#039;&#039;&#039; ist in allen HomeCMD Attributen verfügbar&lt;br /&gt;
&lt;br /&gt;
 set Home dnd-for-minutes &amp;lt;MINUTES&amp;gt;&lt;br /&gt;
schaltet den &amp;quot;Bitte nicht stören&amp;quot; Modus für die angegebenen Minuten ein&amp;lt;br&amp;gt;&lt;br /&gt;
kehrt danach zum vorherigen (tageszeitabhängigen) Modus zurück&lt;br /&gt;
&lt;br /&gt;
 set Home deviceDisable &amp;lt;DEVICE&amp;gt;&lt;br /&gt;
deaktiviert das Gerät für sämtliche HOMEMODE Automationen&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%DISABLED%&#039;&#039;&#039; ist in allen HomeCMD Attributen verfügbar&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%DEVICE%&#039;&#039;&#039; und &#039;&#039;&#039;%ALIAS%&#039;&#039;&#039; sind in allen HomeCMD Attributen verfügbar&lt;br /&gt;
&lt;br /&gt;
 set Home deviceEnable &amp;lt;DEVICE&amp;gt;&lt;br /&gt;
reaktiviert das Gerät für sämtliche HOMEMODE Automationen&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%DISABLED%&#039;&#039;&#039; ist in allen HomeCMD Attributen verfügbar&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%DEVICE%&#039;&#039;&#039; und &#039;&#039;&#039;%ALIAS%&#039;&#039;&#039; sind in allen HomeCMD Attributen verfügbar&lt;br /&gt;
&lt;br /&gt;
 set Home location &amp;lt;arrival/home/bed/underway/wayhome&amp;gt;&lt;br /&gt;
manueller Ortswechsel&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%LOCATION%&#039;&#039;&#039; ist in allen HomeCMD Attributen verfügbar&lt;br /&gt;
&lt;br /&gt;
 set Home mode &amp;lt;morning/day/afternoon/evening/night/gotosleep/asleep/absent/gone/home&amp;gt;&lt;br /&gt;
manueller Moduswechsel&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%MODE%&#039;&#039;&#039; und &#039;&#039;&#039;%PREVMODE%&#039;&#039;&#039; sind in allen HomeCMD Attributen verfügbar&lt;br /&gt;
&lt;br /&gt;
 set Home modeAlarm &amp;lt;armaway/armhome/armnight/disarm&amp;gt;&lt;br /&gt;
schaltet den angegebenen Alarm Modus ein&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%AMODE%&#039;&#039;&#039; und &#039;&#039;&#039;%PREVAMODE%&#039;&#039;&#039; sind in allen HomeCMD Attributen verfügbar&lt;br /&gt;
&lt;br /&gt;
 set Home modeAlarm-for-minutes &amp;lt;armaway/armhome/armnight/disarm&amp;gt; &amp;lt;MINUTES&amp;gt;&lt;br /&gt;
schaltet den angegebenen Alarm Modus für die angegebenen Minuten ein&lt;br /&gt;
kehrt danach zum vorherigen Alarm Modus zurück&lt;br /&gt;
&lt;br /&gt;
 set Home updateHomebridgeMapping&lt;br /&gt;
aktualisiert das Attribut homebridgeMapping des HOMEMODDE Device abhängig von den verfügbaren Informationen&lt;br /&gt;
&lt;br /&gt;
 set Home updateInternalForce&lt;br /&gt;
führt eine Aktualisierung der Internals des HOMEMODE Device aus&amp;lt;br&amp;gt;&lt;br /&gt;
das sollte manuell benutzt werden nachdem das Modul aktualisiert und nur ein reload statt restart gemacht wurde&amp;lt;br&amp;gt;&lt;br /&gt;
auch wenn man überwachte/kontrollierte Geräte ändert sollte man diesen Befehl manuell ausführen, z.B. neue ROOMMATE/GUEST im RESIDENTS Device hinzufügt, oder Geräte in FHEM hinzufügt die dem selben Devspec wie bisher entsprechen (Steckdosen, Sensoren)&lt;br /&gt;
&lt;br /&gt;
==Get-Befehle==&lt;br /&gt;
&#039;&#039;get &amp;lt;required&amp;gt; [optional]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 get Home contactsOpen &amp;lt;all/doorsinside/doorsoutside/doorsmain/outside/windows&amp;gt;&lt;br /&gt;
Liste von all/doorsinside/doorsoutside/doorsmain/outside/windows offenen Kontakten&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%OPEN%&#039;&#039;&#039;, &#039;&#039;&#039;%OPENCT%&#039;&#039;&#039; und &#039;&#039;&#039;%OPENHR%&#039;&#039;&#039; sind in allen HomeCMD Attributen verfügbar&lt;br /&gt;
&lt;br /&gt;
 get Home devicesDisabled&lt;br /&gt;
Anzeige der für HOMEMODE deaktivierten Geräte&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%DISABLED%&#039;&#039;&#039; ist in allen HomeCMD Attributen verfügbar&lt;br /&gt;
&lt;br /&gt;
 get Home mode&lt;br /&gt;
Anzeige von mode&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%MODE%&#039;&#039;&#039; ist in allen HomeCMD Attributen verfügbar&lt;br /&gt;
&lt;br /&gt;
 get Home modeAlarm&lt;br /&gt;
Anzeige von modeAlarm&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%AMODE%&#039;&#039;&#039; und &#039;&#039;&#039;%MODEALARM%&#039;&#039;&#039; sind in allen HomeCMD Attributen verfügbar&lt;br /&gt;
&lt;br /&gt;
 get Home publicIP&lt;br /&gt;
holen der öffentlichen IP Adresse&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%IP%&#039;&#039;&#039; ist in allen HomeCMD Attributen verfügbar&lt;br /&gt;
&lt;br /&gt;
 get Home sensorsTampered&lt;br /&gt;
Liste aller sabotierten Sensoren&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%TAMPERED%&#039;&#039;&#039;, &#039;&#039;&#039;%TAMPEREDCT%&#039;&#039;&#039; und &#039;&#039;&#039;%TAMPEREDHR%&#039;&#039;&#039; sind in allen HomeCMD Attributen verfügbar&lt;br /&gt;
&lt;br /&gt;
 get Home weather &amp;lt;long/short&amp;gt;&lt;br /&gt;
Wetterinfo im angegebenen Format anzeigen&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%WEATHER%&#039;&#039;&#039; und &#039;&#039;&#039;%WEATHERLONG%&#039;&#039;&#039; sind in allen HomeCMD Attributen verfügbar&lt;br /&gt;
&lt;br /&gt;
 get Home weatherForecast [TAG]&lt;br /&gt;
Wettervorhersage für angegebenen Tag&amp;lt;br&amp;gt;&lt;br /&gt;
wenn kein Tag angegeben wird, so wird die Vorhersage für morgen (2) ausgegeben&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%FORECAST%&#039;&#039;&#039; (morgen) und &#039;&#039;&#039;%FORECASTTODAY%&#039;&#039;&#039; (heute) sind in allen HomeCMD Attributen verfügbar&lt;br /&gt;
&lt;br /&gt;
==webCmd==&lt;br /&gt;
Die Schaltmöglichkeiten sind absichtlich gering gehalten, denn im normalen Betrieb sollte nicht mehr benötigt werden als die hier gebotenen.&amp;lt;br&amp;gt;&lt;br /&gt;
Es lässt sich der Alarm Mode manuell umschalten und beim Klick auf das devStateIcon wird der DND Mode an- und ausgeschaltet.&lt;br /&gt;
&lt;br /&gt;
=Konfiguration=&lt;br /&gt;
&lt;br /&gt;
==Grundkonfiguration==&lt;br /&gt;
&lt;br /&gt;
Diese Grundkonfiguration sollte immer als erstes erfolgen um entsprechend darauf weiter aufzubauen. Als zweiter Schritt ist dann die erweiterte Konfiguration angedacht.&lt;br /&gt;
&lt;br /&gt;
Bei der Namensvergabe der Attribute vom HOMEMODE Device wurde nach einem möglichst kurzem Prefix gesucht und nach vielen Tests wurde sich für das Prefix &amp;quot;Home&amp;quot; entschieden. Das hat den Vorteil, dass alle Attribute beisammen stehen und diese auch (durch den Großbuchstaben am Anfang) ziemlich weit oben in der Liste der Attribute stehen. Ebenso wurde bei der Namensvergabe versucht, selbsterklärende Namen zu wählen. Das hat den Vorteil, dass man relativ einfach genau erkennen kann wofür das Attribut steht, allerdings auch den Nachteil, dass einige Attributnamen ganz schön lang werden.&lt;br /&gt;
&lt;br /&gt;
===Attribute===&lt;br /&gt;
&lt;br /&gt;
====HomeAdvancedUserAttr====&lt;br /&gt;
Als Erstes wird empfohlen, gerade für Anfänger, das Attribut &amp;quot;HomeAdvancedUserAttr&amp;quot; auf 1 zu setzen. Dadurch werden viel mehr HomeCMD Attribute freigeschaltet. Diese werden im Attribut userattr des HOMEMODE Device hinzugefügt.&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: 0&lt;br /&gt;
&lt;br /&gt;
====HomeAutoAlarmModes====&lt;br /&gt;
Als Nächstes sollte man sich entscheiden, ob die Alarm Modus evtl. nicht automatisch zum jeweiligen Modus des HOMEMODE Device geschaltet werden sollen. Standardmäßig werden die Alarm Modus automatisch gesteuert. Ist das nicht erwünscht, so ist der Wert dieses Attributs auf 0 zu setzen.&amp;lt;br&amp;gt;&lt;br /&gt;
Bei Modus &amp;quot;absent&amp;quot; des HOMEMODE Device wird automatisch auf &amp;quot;armaway&amp;quot; geschaltet.&amp;lt;br&amp;gt;&lt;br /&gt;
Bei Modus &amp;quot;home&amp;quot; des HOMEMODE Device wird automatisch auf &amp;quot;disarm&amp;quot; geschaltet.&amp;lt;br&amp;gt;&lt;br /&gt;
Bei Modus &amp;quot;asleep&amp;quot; des HOMEMODE Device wird automatisch auf &amp;quot;armnight&amp;quot; geschaltet.&amp;lt;br&amp;gt;&lt;br /&gt;
Alarm Modus &amp;quot;armhome&amp;quot; kann nur manuell gesetzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: 0 oder 1&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: 1&lt;br /&gt;
&lt;br /&gt;
====HomeAutoArrival====&lt;br /&gt;
Ist hier ein Wert größer 0 angegeben, so wird bei Ankunft jedes ROOMMATE/GUEST die location des jeweiligen ROOMMATE/GUEST für die hier angegeben Zeit in Minuten auf &amp;quot;arrival&amp;quot; gesetzt. Beim ersten nach Hause kommenden ROOMMATE/GUEST wird zusätzlich die location des HOMEMODE Device für die hier eingestellte Zeit in Minuten auf &amp;quot;arrival&amp;quot; gesetzt.&amp;lt;br&amp;gt;&lt;br /&gt;
Nach Ablauf der hier eingestellten Minuten wechselt das jeweilige Device von &amp;quot;arrival&amp;quot; auf &amp;quot;home&amp;quot;, sofern es noch die location &amp;quot;arrival&amp;quot; hat.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: 0 bis 5999.9&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: 0&lt;br /&gt;
&lt;br /&gt;
====HomeAutoAsleep====&lt;br /&gt;
Ist hier ein Wert größer 0 angegeben, so wird beim Schlafengehen (gotosleep) jedes ROOMMATE/GUEST ein Timer gestartet, der den jeweiligen ROOMMATE/GUEST nach der hier angegeben Zeit in Minuten auf &amp;quot;asleep&amp;quot; setzt.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: 0 bis 5999.9&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: 0&lt;br /&gt;
&lt;br /&gt;
====HomeAutoAwoken====&lt;br /&gt;
Ist hier ein Wert größer 0 angegeben, so wird beim Erwachen (&amp;quot;awoken&amp;quot; oder &amp;quot;home nach asleep&amp;quot;) jedes ROOMMATE/GUEST dieser auf &amp;quot;awoken&amp;quot; gesetzt und ein Timer gestartet, der den jeweiligen ROOMMATE/GUEST nach der hier angegeben Zeit in Minuten auf &amp;quot;home&amp;quot; setzt.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: 0 bis 5999.9&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: 0&lt;br /&gt;
&lt;br /&gt;
====HomeAutoDaytime====&lt;br /&gt;
Standardmäßig wird mode anhand der Tageszeit automatisch gesetzt. Ist das nicht gewünscht, kann das über den Wert 0 deaktiviert werden. Dann stehen allerdings tageszeitabhängigen mode(s) nicht mehr zur Verfügung.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: 0 oder 1&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: 1&lt;br /&gt;
&lt;br /&gt;
====HomeResidentCmdDelay====&lt;br /&gt;
Normalerweise werden die Events der ROOMMATE/GUEST vor denen des HOMEMODE Device ausgeführt. Um das zu ändern wird die Ausführung der ROOMMATE/GUEST HomeCMD Attribute um die hier eingestellte Zeit in Sekunden verzögert.&amp;lt;br&amp;gt;&lt;br /&gt;
Je genauer der Name des jeweiligen HomeCMD Attributs beschrieben wird, desto später wird dieser ausgeführt.&amp;lt;br&amp;gt;&lt;br /&gt;
Das heißt z.B. dass HomeCMDmode vor HomeCMDmode-absent und dieser wiederrum vor HomeCMDmode-absent-ROOMMATE/GUEST-NAME ausgeführt wird usw.&amp;lt;br&amp;gt;&lt;br /&gt;
Um das normale Verhalten wiederherzustellen ist der Wert dieses Attributs auf 0 zu setzen. Dann wird HomeCMDmode-absent-ROOMMATE/GUEST-NAME vor HomeCMDmode-absent und vor HomeCMDmode ausgeführt.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: 0 bis unendlich in Sekunden&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: 1&lt;br /&gt;
&lt;br /&gt;
==Konfiguration Presence Devices (automatische anwesend/abwesend Umschaltung von ROOMMATE/GUEST)==&lt;br /&gt;
Damit die automatische Zuordnung der Presence Devices zu ihren ROOMMATE/GUEST Devices zuverlässig funktioniert, ist es nötig dass der Hauptteil des Namens des ROOMMATE/GUEST innerhalb des Namens des zugehörigen PRESENCE Device(s) vorkommt.&amp;lt;br&amp;gt;&lt;br /&gt;
Im Attribut HomePresenceDeviceType kann man den zu suchenden TYPE von Presence Device vorgeben.&amp;lt;br&amp;gt;&lt;br /&gt;
Per Default werden nur Devices vom TYPE PRESENCE gesucht und versucht den ROOMMATE/GUEST zuzuweisen.&amp;lt;br&amp;gt;&lt;br /&gt;
Falls man z.B. auch Devices vom TYPE dummy zur Anwesenheitssteuerung benutzt, kann man diese im Attribut HomePresenceDeviceType mit hinzunehmen. Es sind alles Device TYPEn möglich die ein &amp;quot;presence&amp;quot; Reading mit den Werten &amp;quot;present/appeared&amp;quot; und &amp;quot;absent/disappeared&amp;quot; bereitstellen. Mehrere TYPEn sind möglich da in diesem Attribut ein Regex erwartet wird. z.B.: dummy oder PRESENCE|dummy oder PRESENCE|dummy|ONKYO_AVR.&lt;br /&gt;
&lt;br /&gt;
===Beispiel===&lt;br /&gt;
Der Device Name meines ROOMMATE ist &amp;quot;rr_Dan&amp;quot;.&amp;lt;br&amp;gt;&lt;br /&gt;
Auf der Suche nach dem zugehörigen Presence Device wird der erste Teil (rr_ oder rg_) weggeschnitten und der Rest in Kleinbuchstaben umgewandelt.&amp;lt;br&amp;gt;&lt;br /&gt;
Mit dem was übrig bleibt, bei mir also nur dan, werden die möglichen Presence Devices versucht zu erkennen.&amp;lt;br&amp;gt;&lt;br /&gt;
Mein zugehöriges Presence Device heißt, historisch gewachsen, PRESENCE_rr_Dan und würde somit problemlos zugeordnet werden können.&amp;lt;br&amp;gt;&lt;br /&gt;
Die Namen der zugehörigen Presence Devives könnten in ihrer kürzesten Form auch wie folgt sein um meinen ROOMMATE/GUEST Device zugeordnet zu werden:&amp;lt;br&amp;gt;&lt;br /&gt;
 pdan&lt;br /&gt;
 danp&lt;br /&gt;
 ZDan&lt;br /&gt;
 DANZ&lt;br /&gt;
 wenndannsonst&lt;br /&gt;
Aber Achtung, es funktioniert nicht mehr wenn die Namen nicht eindeutig sind. Wenn es z.B. eine rr_Dana geben würde mit Presence Device Name &amp;quot;pdani&amp;quot;, dann würde dieser Name auch bei mir (dan) passen. Das könnte man aber auch bewußt nutzen um mit einem Presence Device 2 ROOMMATE/GUEST Devices gleichzeitig zu steuern.&amp;lt;br&amp;gt;&lt;br /&gt;
Wenn die Namen wirklich absolut eindeutig sind, dann könnte man den Regex im Attribut HomePresenceDeviceType sogar auf &amp;quot;.*&amp;quot; setzen.&lt;br /&gt;
&lt;br /&gt;
Werden pro ROOMMATE/GUEST mehrere Presence Devices gefunden und zugeordnet, so wird automatisch dass Attribut HomePresenceDeviceAbsentCount-&amp;lt;NAME-ROOMMATE/GUEST&amp;gt; auf die Anzahl der gefundenen Presence Devices gesetzt, so dass der/die jeweilige ROOMMATE/GUEST immer erst als abwesend gewertet wird sobald alle zugehörigen Presence Devices abwesend sind. Analog dazu gibt es noch das Attribut HomePresenceDevicePresentCount-&amp;lt;NAME-ROOMMATE/GUEST&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Attribute===&lt;br /&gt;
&lt;br /&gt;
====HomeAutoPresence====&lt;br /&gt;
Ist dieses Attribut auf 1 gesetzt, so werden die ROOMMATE/GUEST Devices automatisch zum Status ihrer zugehörigen PRESENCE Devices geschaltet.&amp;lt;br&amp;gt;&lt;br /&gt;
PRESENCE Device present - ROOMMATE/GUEST home&amp;lt;br&amp;gt;&lt;br /&gt;
PRESENCE Device absent - ROOMMATE/GUEST absent&amp;lt;br&amp;gt;&lt;br /&gt;
Falls es sich bei den von Euch benutzen PRESENCE Devices nicht um Devices vom TYPE PRESENCE handeln sollte, sondern z.B. um PRESENCE und dummy, so kann dieses im Attribut HomePresenceDeviceType als Regex konfiguriert werden! z.B.: PRESENCE|dummy&amp;lt;br&amp;gt;&lt;br /&gt;
Damit ein Device als Presence Device erkannt werden kann, muss dieses über ein presence Reading verfügen.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: 0 oder 1&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: 0&lt;br /&gt;
&lt;br /&gt;
====HomeAutoPresenceSuppressState====&lt;br /&gt;
unterdrücke Anwesenheitsänderung in angegebenen State(s) der RESIDENTS&amp;lt;br&amp;gt;&lt;br /&gt;
z.B. für &amp;quot;mysteriös&amp;quot; verschwindende Anwesenheitsgeräte in der Nacht&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: asleep|awoken|gotosleep&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomePresenceDeviceType====&lt;br /&gt;
Regex des TYPEs/der TYPEn von Presence Devices&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: Regex der Device TYPEn&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: PRESENCE&lt;br /&gt;
&lt;br /&gt;
==Erweiterte Konfiguration==&lt;br /&gt;
Um das HOMEMODE Device vollumfänglich zu benutzen ist es sinnvoll weitere Devices (zur Überwachung) hinzuzufügen.&lt;br /&gt;
&lt;br /&gt;
Die bereits möglichen hinzuzufügenden Devices werden hier folgend nach Attributnamen erklärt.&lt;br /&gt;
&lt;br /&gt;
===Attribute zum Hinzufügen weiterer Geräte===&lt;br /&gt;
&lt;br /&gt;
====HomeEventsCalendarDevices====&lt;br /&gt;
Hier ist ein Devspec von holiday/Calendar Device(s) anzugeben.&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;Es wird empfohlen die holiday/Calendar Namen in Großbuchstaben anzulegen, da dann die daraus resultierenden Platzhalter ebenfalls Großbuchstaben sind und somit zu den anderen Platzhaltern passen.&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Es werden alle Typen von holiday Events (1,2,3,4,5) unterstützt.&amp;lt;br&amp;gt;&lt;br /&gt;
Bei Calendar sind auch gleichzeitig startende/laufende Events möglich, sie müssen nur unterschiedliche Titel haben (summary).&amp;lt;br&amp;gt;&lt;br /&gt;
Der jeweilige Event Text kann auch Leerzeichen enthalten, welche in den HomeCMD Attributen durch Bindestriche (-) ersetzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Diese Devices stellen zusätzlich die Platzhalter &#039;&#039;&#039;%CALENDAR%&#039;&#039;&#039;, &#039;&#039;&#039;%EVENT%&#039;&#039;&#039; und &#039;&#039;&#039;%PREVEVENT%&#039;&#039;&#039; in den HomeCMDevent Attributen zur Verfügung. &#039;&#039;&#039;%CALENDAR%&#039;&#039;&#039; wird dann durch den Namen, &#039;&#039;&#039;%EVENT%&#039;&#039;&#039; durch das aktuelle Event und &#039;&#039;&#039;%PREVEVENT%&#039;&#039;&#039; durch das vorherige Event des jeweiligen Kalenders ersetzt.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Devspec von holiday/Calendar Geräten&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomeEventsHolidayDevices====&lt;br /&gt;
Hier ist ein Devspec von holiday/Calendar Device(s) anzugeben.&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;Es wird empfohlen die holiday/Calendar Namen in Großbuchstaben anzulegen, da dann die daraus resultierenden Platzhalter ebenfalls Großbuchstaben sind und somit zu den anderen Platzhaltern passen.&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Es werden alle Typen von holiday Events (1,2,3,4,5) unterstützt.&amp;lt;br&amp;gt;&lt;br /&gt;
Bei Calendar sind auch gleichzeitig startende/laufende Events möglich, sie müssen nur unterschiedliche Titel haben (summary).&amp;lt;br&amp;gt;&lt;br /&gt;
Der jeweilige Event Text kann auch Leerzeichen enthalten, welche in den HomeCMD Attributen durch Bindestriche (-) ersetzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Diese Devices stellen zusätzlich die Platzhalter &#039;&#039;&#039;%CALENDAR%&#039;&#039;&#039;, &#039;&#039;&#039;%EVENT%&#039;&#039;&#039; und &#039;&#039;&#039;%PREVEVENT%&#039;&#039;&#039; in den HomeCMDevent Attributen zur Verfügung. &#039;&#039;&#039;%CALENDAR%&#039;&#039;&#039; wird dann durch den Namen, &#039;&#039;&#039;%EVENT%&#039;&#039;&#039; durch das aktuelle Event und &#039;&#039;&#039;%PREVEVENT%&#039;&#039;&#039; durch das vorherige Event des jeweiligen Kalenders ersetzt.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Devspec von holiday/Calendar Geräten&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomeSensorAirpressure====&lt;br /&gt;
Luftdrucksensor aussen&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Name des Sensors&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomeSensorHumidityOutside====&lt;br /&gt;
Hier ist der Name des (Haupt)Aussensensors für Luftfeuchtigkeit anzugeben. Dieser muss ein Reading humidity besitzen.&amp;lt;br&amp;gt;&lt;br /&gt;
Falls der Sensor für (Aussen)Luftfeuchtigkeit und Aussentemperatur ein und der selbe ist, so muss dieser nur einmalig im Attribut HomeSensorTemperatureOutside hinterlegt werden. Dieser muss dann die beiden Readings humidity und temperature haben. Im Bedarfsfall können diese Readings auch vorher entsprechend durch eigene userReadings erstellt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Dieser Sensor stellt den Platzhalter &#039;&#039;&#039;%HUMIDITY%&#039;&#039;&#039; für den Wert des Readings humidity zur Verfügung.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Device Name mit Reading humidity&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomeSensorTemperatureOutside====&lt;br /&gt;
Hier ist der Name des (Haupt)Aussentemperatursensors anzugeben. Dieser muss mindestens ein Reading temperature besitzen.&amp;lt;br&amp;gt;&lt;br /&gt;
Falls der Sensor für Aussentemperatur auch ein Reading humidity besitzen sollte und dieses auch der Sensor für die Aussenlufteuchtigkeit ist, so muss dieser nur einmalig hier in diesem Attribut hinterlegt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Dieser Sensor stellt den Platzhalter &#039;&#039;&#039;%TEMPERATURE%&#039;&#039;&#039; für den Wert des Readings temperature zur Verfügung.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Device Name mit Reading temperature und optional humidity&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsContact====&lt;br /&gt;
Hier können alle Kontakt Sensoren als Devspec hinterlegt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Diese Devices stellen zusätzlich die Platzhalter &#039;&#039;&#039;%ALIAS%&#039;&#039;&#039;, &#039;&#039;&#039;%SENSOR%&#039;&#039;&#039; und &#039;&#039;&#039;%STATE%&#039;&#039;&#039; in den HomeCMDcontact Attributen zur Verfügung. &#039;&#039;&#039;%ALIAS%&#039;&#039;&#039; wird dann durch den Alias, &#039;&#039;&#039;%SENSOR%&#039;&#039;&#039; durch den Namen und &#039;&#039;&#039;%STATE%&#039;&#039;&#039; durch den aktuellen state des zuletzt ausgelösten Kontakts ersetzt.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Devspec&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;In meinem Falle sind das optische und magnetische Kontaktsensoren vom HomeMatic. HM-SEC-SCO und HM-SEC-SC-2.&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;Darum ist bei mir als Devspec &#039;&#039;&#039;model=HM-SEC-SC(O|-2)&#039;&#039;&#039; eingetragen um alle diese Kontaktsensoren zu erfassen.&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Nach Übernehmen des Attributs werden alle gefundenen Kontaktsensoren mit ihren Namen im Internal SENSORSCONTACT des HOMEMODE Device einzeln aufgelistet und können dort auch direkt angeklickt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Des weiteren werden beim Übernehmen dieses Attributs jedem Kontaktsensor folgende Attribute im Attribut userattr hinzugefügt:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====HomeContactType=====&lt;br /&gt;
Typ des Kontakts - wird versucht anhand des Namen/Alias beim Hinzufügen zum HOMEMODE Device zu ermitteln, sollte jedoch für jeden Kontaktsensor einzeln überprüft werden&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: doorinside,dooroutside,doormain,window&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: vorgegebene Werteauswahl&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: window&lt;br /&gt;
&lt;br /&gt;
=====HomeModeAlarmActive=====&lt;br /&gt;
Regex der Alarm Mode(s) in denen der Kontaktsensor eine erfolgte Öffnung als Alarm melden soll.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: armaway|armhome|armnight&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Regex von Alarm Modes&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: armaway&lt;br /&gt;
&lt;br /&gt;
=====HomeOpenDontTriggerModes=====&lt;br /&gt;
Regex der Mode(s) des HOMEMODE Device in denen keine Offen Warnungen erfolgen sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Ist ein Kontakt geöffnet während die hier eingestellten Mode(s) eintreten, so wird der noch bestehende Timer abgebrochen. Entgegengesetzt startet er wieder sobal die hier eingestellten Mode(s) verlassen werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Ist hier z.B. &amp;quot;gotosleep|asleep&amp;quot; eingestellt, so kann man z.B. das Fenster schon vor dem Auslösen von gotosleep oder asleep öffnen und der bestehende Offenwarnung-Timer wird dann abgebrochen. Sobald man am Morgen z.B. awoken oder home auslöst, so wird ein neuer Timer gestartet der einen dann an das noch offene Fenster erinnert.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: alle Modes des HOMEMODE Device&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Regex von Modes&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
=====HomeOpenDontTriggerModesResidents=====&lt;br /&gt;
Devspec der ROOMMATE/GUEST Devices deren Status statt der Modes des HOMEMODE Device für Attribut HomeOpenDontTriggerModes benutzt werden soll.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: alle überwachten ROOMMATE/GUEST&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Devspec&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
=====HomeOpenMaxTrigger=====&lt;br /&gt;
Maximale Anzahl an Warnmeldungen&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: 0 bis ~&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: ganze Zahl&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
=====HomeOpenTimes=====&lt;br /&gt;
Leerzeichenseparierte Liste von Offen Warnung Zeiten in Minuten.&amp;lt;br&amp;gt;&lt;br /&gt;
Der erste Wert entspricht der ersten Zeit, der zweite Wert der zweiten Zeit usw.&amp;lt;br&amp;gt;&lt;br /&gt;
Die Anzahl sollte dem Wert im Attribut HomeOpenMaxTrigger entsprechen. Wenn hier weniger Zeiten vorgegeben werden, so wird für weitere Offen Warnungen immer die letzte hier angegebene Zeit verwendet.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: leerzeichenseparierte Liste von Zahlen mit einer Kommmastelle, z.B. 2.5&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: 10&lt;br /&gt;
&lt;br /&gt;
=====HomeOpenTimesDividers=====&lt;br /&gt;
Leerzeichenseparierte Liste von Offenwarnzeit Teilern.&amp;lt;br&amp;gt;&lt;br /&gt;
Es müssen so viele Werte angegeben werden wie in HomeSeasons Jahreszeiten hinterlegt worden sind (Default 4).&amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer normalen Offenwarnzeit von 10 Minuten und den hier anzugebenen Teilern z.B. &amp;quot;2 1 2 3&amp;quot; ergeben sich für Frühling und Herbst Offenwarnzeiten von jeweils 5 Minuten und im Winter 3.3 Minuten.&amp;lt;br&amp;gt;&lt;br /&gt;
Die hier eingetragenen Werte überschreiben die Werte aus dem Attribut HomeSensorsContactOpenTimeDividers des HOMEMODE Device.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: leerzeichenseparierte Liste von Zahlen mit einer Kommmastelle, z.B. 2 1 2 2.5&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
=====HomeReadings=====&lt;br /&gt;
Zwei leerzeichenseparierte Readings für open und sabotage Status.&amp;lt;br&amp;gt;&lt;br /&gt;
Die hier eingetragenen Readings überschreiben die Werte aus dem Attribut HomeSensorsContactReadings des HOMEMODE Device.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: zwei Wörter&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: state sabotageError&lt;br /&gt;
&lt;br /&gt;
=====HomeValues=====&lt;br /&gt;
Regex der Werte die für offen und sabotiert stehen.&amp;lt;br&amp;gt;&lt;br /&gt;
Die hier eingetragenen Werte überschreiben die Werte aus dem Attribut HomeSensorsContactValues des HOMEMODE Device.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Regex&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: open|tilted|on&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsContactReadings====&lt;br /&gt;
Zwei leerzeichenseparierte Readings für open und sabotage Status.&amp;lt;br&amp;gt;&lt;br /&gt;
Die hier eingetragenen Readings sind global für alle Kontaktsensoren, können aber durch setzen des Attributs HomeReadings in jedem Sensor überschrieben werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: zwei Wörter&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: state sabotageError&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsContactValues====&lt;br /&gt;
Regex der Werte die für offen und sabotiert stehen.&amp;lt;br&amp;gt;&lt;br /&gt;
Die hier eingetragenen Werte sind global für alle Kontaktsensoren, können aber durch setzen des Attributs HomeValues in jedem Sensor überschrieben werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Regex&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: open|tilted|on&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsContactOpenTimeDividers====&lt;br /&gt;
Leerzeichenseparierte Liste von Offenwarnzeit Teilern.&amp;lt;br&amp;gt;&lt;br /&gt;
Es müssen so viele Werte angegeben werden wie in HomeSeasons Jahreszeiten hinterlegt worden sind (Default 4).&amp;lt;br&amp;gt;&lt;br /&gt;
Bei einer normalen Offenwarnzeit von 10 Minuten und den hier anzugebenen Teilern z.B. &amp;quot;2 1 2 3&amp;quot; ergeben sich für Frühling und Herbst Offenwarnzeiten von jeweils 5 Minuten und im Winter 3.3 Minuten.&amp;lt;br&amp;gt;&lt;br /&gt;
Die hier eingetragenen Werte sind global für alle Kontaktsensoren, können aber durch setzen des Attributs HomeOpenTimesDividers in jedem Sensor überschrieben werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: leerzeichenseparierte Liste von Zahlen mit max. einer Kommmastelle, z.B. 2 1 2 2.5 (für 4 Jahreszeiten)&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsContactOpenTimeMin====&lt;br /&gt;
Minimale Zeit in Minuten die mindestens für eine Offenwarnung gewartet werden soll - im Falle dass sich durch den Teiler evtl. zu kleine Werte ergeben.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: eine Zahle mit max. einer Kommmastelle, z.B. 2.5&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsContactOpenTimes====&lt;br /&gt;
Leerzeichenseparierte Liste von Offen Warnung Zeiten in Minuten.&amp;lt;br&amp;gt;&lt;br /&gt;
Der erste Wert entspricht der ersten Zeit, der zweite Wert der zweiten Zeit usw.&amp;lt;br&amp;gt;&lt;br /&gt;
Die Anzahl sollte dem Wert im Attribut HomeOpenMaxTrigger entsprechen. Wenn hier weniger Zeiten vorgegeben werden, so wird für weitere Offen Warnungen immer die letzte hier angegebene Zeit verwendet.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: leerzeichenseparierte Liste von Zahlen mit max. einer Kommmastelle, z.B. 7.5&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: 10&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsLuminance====&lt;br /&gt;
Devspec von (Innen-)Lichtsensoren deren Durchschnittswert berechnet werden soll&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Devspec&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsMotion====&lt;br /&gt;
Hier können alle Bewegungs Sensoren als Devspec hinterlegt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Diese Devices stellen zusätzlich die Platzhalter &#039;&#039;&#039;%ALIAS%&#039;&#039;&#039;, &#039;&#039;&#039;%SENSOR%&#039;&#039;&#039; und &#039;&#039;&#039;%STATE%&#039;&#039;&#039; in den HomeCMDmotion Attributen zur Verfügung. &#039;&#039;&#039;%ALIAS%&#039;&#039;&#039; wird dann durch den Alias, &#039;&#039;&#039;%SENSOR%&#039;&#039;&#039; durch den Namen und &#039;&#039;&#039;%STATE%&#039;&#039;&#039; durch den aktuellen state des zuletzt ausgelösten Kontakts ersetzt.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Devspec&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;In meinem Falle sind das Fibaro Motion Sensor Gen4/5.&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;Darum ist bei mir als Devspec &#039;&#039;&#039;modelId=010f-0801-1001|010f-0800-1001&#039;&#039;&#039; eingetragen um alle diese Bewegungssensoren zu erfassen.&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;Damit bei den Gen5 Sensoren auch das open im reading state steht, habe ich mir bei diesen Sensoren ein userReading angelegt.&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Nach Übernehmen des Attributs werden alle gefundenen Bewegungssensoren mit ihren Namen im Internal SENSORSMOTION des HOMEMODE Device einzeln aufgelistet und können dort auch direkt angeklickt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Des weiteren werden beim Übernehmen dieses Attributs jedem Bewegungssensor folgende Attribute im Attribut userattr hinzugefügt:&lt;br /&gt;
&lt;br /&gt;
=====HomeModeAlarmActive=====&lt;br /&gt;
Regex der Alarm Mode(s) in denen der Bewegungssensor eine erfolgte Öffnung als Alarm melden soll.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: armaway|armhome|armnight&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Regex von Alarm Modes&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: armaway&lt;br /&gt;
&lt;br /&gt;
=====HomeReadings=====&lt;br /&gt;
2 leerzeichenseparierte Readings für open und sabotage.&amp;lt;br&amp;gt;&lt;br /&gt;
Die hier eingetragenen Readings überschreiben die Werte aus dem Attribut HomeSensorsMotionReadings des HOMEMODE Device.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: zwei Wörter&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: state sabotageError&lt;br /&gt;
&lt;br /&gt;
=====HomeSensorLocation=====&lt;br /&gt;
Standort des Bewegungssensors (außen oder innen) - wird standardmäßig beim Hinzufügen zum HOMEMODE Device auf &amp;quot;inside&amp;quot; gesetzt, sollte jedoch für jeden Kontaktsensor einzeln überprüft werden&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: inside,outside&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: vorgegebene Werteauswahl&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: inside&lt;br /&gt;
&lt;br /&gt;
=====HomeValues=====&lt;br /&gt;
Regex der Werte die für offen und sabotiert stehen.&amp;lt;br&amp;gt;&lt;br /&gt;
Die hier eingetragenen Werte überschreiben die Werte aus dem Attribut HomeSensorsMotionValues des HOMEMODE Device.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Regex&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: open|on&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsMotionReadings====&lt;br /&gt;
2 leerzeichenseparierte Readings für open und sabotage.&amp;lt;br&amp;gt;&lt;br /&gt;
Die hier eingetragenen Readings sind global für alle Kontaktsensoren, können aber durch setzen des Attributs HomeReadings in jedem Sensor überschrieben werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: zwei Wörter&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: state sabotageError&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsMotionValues====&lt;br /&gt;
Regex der Werte die für offen und sabotiert stehen.&amp;lt;br&amp;gt;&lt;br /&gt;
Die hier eingetragenen Werte sind global für alle Kontaktsensoren, können aber durch setzen des Attributs HomeValues in jedem Sensor überschrieben werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Regex&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: open|on&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsPowerEnergy====&lt;br /&gt;
Hier können alle Energie Sensoren als Devspec hinterlegt werden. Diese müssen die beiden Readings power und energy besitzen.&amp;lt;br&amp;gt;&lt;br /&gt;
Anhand dieser Readings wird dann der Gesamtverbrauch und die derzeitige gesamte Leistungsaufnahme berechnet.&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;In meinem Falle sind das Fibaro Wall Plugs Gen4/5.&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;Darum ist bei mir als Devspec &#039;&#039;&#039;modelId=010f-0600-1000|010f-0602-1001&#039;&#039;&#039; eingetragen um alle diese Energie Sensoren zu erfassen.&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Devspec mit vorhandenen energy und power Readings&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsSmoke====&lt;br /&gt;
Devspec mit Rauchmeldern&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Devspec&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomeSensorWindspeed====&lt;br /&gt;
Sensor für Windgeschwindigkeit&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Name des Sensors und Reading der Windgeschwindigkeit separiert mit : (z.B. ga_Windsensor:wind)&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsBattery====&lt;br /&gt;
Devspec von Batteriesensoren mit einem Reading &amp;quot;battery&amp;quot;&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Devspec&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomeTriggerAnyoneElseAtHome====&lt;br /&gt;
auslösendes Gerät für anyoneElseAtHome&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: device:reading:valueOn:valueOff&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomeTriggerPanic====&lt;br /&gt;
auslösendes Gerät für Panikalarm&amp;lt;br&amp;gt;&lt;br /&gt;
valueOff ist optional, wird es weggelassen, so fungiert valueOn als toggle&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: device:reading:valueOn[:valueOff]&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomeTwilightDevice====&lt;br /&gt;
Hier ist der Name des lokalen Twilight Device anzugeben.&amp;lt;br&amp;gt;&lt;br /&gt;
Diese Device stellt zusätzlich die Platzhalter &#039;&#039;&#039;%LIGHT%&#039;&#039;&#039;, &#039;&#039;&#039;%TWILIGHT%&#039;&#039;&#039; und &#039;&#039;&#039;%TWILIGHTEVENT%&#039;&#039;&#039; in den HomeCMD Attributen zur Verfügung. &#039;&#039;&#039;%LIGHT%&#039;&#039;&#039; wird dann durch das Reading light, &#039;&#039;&#039;%TWILIGHT%&#039;&#039;&#039; durch das Reading twilight und &#039;&#039;&#039;%TWILIGHTEVENT%&#039;&#039;&#039; durch das aktuelle Twilight Event ersetzt.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Devspec&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomeUWZ====&lt;br /&gt;
Hier ist der Name des lokalen UWZ Geräts anzugeben.&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%UWZ%&#039;&#039;&#039;, &#039;&#039;&#039;%UWZSHORT%&#039;&#039;&#039; und &#039;&#039;&#039;%UWZLONG%&#039;&#039;&#039; sind verfügbar in allen HomeCMD Attributen&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Name des UWZ Geräts&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomeWeatherDevice====&lt;br /&gt;
Hier ist der Name des lokalen Weather Geräts anzugeben.&amp;lt;br&amp;gt;&lt;br /&gt;
Diese Device stellt zusätzlich einige Platzhalter zur Verfügung. Für die genaue Beschreibung derer siehe &amp;quot;Platzhalter&amp;quot;.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Devspec&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
===HomeText Attribute===&lt;br /&gt;
Die HomeText Attribute sind größtenteils zur Übersetzung einiger benötigter Begriffe gedacht.&amp;lt;br&amp;gt;&lt;br /&gt;
In den speziellen Attributen die mit HomeTextWeather anfangen, sind ganze Texte mit entsprechenden Platzhaltern einzufügen.&lt;br /&gt;
&lt;br /&gt;
====HomeTextAndAreIs====&lt;br /&gt;
Übersetzung für &amp;quot;and&amp;quot;, &amp;quot;are&amp;quot; und &amp;quot;is&amp;quot;&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar separiert mit |&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Wort/Wörter&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: and|are|is&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 und|sind|ist&lt;br /&gt;
&lt;br /&gt;
====HomeTextClosedOpen====&lt;br /&gt;
Übersetzung für &amp;quot;closed&amp;quot; und &amp;quot;open&amp;quot;&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar separiert mit |&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Wort&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: closed|open&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 geschlossen|geöffnet&lt;br /&gt;
&lt;br /&gt;
====HomeTextNosmokeSmoke====&lt;br /&gt;
Übersetzung für &amp;quot;no smoke&amp;quot; und &amp;quot;smoke&amp;quot;&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar separiert mit |&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Wort&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: no smoke|smoke&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 kein Rauch|Rauch&lt;br /&gt;
&lt;br /&gt;
====HomeTextRisingConstantFalling====&lt;br /&gt;
Übersetzung für &amp;quot;rising&amp;quot;, &amp;quot;constant&amp;quot; und &amp;quot;falling&amp;quot;&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar separiert mit |&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Wort&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: rising|constant|falling&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 steigend|gleichbleibend|fallend&lt;br /&gt;
&lt;br /&gt;
====HomeTextTodayTomorrowAfterTomorrow====&lt;br /&gt;
Übersetzung für &amp;quot;today&amp;quot;, &amp;quot;tomorrow&amp;quot; und &amp;quot;day after tomorrow&amp;quot;&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar separiert mit |&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Wort&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: today|tomorrow|day after tomorrow&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 Heute|Morgen|Übermorgen&lt;br /&gt;
&lt;br /&gt;
====HomeTextWeatherNoForecast====&lt;br /&gt;
Übersetzung für &amp;quot;No forecast available&amp;quot; - Text wenn keine Wettervorhersage verfügbar ist&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Text&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: No forecast available&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 Es ist leider keine Wettervorhersage für den angegebenen Tag verfügbar!&lt;br /&gt;
&lt;br /&gt;
====HomeTextWeatherForecastInSpecDays====&lt;br /&gt;
Text mit Platzhaltern für Wettervorhersage in 4-10 Tagen&amp;lt;br&amp;gt;&lt;br /&gt;
spezielle Platzhalter die nur in diesem Attribut gültig sind: &#039;&#039;&#039;%CONDITION%&#039;&#039;&#039;, &#039;&#039;&#039;%DAY%&#039;&#039;&#039;, &#039;&#039;&#039;%HIGH%&#039;&#039;&#039; und &#039;&#039;&#039;%LOW%&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Text mit Platzhaltern&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 In %DAY% Tagen %CONDITION% bei Temperaturen von %LOW% bis %HIGH%°C.&lt;br /&gt;
&lt;br /&gt;
====HomeTextWeatherForecastToday====&lt;br /&gt;
Text mit Platzhaltern für Wettervorhersage für heute&amp;lt;br&amp;gt;&lt;br /&gt;
spezielle Platzhalter die nur in diesem Attribut gültig sind: &#039;&#039;&#039;%CONDITION%&#039;&#039;&#039;, &#039;&#039;&#039;%DAY%&#039;&#039;&#039;, &#039;&#039;&#039;%HIGH%&#039;&#039;&#039; und &#039;&#039;&#039;%LOW%&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Text mit Platzhaltern&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 %DAY% %CONDITION% bei Temperaturen von %LOW% bis %HIGH%°C. Aktuelle Temperatur %TEMPERATURE%°C bei einer Luftfeuchtigkeit von %HUMIDITY%%. Die gefühlte Temperatur ist %WINDCHILL%°C bei einer Windgeschwindigkeit von %WIND%km/h.&lt;br /&gt;
&lt;br /&gt;
====HomeTextWeatherForecastTomorrow====&lt;br /&gt;
Text mit Platzhaltern für Wettervorhersage für morgen/übermorgen&amp;lt;br&amp;gt;&lt;br /&gt;
spezielle Platzhalter die nur in diesem Attribut gültig sind: &#039;&#039;&#039;%CONDITION%&#039;&#039;&#039;, &#039;&#039;&#039;%DAY%&#039;&#039;&#039;, &#039;&#039;&#039;%HIGH%&#039;&#039;&#039; und &#039;&#039;&#039;%LOW%&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Text mit Platzhaltern&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 %DAY% %CONDITION% bei Temperaturen von %LOW% bis %HIGH%°C.&lt;br /&gt;
&lt;br /&gt;
====HomeTextWeatherLong====&lt;br /&gt;
Langer Text mit Platzhaltern für aktuelle Wetterdaten&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Text mit Platzhaltern&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 Es %TOBE% %CONDITION% bei %TEMPERATURE%°C und %HUMIDITY%% Luftfeuchtigkeit. Die gefühlte Temperatur ist %WINDCHILL%°C bei einer Windgeschwindigkeit von %WIND%km/h. Der Luftdruck liegt bei %PRESSURE%hPa.&lt;br /&gt;
&lt;br /&gt;
====HomeTextWeatherShort====&lt;br /&gt;
Kurzer Text mit Platzhaltern für aktuelle Wetterdaten&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Text mit Platzhaltern&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 %CONDITION%, %TEMPERATURE%°C, %HUMIDITY%% Luftfeuchtigkeit, Luftdruck %PRESSURE%hPa&lt;br /&gt;
&lt;br /&gt;
===weitere Attribute===&lt;br /&gt;
Viele weitere Dinge lassen sich anpassen.&lt;br /&gt;
&lt;br /&gt;
====HomeAdvancedDetails====&lt;br /&gt;
mehr Details anzeigen, abhängig von den zu HOMEMODE hinzugefügten Geräten&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: none, detail, both, room&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Auswahlliste&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: none&lt;br /&gt;
&lt;br /&gt;
====HomeDaytimes====&lt;br /&gt;
Eigene Tageszeiten als Paare aus Zeit|Wort&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: Zeit|Wort Paare separiert mit Leerzeichen&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Zeit|Wort&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: 05:00|morning 10:00|day 14:00|afternoon 18:00|evening 23:00|night&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 00:00|Mitternacht&lt;br /&gt;
 00:05|Nacht&lt;br /&gt;
 06:30|Morgen&lt;br /&gt;
 10:00|Vormittag&lt;br /&gt;
 13:00|Mittag&lt;br /&gt;
 14:30|Nachmittag&lt;br /&gt;
 17:30|Vorabend&lt;br /&gt;
 19:00|Abend&lt;br /&gt;
 23:00|Spätabend&lt;br /&gt;
&lt;br /&gt;
====HomeIcewarningOnOffTemps====&lt;br /&gt;
2 leerzeichenseparierte Temperaturen für das Ein- und Ausschalten der Eiswarnung.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: zwei leerzeichenseparierte Temperaturen mit maximal einer Kommastelle&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: 2 3&lt;br /&gt;
&lt;br /&gt;
====HomeModeAlarmArmDelay====&lt;br /&gt;
Zeit in Sekunden um das aktivieren der Alarmschaltung zu verzögern.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: 0 bis 99999&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: einzelne Zahl (gleiche Verzögerung für alle modeAlarm) oder 3 leerzeichenseparierte Zahlen für jeden modeAlarm (Reihenfolge: armaway armnight armhome)&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: 0&lt;br /&gt;
&lt;br /&gt;
====HomeAtTmpRoom====&lt;br /&gt;
Diesen Raum zu temporäre at(s) hinzufügen die von HOMEMODE generiert werden&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Wort&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomePresenceDeviceAbsentCount-&amp;lt;ROOMMATE/GUEST&amp;gt;====&lt;br /&gt;
Anzahl der dem ROOMMATE/GUEST zugeordneten Presence Geräte um den jeweiligen ROOMMATE/GUEST auf &amp;quot;absent&amp;quot; zu setzen&amp;lt;br&amp;gt;&lt;br /&gt;
Das Attribut ist nur verfügbar wenn mehr als ein Presence Gerät pro ROOMMATE/GUEST gefunden/zugeordnet wurde&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: 0 bis ~&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: einzelne Zahl&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: maximale Anzahl von verfügbaren Presence Geräten für jeden ROOMMATE/GUEST&lt;br /&gt;
&lt;br /&gt;
====HomePresenceDevicePresentCount-&amp;lt;ROOMMATE/GUEST&amp;gt;====&lt;br /&gt;
Anzahl der dem ROOMMATE/GUEST zugeordneten Presence Geräte um den jeweiligen ROOMMATE/GUEST auf &amp;quot;present&amp;quot; zu setzen&amp;lt;br&amp;gt;&lt;br /&gt;
Das Attribut ist nur verfügbar wenn mehr als ein Presence Gerät pro ROOMMATE/GUEST gefunden/zugeordnet wurde&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: 0 bis ~&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: einzelne Zahl&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: 1&lt;br /&gt;
&lt;br /&gt;
====HomePublicIpCheckInterval====&lt;br /&gt;
Interval in Minuten für die Überprüfung der öffentlichen IP-Adresse&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: 0 bis 99999&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: einzelne Zahl&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: 0 (deaktiviert)&lt;br /&gt;
&lt;br /&gt;
====HomeSeasons====&lt;br /&gt;
Eigene Jahreszeiten als Paare aus Datum|Wort&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: Datum|Wort Paare separiert mit Leerzeichen&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Datum|Wort&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: 03.01|spring 06.01|summer 09.01|autumn 12.01|winter&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 03.01|Frühling&lt;br /&gt;
 06.01|Sommer&lt;br /&gt;
 09.01|Herbst&lt;br /&gt;
 12.01|Winter&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsBatteryLowPercentage====&lt;br /&gt;
Prozentsatz um einen Batteriesensor mit geringer Batterie anzuzeigen (nur bei Sensoren die ihren Batteriewert prozentual angeben)&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Zahl&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: 50&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsBatteryReading====&lt;br /&gt;
Reading der Batteriesensoren welches statt &amp;quot;battery&amp;quot; benutzt werden soll&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: einzelnes Wort&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: battery&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsLuminanceReading====&lt;br /&gt;
Reading der Lichtsensoren welches statt &amp;quot;luminance&amp;quot; benutzt werden soll&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: einzelnes Wort&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: luminance&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsPowerEnergyReadings====&lt;br /&gt;
Readings der Power/Energy Sensoren welche statt &amp;quot;power&amp;quot; und &amp;quot;energy&amp;quot; benutzt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: 2 leerzeichenseparierte Wörter&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: power energy&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsSmokeReading====&lt;br /&gt;
Readings der Rauchmelder welche statt &amp;quot;state&amp;quot; benutzt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: ein Wort&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: state&lt;br /&gt;
&lt;br /&gt;
====HomeSensorsSmokeValue====&lt;br /&gt;
Regex der Auslösewerte von Rauchmeldern&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: RegEx&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: on&lt;br /&gt;
&lt;br /&gt;
====HomeSpecialLocation====&lt;br /&gt;
Hier können eigene zusätzliche location(s) als kommaseparierte Liste angegeben werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Diese können dann über &amp;quot;set &amp;lt;HOMEMODE&amp;gt; location &amp;lt;LOCATION&amp;gt;&amp;quot; gesetzt werden. Dazu passend werden HomeCMD Attribute erstellt.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: kommaseparierte Liste von Wörtern&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomeSpecialModes====&lt;br /&gt;
Hier können eigene zusätzliche mode(s) als kommaseparierte Liste angegeben werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Diese können dann über &amp;quot;set &amp;lt;HOMEMODE&amp;gt; mode &amp;lt;MODE&amp;gt;&amp;quot; gesetzt werden. Dazu passend werden HomeCMD Attribute erstellt.&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: kommaseparierte Liste von Wörtern&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert:&lt;br /&gt;
&lt;br /&gt;
====HomeTrendCalcAge====&lt;br /&gt;
Zeit in Sekunden für das Maximalalter des vorherigen Wertes für die Trendberechnung&amp;lt;br&amp;gt;&lt;br /&gt;
Werte: frei wählbar&amp;lt;br&amp;gt;&lt;br /&gt;
Werteformat: Zeit in Sekunden&amp;lt;br&amp;gt;&lt;br /&gt;
Standardwert: 900&lt;br /&gt;
&lt;br /&gt;
Ein weiterer Teil der Konfiguration ist das Befüllen der HomeCMD Attribute. Da dieses durch die Vermischung von FHEM Code, Perl Code und zusätzlichen Platzhaltern erst einmal sehr befremdlich sein kann, habe ich bei der Beschreibung der HomeCMD Attribute teilweise Beispiele hinzugefügt um den Einstieg weiter zu erleichtern.&lt;br /&gt;
&lt;br /&gt;
==HomeCMD Attribute (mit Beispielen)==&lt;br /&gt;
Die HomeCMD Attribute sind zum Festlegen der jeweiligen Schaltaktionen gedacht und können damit evtl. vorhandene notify/DOIF ablösen. Sie können mit FHEM-Code, Perl-Code oder aber auch mit beidem vermischt befüllt werden (wovon ich allerdings abrate). Zusätzlich sind noch diverse Platzhalter (siehe Platzhalter) verfügbar.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Bei Perl-Code innerhalb der HomeCMD Attribute gibt es hier Besonderheiten.&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
*Im Gegensatz zur FHEM-Eingabezeile müssen hier keine Semikolon verdoppelt werden&lt;br /&gt;
*Kommetarzeilen sind zulässig&lt;br /&gt;
*Kommentare am Ende einer Perl-Zeile sind nicht zulässig&lt;br /&gt;
&lt;br /&gt;
Typischer Weise werden in den HomeCMD Attributen weitere Module angesprochen.&amp;lt;br&amp;gt;&lt;br /&gt;
Z.B. benutze ich für jegliche Form der Benachrichtigung den msg Befehl.&lt;br /&gt;
&lt;br /&gt;
Keines der HomeCMD Attribute hat einen Standardwert. Es müssen alle Befehle selbst programmiert werden.&lt;br /&gt;
&lt;br /&gt;
Platzhalter die Text(e) (string) beinhalten, müssen im Perl-Code in Anführungszeichen gesetzt werden (Beispiel %SENSOR%).&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter die Zahlen beinhalten (int,float) sollten nicht in Anführungszeichen gesetzt werden damit Zahlenvergleiche (mittels ==, &amp;lt;=, &amp;gt;=, &amp;gt;, &amp;lt;) funktionieren (Beispiel %LIGHT%, %ICE% oder %TEMPERATURE%).&lt;br /&gt;
&lt;br /&gt;
====HomeCMDalarmSmoke====&lt;br /&gt;
Befehle die beim Anfang/Ende eines Rauchalarms ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====HomeCMDalarmSmoke-off====&lt;br /&gt;
Befehle die beim Ende eines Rauchalarms ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Ende Rauchalarm eines beliebigen (von HOMEMODE überwachten) Rauchmelders&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 msg push ENTWARNUNG: Alle Rauchalarme sind beendet!&lt;br /&gt;
&lt;br /&gt;
====HomeCMDalarmSmoke-on====&lt;br /&gt;
Befehle die bei einem Rauchalarm ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Rauchalarm eines beliebigen (von HOMEMODE überwachten) Rauchmelders&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   my $is = &amp;quot;meldet&amp;quot;;&lt;br /&gt;
   $is = &amp;quot;melden&amp;quot; if (%SMOKECT% &amp;gt; 1);&lt;br /&gt;
   fhem &amp;quot;msg push ACHTUNG: %SMOKEHR% $is Rauchalarm!&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDalarmTampered====&lt;br /&gt;
Befehle die beim Anfang/Ende eines Sabotage Alarms ausgeführt werden sollen.&lt;br /&gt;
&lt;br /&gt;
====HomeCMDalarmTampered-off====&lt;br /&gt;
Befehle die beim Ende eines Sabotage Alarms ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Ende Sabotage Alarm eines beliebigen (von HOMEMODE überwachten) Kontakt-/Bewegungs-Sensors&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 msg push ENTWARNUNG: Alle Manipulationen wurden beseitigt!&lt;br /&gt;
&lt;br /&gt;
====HomeCMDalarmTampered-on====&lt;br /&gt;
Befehle die bei einem Sabotage Alarm ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Sabotage Alarm eines beliebigen (von HOMEMODE überwachten) Kontakt-/Bewegungs-Sensors&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   my $is = &amp;quot;ist&amp;quot;;&lt;br /&gt;
   $is = &amp;quot;sind&amp;quot; if (%TAMPEREDCT% &amp;gt; 1);&lt;br /&gt;
   fhem &amp;quot;msg push ACHTUNG: %TAMPEREDHR% $is sabotiert!&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDalarmTriggered====&lt;br /&gt;
Befehle die beim Anfang/Ende eines Alarms ausgeführt werden sollen.&lt;br /&gt;
&lt;br /&gt;
====HomeCMDalarmTriggered-off====&lt;br /&gt;
Befehle die beim Ende eines Alarms ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Ende Alarm eines beliebigen (von HOMEMODE überwachten) Kontakt-/Bewegungs-Sensors&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 msg ENTWARNUNG: Alle Alarme sind beendet!&lt;br /&gt;
&lt;br /&gt;
====HomeCMDalarmTriggered-on====&lt;br /&gt;
Befehle die bei einem Alarm ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Alarm eines beliebigen (von HOMEMODE überwachten) Kontakt-/Bewegungs-Sensors&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   my $is = &amp;quot;ist&amp;quot;;&lt;br /&gt;
   $is = &amp;quot;sind&amp;quot; if (%ALARMCT% &amp;gt; 1);&lt;br /&gt;
   fhem &amp;quot;msg audio,push,light 3 !!! ALARM !!! %ALARMHR% $is ausgelöst!&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDanyoneElseAtHome====&lt;br /&gt;
Befehle die beim on/off von anyoneElseAtHome ausgeführt werden sollen.&lt;br /&gt;
&lt;br /&gt;
====HomeCMDanyoneElseAtHome-off====&lt;br /&gt;
Befehle die ausgeführt werden sollen sobald anyoneElseAtHome deaktiviert wird.&amp;lt;br&amp;gt;&lt;br /&gt;
Bei Abwesenheit und nicht deaktiviertem HomeAutoAlarmModes wird der Alarm Mode von &amp;quot;armaway&amp;quot; auf &amp;quot;armhome&amp;quot; umgeschaltet damit evtl. vorhandene Bewegungsmelder keinen Alarm mehr melden.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: anyoneElseAtHome on&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 msg HINWEIS: Es ist nun niemand anderes mehr zu Hause!&lt;br /&gt;
&lt;br /&gt;
====HomeCMDanyoneElseAtHome-on====&lt;br /&gt;
Befehle die ausgeführt werden sollen sobald anyoneElseAtHome aktiviert wird.&amp;lt;br&amp;gt;&lt;br /&gt;
Bei Abwesenheit und nicht deaktiviertem HomeAutoAlarmModes wird der Alarm Mode von &amp;quot;armhome&amp;quot; auf &amp;quot;armaway&amp;quot; umgeschaltet damit evtl. vorhandene Bewegungsmelder wieder Alarme melden können.&amp;lt;br&amp;gt;&lt;br /&gt;
Wird anyoneElseAtHome bei Anwesenheit und nicht deaktiviertem HomeAutoAlarmModes aktiviert, so passiert erst einmal nichts, ausser dass die hier angegebenen Befehle ausgeführt werden. Wird dann später die Abwesenheit erkannt, schaltet der Alarm Mode auf &amp;quot;armhome&amp;quot; statt auf &amp;quot;armaway&amp;quot; damit evtl. vorhandene Bewegungsmelder keinen Alarm mehr melden.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: anyoneElseAtHome off&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 msg HINWEIS: Es ist nun noch jemand anderes zu Hause!&lt;br /&gt;
&lt;br /&gt;
====HomeCMDbatteryLow====&lt;br /&gt;
Befehle die ausgeführt werden sollen sobald ein Sensor einen niedrigen Batteriewert meldet.&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   my $msg;&lt;br /&gt;
   $msg = &amp;quot;Die Batterien von %BATTERYLOW% gehen zur Neige und sollten ausgetauscht werden!&amp;quot; if (%BATTERYLOWCT% == 1);&lt;br /&gt;
   $msg = &amp;quot;Die Batterien bei folgenden Geräten sollten ausgetauscht werden: %BATTERYLOWALL%&amp;quot; if (%BATTERYLOWCT% &amp;gt; 1);&lt;br /&gt;
   fhem &amp;quot;msg push $msg&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDcontact====&lt;br /&gt;
Befehle die ausgeführt werden sollen sobald ein Kontaktsensor open/tilted/closed meldet.&amp;lt;br&amp;gt;&lt;br /&gt;
Die speziellen Platzhalter %ALIAS%, %SENSOR% und %STATE% können in diesem Attribut benutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Kontaktsensor open/tilted/closed&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   my $a = &amp;quot;%ALIAS%&amp;quot;;&lt;br /&gt;
   $a =~ s/d/D/;&lt;br /&gt;
   fhem &amp;quot;msg $a ist nun %STATE%!&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDcontactClosed====&lt;br /&gt;
Befehle die ausgeführt werden sollen sobald ein Kontaktsensor geschlossen meldet.&amp;lt;br&amp;gt;&lt;br /&gt;
Die speziellen Platzhalter %ALIAS%, %SENSOR% und %STATE% können in diesem Attribut benutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Kontaktsensor closed&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   my $a = &amp;quot;%ALIAS%&amp;quot;;&lt;br /&gt;
   $a =~ s/d/D/;&lt;br /&gt;
   fhem &amp;quot;msg $a ist nun geschlossen!&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDcontactOpen====&lt;br /&gt;
Befehle die ausgeführt werden sollen sobald ein Kontaktsensor offen meldet.&amp;lt;br&amp;gt;&lt;br /&gt;
Die speziellen Platzhalter &#039;&#039;&#039;%ALIAS%&#039;&#039;&#039;, &#039;&#039;&#039;%SENSOR%&#039;&#039;&#039; und &#039;&#039;&#039;%STATE%&#039;&#039;&#039; können in diesem Attribut benutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Kontaktsensor open/tilted&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   my $a = &amp;quot;%ALIAS%&amp;quot;;&lt;br /&gt;
   $a =~ s/d/D/;&lt;br /&gt;
   fhem &amp;quot;msg $a ist nun offen!&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDcontactDoormain====&lt;br /&gt;
Befehle die ausgeführt werden sollen sobald ein Kontaktsensor des Types doormain open/tilted/closed meldet.&amp;lt;br&amp;gt;&lt;br /&gt;
Die speziellen Platzhalter %ALIAS%, %SENSOR% und %STATE% können in diesem Attribut benutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Kontaktsensor Type doormain open/tilted/closed&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   my $a = &amp;quot;%ALIAS%&amp;quot;;&lt;br /&gt;
   $a =~ s/d/D/;&lt;br /&gt;
   fhem &amp;quot;msg $a ist nun %STATE%!&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDcontactDoormainClosed====&lt;br /&gt;
Befehle die ausgeführt werden sollen sobald ein Kontaktsensor des Types doormain closed meldet.&amp;lt;br&amp;gt;&lt;br /&gt;
Die speziellen Platzhalter &#039;&#039;&#039;%ALIAS%&#039;&#039;&#039;, &#039;&#039;&#039;%SENSOR%&#039;&#039;&#039; und &#039;&#039;&#039;%STATE%&#039;&#039;&#039; können in diesem Attribut benutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Kontaktsensor vom Typ doormain wird geschlossen&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 { &lt;br /&gt;
   # Wenn es Ankommende gibt&lt;br /&gt;
   if (&amp;quot;%ARRIVERS%&amp;quot;)&lt;br /&gt;
   {&lt;br /&gt;
     # Zusammenstellen der Begrüßung&lt;br /&gt;
     my $msg = &amp;quot;Gute&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
     # &amp;quot;n&amp;quot; anhängen wenn Tageszeit nicht Nacht ist&lt;br /&gt;
     $msg .= &amp;quot;n&amp;quot; if (&amp;quot;%DAYTIME%&amp;quot; ne &amp;quot;Nacht&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
     # Leerzeichen einfügen&lt;br /&gt;
     $msg .= &amp;quot; &amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
     # den Feiertag der Tageszeit voranstellen wenn ein Feiertag im Kalender FEIERTAG ist&lt;br /&gt;
     $msg .= &amp;quot;%FEIERTAG%-&amp;quot; if (&amp;quot;%FEIERTAG%&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
     # Tageszeit einfügen&lt;br /&gt;
     $msg .= &amp;quot;%DAYTIME% &amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
     # bei ROOMMATE &amp;quot;zu Hause&amp;quot; in Begrüßung einfügen&lt;br /&gt;
     $msg .= &amp;quot;zu Hause &amp;quot; if (&amp;quot;%RESIDENT%&amp;quot; =~ /^rr_/);&lt;br /&gt;
 &lt;br /&gt;
     # Ankommende einfügen&lt;br /&gt;
     $msg .= &amp;quot;%ARRIVERS%&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
     # Begrüßung am Sonos im Flur ausgeben bei Abwesenheit über 60 min&lt;br /&gt;
     fhem &amp;quot;msg audio \@fl_Sonos $msg!&amp;quot; if (%DURABSENCELAST% &amp;gt; 60);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDcontactDoormainOpen====&lt;br /&gt;
Befehle die ausgeführt werden sollen sobald ein Kontaktsensor des Types doormain open/tilted meldet.&amp;lt;br&amp;gt;&lt;br /&gt;
Die speziellen Platzhalter &#039;&#039;&#039;%ALIAS%&#039;&#039;&#039;, &#039;&#039;&#039;%SENSOR%&#039;&#039;&#039; und &#039;&#039;&#039;%STATE%&#039;&#039;&#039; können in diesem Attribut benutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Kontaktsensor vom Typ doormain geöffnet&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   my $a = &amp;quot;%ALIAS%&amp;quot;;&lt;br /&gt;
   $a =~ s/d/D/;&lt;br /&gt;
   fhem &amp;quot;msg $a ist nun geöffnet!&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDcontactOpenWarning1====&lt;br /&gt;
Befehle die ausgeführt werden sollen sobald ein Kontaktsensor die erste Offenwarnzeit erreicht hat.&amp;lt;br&amp;gt;&lt;br /&gt;
Die speziellen Platzhalter &#039;&#039;&#039;%ALIAS%&#039;&#039;&#039;, &#039;&#039;&#039;%SENSOR%&#039;&#039;&#039; und &#039;&#039;&#039;%STATE%&#039;&#039;&#039; können in diesem Attribut benutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: erste Offenwarnzeit des Kontakts erreicht&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 msg audio %ALIAS% steht noch offen!&lt;br /&gt;
&lt;br /&gt;
====HomeCMDcontactOpenWarning2====&lt;br /&gt;
Befehle die ausgeführt werden sollen sobald ein Kontaktsensor die zweite Offenwarnzeit erreicht hat.&amp;lt;br&amp;gt;&lt;br /&gt;
Die speziellen Platzhalter &#039;&#039;&#039;%ALIAS%&#039;&#039;&#039;, &#039;&#039;&#039;%SENSOR%&#039;&#039;&#039; und &#039;&#039;&#039;%STATE%&#039;&#039;&#039; können in diesem Attribut benutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: ab Erreichen der zweiten Offenwarnzeit des Kontakts&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 msg audio %ALIAS% steht immer noch offen!&lt;br /&gt;
&lt;br /&gt;
====HomeCMDcontactOpenWarningLast====&lt;br /&gt;
Befehle die ausgeführt werden sollen sobald ein Kontaktsensor die letzte Offenwarnzeit erreicht hat.&amp;lt;br&amp;gt;&lt;br /&gt;
Die speziellen Platzhalter &#039;&#039;&#039;%ALIAS%&#039;&#039;&#039;, &#039;&#039;&#039;%SENSOR%&#039;&#039;&#039; und &#039;&#039;&#039;%STATE%&#039;&#039;&#039; können in diesem Attribut benutzt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Erreichen der letzten Offenwarnzeit des Kontakts&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 msg audio Das ist der letzte Hinweis %ALIAS% endlich zu schliessen!&lt;br /&gt;
&lt;br /&gt;
====HomeCMDdaytime====&lt;br /&gt;
Befehle die ausgeführt werden sollen sobald sich die Tageszeit (daytime) auf einen beliebigen Wert ändert.&amp;lt;br&amp;gt;&lt;br /&gt;
Um die jeweilige eingetretene Tageszeit zu ermitteln ist der Platzhalter &#039;&#039;&#039;%DAYTIME%&#039;&#039;&#039; vorgesehen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung der Tageszeit (daytime)&lt;br /&gt;
&lt;br /&gt;
====HomeCMDdaytime-&amp;amp;lt;DAYTIME&amp;amp;gt;====&lt;br /&gt;
Befehle die ausgeführt werden sollen sobald die jeweilige Tageszeit (daytime) erreicht ist.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung der Tageszeit (daytime) auf bestimmten Wert&amp;lt;br&amp;gt;&lt;br /&gt;
Bei &amp;quot;night&amp;quot; könnte man z.B. die Heizung bewohnerunabhängig ausschalten, bei &amp;quot;morning&amp;quot; wieder ein.&lt;br /&gt;
&lt;br /&gt;
====HomeCMDdeviceDisable====&lt;br /&gt;
Befehle die ausgeführt werden sollen sobald ein Gerät deaktiviert wird.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: &#039;set deviceDisable &amp;amp;lt;DEVICE&amp;amp;gt;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   speak &amp;quot;Das Gerät %ALIAS% ist nun deaktiviert!&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
   # optional wirklich attr disable für Device setzen und Konfig speichern&lt;br /&gt;
   #fhem &amp;quot;attr %DEVICE%:FILTER=disable!=1 disable 1; save&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
   # ROOMMATE/GUEST auf gone/none setzen wenn Presence Devices deaktiviert werden&lt;br /&gt;
   if (&amp;quot;%DEVICE%&amp;quot; =~ /^PRESENCE\d?_(r[rg]_.*)/)&lt;br /&gt;
   {&lt;br /&gt;
     my $resident = $1;&lt;br /&gt;
     my $gone = $resident =~ /^rr_/ ? &amp;quot;gone&amp;quot; : &amp;quot;none&amp;quot;;&lt;br /&gt;
     fhem &amp;quot;set $resident:FILTER=state!=$gone state $gone&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDdeviceEnable====&lt;br /&gt;
Befehle die ausgeführt werden sollen sobald ein Gerät aktiviert wird.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: &#039;set deviceEnable &amp;amp;lt;DEVICE&amp;amp;gt;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   speak &amp;quot;Das Gerät %ALIAS% ist nun aktiviert!&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
   # optional attr disable für Device entfernen und Konfig speichern&lt;br /&gt;
   #fhem &amp;quot;deleteattr %DEVICE%:FILTER=disable=1 disable; save&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
   # ROOMMATE/GUEST auf home setzen wenn Presence Devices aktiviert werden und anwesend sind&lt;br /&gt;
   if (&amp;quot;%DEVICE%&amp;quot; =~ /^PRESENCE\d?_(r[rg]_.*)/)&lt;br /&gt;
   {&lt;br /&gt;
     fhem &amp;quot;set $1:FILTER=state!=home state home&amp;quot; if (ReadingsVal(&amp;quot;%DEVICE%&amp;quot;,&amp;quot;presence&amp;quot;,&amp;quot;&amp;quot;) eq &amp;quot;present&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDdnd====&lt;br /&gt;
Befehle die beim Anfang/Ende des DND Modus ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Ende des DND Modus&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   if (%DND%)&lt;br /&gt;
   {&lt;br /&gt;
     fhem &amp;quot;msg audio Der DND Modus ist nun eingeschaltet!&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
   else&lt;br /&gt;
   {&lt;br /&gt;
     fhem &amp;quot;msg audio Der DND Modus ist nun beendet!&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDdnd-off====&lt;br /&gt;
Befehle die beim Ende des DND Modus ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Ende des DND Modus&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 msg audio Der DND Modus ist nun beendet!&lt;br /&gt;
&lt;br /&gt;
====HomeCMDdnd-on====&lt;br /&gt;
Befehle die beim Beginn des DND Modus ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Beginn des DND Modus&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 msg audio Der DND Modus ist nun eingeschaltet!&lt;br /&gt;
&lt;br /&gt;
====HomeCMDevent====&lt;br /&gt;
Befehle die beim Beginn eines beliebigen (holiday)Kalender Events ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Beginn eines beliebigen (holiday)Kalender Events&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%CALENDAR%&#039;&#039;&#039;, &#039;&#039;&#039;%EVENT%&#039;&#039;&#039; und &#039;&#039;&#039;%PREVEVENT%&#039;&#039;&#039; können zusätzlich verwendet werden&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   fhem &amp;quot;set Weihnachten on&amp;quot; if (&amp;quot;%EVENT%&amp;quot; eq &amp;quot;Weihnachten&amp;quot;);&lt;br /&gt;
   fhem &amp;quot;set Weihnachten off&amp;quot; if (&amp;quot;%PREVEVENT%&amp;quot; eq &amp;quot;Weihnachten&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDevent-&amp;amp;lt;KALENDER&amp;amp;gt;-each====&lt;br /&gt;
Befehle die beim Beginn/Ende eines beliebigen (holiday)Kalender Events eines bestimmten KALENDERs ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Beginn eines beliebigen (holiday)Kalender Events eines bestimmten KALENDERs&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%EVENT%&#039;&#039;&#039; und &#039;&#039;&#039;%PREVEVENT%&#039;&#039;&#039; können zusätzlich verwendet werden&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel für &amp;quot;HomeCMDevent-FEIERTAGE-each&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   fhem &amp;quot;set Weihnachten off&amp;quot; if (&amp;quot;%PREVEVENT%&amp;quot; eq &amp;quot;Weihnachten&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&#039;&#039;&#039;Beispiel für &amp;quot;HomeCMDevent-URLAUBDAN-each&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   if (&amp;quot;%EVENT%&amp;quot; =~ /urlaub/i)&lt;br /&gt;
   {&lt;br /&gt;
     speak &amp;quot;Dan hat jetzt Urlaub!!!&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
   elsif (&amp;quot;%PREVEVENT%&amp;quot; =~ /urlaub/i)&lt;br /&gt;
   {&lt;br /&gt;
     speak &amp;quot;Der Urlaub von Dan ist nun zu Ende!!!&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel für &amp;quot;HomeCMDevent-WOHNUNG-each&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   # Heizung an/aus schalten&lt;br /&gt;
   my $heiz = &amp;quot;([bksw]z|ku)_Thermostat&amp;quot;;&lt;br /&gt;
   if (&amp;quot;%EVENT%&amp;quot; =~ /^heizung(..+)?$/i)&lt;br /&gt;
   {&lt;br /&gt;
     my $zeit = $1;&lt;br /&gt;
     if (&amp;quot;%SEASON%&amp;quot; ne &amp;quot;Sommer&amp;quot;)&lt;br /&gt;
     {&lt;br /&gt;
 &lt;br /&gt;
       # morgens nicht alle Thermostaten schalten&lt;br /&gt;
       $heiz = &amp;quot;([bks]z|ku)_Thermostat&amp;quot; if ($zeit &amp;amp;&amp;amp; $zeit =~ /morgens?$/i);&lt;br /&gt;
       fhem &amp;quot;set $heiz:FILTER=controlMode!=day controlMode day&amp;quot;&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
   elsif (&amp;quot;%PREVEVENT%&amp;quot; =~ /^heizung/i)&lt;br /&gt;
   {&lt;br /&gt;
     fhem &amp;quot;set $heiz:FILTER=controlMode!=night controlMode night&amp;quot; if (&amp;quot;%SEASON%&amp;quot; ne &amp;quot;Sommer&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   # WLAN an/aus schalten&lt;br /&gt;
   elsif (&amp;quot;%EVENT%&amp;quot; =~ /^wlan|wifi|wi-fi/i)&lt;br /&gt;
   {&lt;br /&gt;
     fhem &amp;quot;set Router wifi off&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
   elsif (&amp;quot;%PREVEVENT%&amp;quot; =~ /^wlan|wifi|wi-fi/i)&lt;br /&gt;
   {&lt;br /&gt;
     fhem &amp;quot;set Router wifi on&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   # G-Tag für Putzfrau (de)aktivieren&lt;br /&gt;
   elsif (&amp;quot;%EVENT%&amp;quot; =~ /^putz/i)&lt;br /&gt;
   {&lt;br /&gt;
     fhem &amp;quot;set %NAME% deviceEnable PRESENCE_rg_Inge&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
   elsif (&amp;quot;%PREVEVENT%&amp;quot; =~ /^putz/i)&lt;br /&gt;
   {&lt;br /&gt;
     fhem &amp;quot;set %NAME% deviceDisable PRESENCE_rg_Inge&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   # G-Tag für Gast (de)aktivieren&lt;br /&gt;
   elsif (&amp;quot;%EVENT%&amp;quot; =~ /g([aä]|ae)st/i)&lt;br /&gt;
   {&lt;br /&gt;
     fhem &amp;quot;set %NAME% deviceEnable PRESENCE_rg_Gast&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
   elsif (&amp;quot;%PREVEVENT%&amp;quot; =~ /g([aä]|ae)st/i)&lt;br /&gt;
   {&lt;br /&gt;
     fhem &amp;quot;set %NAME% deviceDisable PRESENCE_rg_Gast&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDevent-&amp;amp;lt;KALENDER&amp;amp;gt;-&amp;amp;lt;EVENT&amp;amp;gt;-begin====&lt;br /&gt;
Befehle die beim Beginn eines bestimmten (holiday)Kalender EVENTs eines bestimmten KALENDERs ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Beginn eines bestimmten (holiday)Kalender EVENTs eines bestimmten KALENDERs&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%PREVEVENT%&#039;&#039;&#039; kann zusätzlich verwendet werden&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel für &amp;quot;HomeCMDevent-FEIERTAGE-Neujahr-begin&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
 set %SENSORSENERGY% meterReset&lt;br /&gt;
&lt;br /&gt;
====HomeCMDevent-&amp;amp;lt;KALENDER&amp;amp;gt;-&amp;amp;lt;EVENT&amp;amp;gt;-end====&lt;br /&gt;
Befehle die bei Ende der (holiday)Kalender EVENTs eines bestimmten KALENDERs ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Ende der (holiday)Kalender EVENTs eines bestimmten KALENDERs&amp;lt;br&amp;gt;&lt;br /&gt;
Platzhalter &#039;&#039;&#039;%PREVEVENT%&#039;&#039;&#039; kann zusätzlich verwendet werden&lt;br /&gt;
&lt;br /&gt;
====HomeCMDfhemDEFINED====&lt;br /&gt;
Befehle die ausgeführt werden sollen wenn ein neues Gerät angelegt wird (define)&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   # Jedem neu definierten Gerät den Geräte-TYPE auch als Raum im Menüpunkt Module zuweisen&lt;br /&gt;
   fhem &amp;quot;attr %DEFINED% room Module-&amp;gt;&amp;quot;.InternalVal(&amp;quot;%DEFINED%&amp;quot;,&amp;quot;TYPE&amp;quot;,&amp;quot;default&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDfhemINITIALIZED====&lt;br /&gt;
Befehle die ausgeführt werden sollen wenn FHEM gestartet wurde&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 msg FHEM Home wurde gestartet...&lt;br /&gt;
&lt;br /&gt;
====HomeCMDfhemSAVE====&lt;br /&gt;
Befehle die ausgeführt werden sollen wenn in FHEM die Konfigurationsdatei gespeichert wird&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel (Backup von fhem.cfg und fhem.state):&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   # Datum/Uhrzeit&lt;br /&gt;
   my $now = Timeow();&lt;br /&gt;
   # Leerzeichen durch Unterstriche ersetzen&lt;br /&gt;
   $now =~ s/ /_/g;&lt;br /&gt;
   # Backup der Datei fhem.cfg&lt;br /&gt;
   `cp $attr{global}{configfile} ./backup/fhem.cfg.$now`;&lt;br /&gt;
   # Log-Ausgabe der gespeicherten Datei&lt;br /&gt;
   Log3 undef,3,&amp;quot;saved ./backup/fhem.cfg.$now&amp;quot;;&lt;br /&gt;
   # Backup der Datei fhem.state&lt;br /&gt;
   `cp $attr{global}{statefile} ./backup/fhem.state.$now`;&lt;br /&gt;
   # Log-Ausgabe der gespeicherten Datei&lt;br /&gt;
   Log3 undef,3,&amp;quot;saved ./backup/fhem.state.$now&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDfhemUPDATE====&lt;br /&gt;
Befehle die ausgeführt werden sollen wenn das Update von FHEM ausgeführt wurde&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 msg audio Das Update für FHEM ist beendet!&lt;br /&gt;
&lt;br /&gt;
====HomeCMDicewarning====&lt;br /&gt;
Befehle die bei Anfang/Ende der Eiswarnung ausgeführt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: icewarning 0/1&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   if (%ICE%)&lt;br /&gt;
   {&lt;br /&gt;
     fhem &amp;quot;msg push ACHTUNG!!! Es sind nur noch %TEMPERATURE%°C! Somit könnte es glatt werden!&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
   else&lt;br /&gt;
   {&lt;br /&gt;
     fhem &amp;quot;msg audio Es sind wieder %TEMPERATURE%°C! Die Glättewarnung ist damit beendet!.&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDicewarning-off====&lt;br /&gt;
Befehle die bei Ende der Eiswarnung ausgeführt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: icewarning 0&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 msg audio Es sind wieder %TEMPERATURE%°C! Die Glättewarnung ist damit beendet!&lt;br /&gt;
&lt;br /&gt;
====HomeCMDicewarning-on====&lt;br /&gt;
Befehle die bei Beginn der Eiswarnung ausgeführt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: icewarning 1&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 msg audio ACHTUNG!!! Es sind nur noch %TEMPERATURE%°C! Somit könnte es glatt werden!&lt;br /&gt;
&lt;br /&gt;
====HomeCMDlocation====&lt;br /&gt;
Befehle die beim Ändern der location ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung location&lt;br /&gt;
&lt;br /&gt;
====HomeCMDlocation-&amp;amp;lt;LOCATION&amp;amp;gt;====&lt;br /&gt;
Befehle die bei Änderung auf eine bestimmte location ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung auf bestimmte location&lt;br /&gt;
&lt;br /&gt;
====HomeCMDmode====&lt;br /&gt;
Befehle die beim Ändern von mode ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung mode&lt;br /&gt;
&lt;br /&gt;
====HomeCMDmode-absent-belated====&lt;br /&gt;
Befehle die nachträglich zur Abwesenheit ausgeführt werden sollen, die Zeit kann im Atteribut &amp;quot;HomeModeAbsentBelatedTime&amp;quot; eingestellt werden&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Abwesenheit + XX min&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 set Heizungen [FILTER=controlManu!=off] controlMode night&lt;br /&gt;
&lt;br /&gt;
====HomeCMDmode-&amp;amp;lt;MODE&amp;amp;gt;====&lt;br /&gt;
Befehle die bei Änderung auf einen bestimmten mode ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung auf bestimmten mode&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel für &amp;quot;HomeCMDmode-absent&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
 set HarmonyHub:FILTER=activity!=PowerOff activity PowerOff;&lt;br /&gt;
 set wz_Ventilator:FILTER=speed!=0 speed 0;&lt;br /&gt;
 set TYPE=SONOSPLAYER:FILTER=Volume&amp;gt;0 Volume 0;&lt;br /&gt;
 set Sonos stopAll;&lt;br /&gt;
 sleep 3;&lt;br /&gt;
 set Wohnung [FILTER=state!=off] off&amp;quot;&lt;br /&gt;
&#039;&#039;&#039;Beispiel für &amp;quot;HomeCMDmode-asleep&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
 define atTmp_wz_Media_aus_%SELF% at +01:00:00 set HarmonyHub:FILTER=currentActivity!=PowerOff activity PowerOff;&lt;br /&gt;
 define atTmp_wz_Venti_aus_%SELF% at +01:00:00 set wz_Ventilator:FILTER=speed!=0 speed 0;&lt;br /&gt;
 define atTmp_wzLS_aus_%SELF% at +00:30:00 set wz_LS scene aus;&lt;br /&gt;
 define atTmp_all_Sonos_vol_down_%SELF% at +00:02:00 set TYPE=SONOSPLAYER:FILTER=Volume!=0 Volume 0 1;&lt;br /&gt;
 define atTmp_all_Sonos_off_%SELF% at +00:02:30 set Sonos stopAll;&lt;br /&gt;
 set [sw]z_Auto(Music|Light):FILTER=state!=off off;&lt;br /&gt;
 set Heizungen [FILTER=controlManu!=off] controlMode night&lt;br /&gt;
&#039;&#039;&#039;Beispiel für &amp;quot;HomeCMDmode-awoken&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
 set [sw]z_Auto(Music|Light):FILTER=state!=on on&lt;br /&gt;
&#039;&#039;&#039;Beispiel für &amp;quot;HomeCMDmode-gone&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
 set Heizungen [FILTER=controlManu!=off] controlManu off&lt;br /&gt;
&lt;br /&gt;
====HomeCMDmode-&amp;amp;lt;MODE&amp;amp;gt;-resident====&lt;br /&gt;
Befehle die bei Änderung auf einen bestimmten mode, ausgelöst durch einen beliebigen Resident, ausgeführt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung mode von beliebigem Resident ausgelöst&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel für &amp;quot;HomeCMDmode-asleep-resident&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
 msg audio @%AUDIO% Guten Nacht und schlaf&#039; gut %ALIAS%!&lt;br /&gt;
&#039;&#039;&#039;Beispiel für &amp;quot;HomeCMDmode-awoken-resident&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   my $msg = &amp;quot;Guten&amp;quot;;&lt;br /&gt;
   $msg .= &amp;quot; %FEIERTAG%&amp;quot; if (&amp;quot;%FEIERTAG%&amp;quot;);&lt;br /&gt;
   $msg .= &amp;quot; Morgen %ALIAS%&amp;quot;;&lt;br /&gt;
   fhem &amp;quot;msg audio \@%AUDIO% $msg&amp;quot;;&lt;br /&gt;
   fhem &amp;quot;defmod atTmp_wetter_%RESIDENT%_%SELF% at +00:07:00 msg audio Wettervorhersage für heute: %FORECASTTODAY%&amp;quot;;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDmode-&amp;amp;lt;MODE&amp;amp;gt;-&amp;amp;lt;ROOMMATE/GUEST&amp;amp;gt;====&lt;br /&gt;
Befehle die bei Änderung auf einen bestimmten mode, ausgelöst durch einen bestimmten Resident, ausgeführt werden.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung mode von bestimmten Resident ausgelöst&lt;br /&gt;
&lt;br /&gt;
====HomeCMDmodeAlarm====&lt;br /&gt;
Befehle die beim Ändern von modeAlarm ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung modeAlarm&lt;br /&gt;
&lt;br /&gt;
====HomeCMDmodeAlarm-&amp;amp;lt;armaway/armhome/armnight/disarm&amp;amp;gt;====&lt;br /&gt;
Befehle die bei Änderung auf einen bestimmten modeAlarm ausgeführt werden sollen.&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung auf bestimmten modeAlarm&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel für &amp;quot;HomeCMDmodeAlarm-armaway&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   if (&amp;quot;%PREVAMODE%&amp;quot; eq &amp;quot;disarm&amp;quot;)&lt;br /&gt;
   {&lt;br /&gt;
     # Alarmanlage einschalten&lt;br /&gt;
     fhem &amp;quot;set AA_Arm:FILTER=level!=100 alarmLevel armAll&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
     # Nachricht zusammensetzen&lt;br /&gt;
     my $msg;&lt;br /&gt;
     $msg .= &amp;quot;Die Alarmanlage ist nun scharf geschaltet!&amp;quot; if (&amp;quot;%RESIDENT%&amp;quot; ne &amp;quot;rr_Dan&amp;quot;);&lt;br /&gt;
     my $is = &amp;quot;%ALARMHR%&amp;quot; =~ /und/ ? &amp;quot;sind&amp;quot; : &amp;quot;ist&amp;quot;;&lt;br /&gt;
     $msg .= &amp;quot; &amp;quot; if ($msg);&lt;br /&gt;
     $msg .= &amp;quot;ACHTUNG: %ALARMHR% $is noch offen!!!&amp;quot; if (%ALARMCT%);&lt;br /&gt;
 &lt;br /&gt;
     # Nachricht an ROOMMATE/GUEST senden&lt;br /&gt;
     fhem &amp;quot;msg \@%RESIDENT% $msg&amp;quot; if ($msg);&lt;br /&gt;
 &lt;br /&gt;
     # Eingangstür abschließen falls noch nicht geschehen&lt;br /&gt;
     fhem &amp;quot;set fl_Tuerschloss:FILTER=state!=locked lock&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&#039;&#039;&#039;Beispiel für &amp;quot;HomeCMDmodeAlarm-armhome&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
 AA_Arm:FILTER=level!=25 alarmLevel armExtSens;&lt;br /&gt;
 set fl_Tuerschloss:FILTER=state!=locked lock&lt;br /&gt;
&#039;&#039;&#039;Beispiel für &amp;quot;HomeCMDmodeAlarm-armnight&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
 AA_Arm:FILTER=level!=25 alarmLevel armExtSens;&lt;br /&gt;
 set fl_Tuerschloss:FILTER=state!=locked lock&lt;br /&gt;
&#039;&#039;&#039;Beispiel für &amp;quot;HomeCMDmodeAlarm-disarm&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   # Alarmanlage ausschalten&lt;br /&gt;
   fhem &amp;quot;set AA_Arm:FILTER=level!=0 alarmLevel disarmed&amp;quot;;&lt;br /&gt;
   my $prio = &amp;quot;&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
   # Nachrichtenpriorität auf 1 setzen bei Ankunft (höhere Lautstärke beim Abspielen damit man das auch vor der Tür hört)&lt;br /&gt;
   $prio = &amp;quot; 1&amp;quot; if (&amp;quot;%LOCATION%&amp;quot; eq &amp;quot;arrival&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
   # Nachricht an ROOMMATE/GUEST senden wenn der vorherige alarmMode nicht &amp;quot;armnight&amp;quot; ist&lt;br /&gt;
   fhem &amp;quot;msg audio \@fl_Sonos$prio Die Alarmanlage ist nun ausgeschaltet %ALIAS%!&amp;quot; if (&amp;quot;%PREVAMODE%&amp;quot; ne &amp;quot;armnight&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDmotion====&lt;br /&gt;
Befehle die bei Statusänderung eines beliebigen Bewegungsmelders ausgeführt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: öffnen/schließen eines beliebigen Bewegungsmelders&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   # Raum aus Sensornamen ermitteln, z.B. bz_Sensor&lt;br /&gt;
   my $room = (split /_/,&amp;quot;%SENSOR%&amp;quot;)[0];&lt;br /&gt;
 &lt;br /&gt;
   # Status des structure aller Lichter dieses Raums&lt;br /&gt;
   my $lichter = Value($room.&amp;quot;_Lichter&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
   # Status des dummy Tageslicht&lt;br /&gt;
   my $tl = Value(&amp;quot;Tageslicht&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
   if (&amp;quot;%STATE%&amp;quot; eq &amp;quot;geöffnet&amp;quot;)&lt;br /&gt;
   {&lt;br /&gt;
     # Lichtwert des Sensors&lt;br /&gt;
     my $lum = ReadingsNum(&amp;quot;%SENSOR%&amp;quot;,&amp;quot;luminance&amp;quot;,100);&lt;br /&gt;
 &lt;br /&gt;
     # Löschen des evtl. schon vorhandenen &amp;quot;at&amp;quot;&lt;br /&gt;
     fhem &amp;quot;delete atTmp_Bewegungsmelder_Licht_aus_&amp;quot;.$room.&amp;quot;_%SELF%&amp;quot; if (IsDevice(&amp;quot;atTmp_Bewegungsmelder_Licht_aus_&amp;quot;.$room.&amp;quot;_%SELF%&amp;quot;));&lt;br /&gt;
 &lt;br /&gt;
     # Licht nur wenn kein Tageslicht oder Lichtwert des Sensors kleiner als 10 und AutoLight eingeschaltet und modeAlarm nicht armaway&lt;br /&gt;
     if (($tl eq &amp;quot;off&amp;quot; || $lum &amp;lt; 10) &amp;amp;&amp;amp; $lichter eq &amp;quot;off&amp;quot; &amp;amp;&amp;amp; Value($room.&amp;quot;_AutoLight&amp;quot;) eq &amp;quot;on&amp;quot; &amp;amp;&amp;amp; &amp;quot;%AMODE%&amp;quot; ne &amp;quot;armaway&amp;quot;)&lt;br /&gt;
     {&lt;br /&gt;
       my $scene;&lt;br /&gt;
 &lt;br /&gt;
       # verschiedene Szenen für verschiedene Modus bzw. Aussenlichtstärken&lt;br /&gt;
       if (&amp;quot;%MODE%&amp;quot; eq &amp;quot;gotosleep&amp;quot;)&lt;br /&gt;
       {&lt;br /&gt;
         $scene = &amp;quot;Abend&amp;quot;;&lt;br /&gt;
       }&lt;br /&gt;
       elsif (&amp;quot;%MODE%&amp;quot; eq &amp;quot;asleep&amp;quot;)&lt;br /&gt;
       {&lt;br /&gt;
         $scene = &amp;quot;Nacht&amp;quot;;&lt;br /&gt;
       }&lt;br /&gt;
       elsif (%LIGHT% &amp;gt; 3)&lt;br /&gt;
       {&lt;br /&gt;
         $scene = &amp;quot;viel&amp;quot;;&lt;br /&gt;
       }&lt;br /&gt;
       elsif (%LIGHT% &amp;lt; 4)&lt;br /&gt;
       {&lt;br /&gt;
         $scene = &amp;quot;mittel&amp;quot;;&lt;br /&gt;
       }&lt;br /&gt;
 &lt;br /&gt;
       # Schalten der entsprechenden Szene (Modul LightScene)&lt;br /&gt;
       fhem &amp;quot;set &amp;quot;.$room.&amp;quot;_LS scene $scene&amp;quot; if ($scene);&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
   else&lt;br /&gt;
   {&lt;br /&gt;
     # unterschiedliche Ausschaltzeiten für unterschiedliche Räume&lt;br /&gt;
     my $t = 3;&lt;br /&gt;
     $t = 15 if ($room eq &amp;quot;wz&amp;quot;);&lt;br /&gt;
     $t = 2 if ($room eq &amp;quot;bz&amp;quot; || ($room =~ /wz|ku/ &amp;amp;&amp;amp; &amp;quot;%MODE%&amp;quot; =~ /sleep/));&lt;br /&gt;
     $t = 1 if ($room eq &amp;quot;fl&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
     # Zahl in Minuten umrechnen in einen Zeitpunkt für das &amp;quot;at&amp;quot;&lt;br /&gt;
     my $d = HOMEMODE_hourMaker($t);&lt;br /&gt;
 &lt;br /&gt;
     # Anlegen des &amp;quot;at&amp;quot; zum Ausschalten des Lichts wenn die Lichter angeschaltet sind und auch AutoLight eingeschaltet ist&lt;br /&gt;
     if ($lichter ne &amp;quot;off&amp;quot; &amp;amp;&amp;amp; Value($room.&amp;quot;_AutoLight&amp;quot;) eq &amp;quot;on&amp;quot;)&lt;br /&gt;
     {&lt;br /&gt;
       my $cmd = &amp;quot;set &amp;quot;.$room.&amp;quot;_LS scene aus&amp;quot;;&lt;br /&gt;
       fhem &amp;quot;defmod atTmp_Bewegungsmelder_Licht_aus_&amp;quot;.$room.&amp;quot;_%SELF% at +$d $cmd&amp;quot;;&lt;br /&gt;
     }&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDmotion-off====&lt;br /&gt;
Befehle die bei Ende der Bewegung eines beliebigen Bewegungsmelders ausgeführt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Ende der Bewegung eines beliebigen Bewegungsmelders&lt;br /&gt;
&lt;br /&gt;
====HomeCMDmotion-on====&lt;br /&gt;
Befehle die bei Beginn der Bewegung eines beliebigen Bewegungsmelders ausgeführt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Beginn der Bewegung eines beliebigen Bewegungsmelders&lt;br /&gt;
&lt;br /&gt;
====HomeCMDpresence-&amp;amp;lt;absent/present&amp;amp;gt;====&lt;br /&gt;
Befehle die bei Änderung von presence ausgeführt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung presence&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel für &amp;quot;HomeCMDpresence-present&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
 set w_Steckdosen [FILTER=state!=on] on;&lt;br /&gt;
 set Heizungen [FILTER=controlManu!=off] controlMode auto&lt;br /&gt;
&lt;br /&gt;
====HomeCMDpresence-&amp;amp;lt;absent/present&amp;amp;gt;-device====&lt;br /&gt;
Befehle die bei Änderung von presence, ausgelöst durch ein beliebiges Presence Device, ausgeführt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung presence, ausgelöst durch beliebiges Presence Device&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel für &amp;quot;HomeCMDpresence-present-device&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   # mindestens 1x täglich den Batteriewert des PRESENCE Geräts bei erkannter Anwesenheit holen&lt;br /&gt;
   fhem &#039;&amp;quot;sudo /opt/fhem/scripts/GTag-bat.sh %DEVICE% %ADDRESS% &amp;amp;&amp;quot;&#039;&lt;br /&gt;
     if (&amp;quot;%DEVICE%&amp;quot; =~ /^PRESENCE_/ &amp;amp;&amp;amp; (!defined ReadingsVal(&amp;quot;%DEVICE%&amp;quot;,&amp;quot;battery&amp;quot;,undef) || ReadingsAge(&amp;quot;%DEVICE%&amp;quot;,&amp;quot;battery&amp;quot;,0) &amp;gt; 64800));&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDpresence-&amp;amp;lt;absent/present&amp;amp;gt;-resident====&lt;br /&gt;
Befehle die bei Änderung von presence, ausgelöst durch einen beliebigen Resident, ausgeführt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung presence, ausgelöst durch beliebigen Resident&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel für &amp;quot;HomeCMDpresence-absent-resident&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   # Mich benachrichtigen wenn ich nicht zu hause bin und jemand anderes die Wohnung verlässt&lt;br /&gt;
   fhem &amp;quot;msg push \@rr_Dan %ALIAS% hat gerade die Wohnung verlassen!&amp;quot;&lt;br /&gt;
     if (&amp;quot;%RESIDENT%&amp;quot; ne &amp;quot;rr_Dan&amp;quot; &amp;amp;&amp;amp; ReadingsVal(&amp;quot;rr_Dan&amp;quot;,&amp;quot;presence&amp;quot;,&amp;quot;&amp;quot;) ne &amp;quot;present&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
   # Verabschiedungsnachricht zusammensetzen&lt;br /&gt;
   my $msg;&lt;br /&gt;
 &lt;br /&gt;
   # Alle außer mich selbst verabschieden&lt;br /&gt;
   $msg .= &amp;quot;Bis bald und auf Wiedersehen %ALIAS%...&amp;quot; if (&amp;quot;%RESIDENT%&amp;quot; ne &amp;quot;rr_Dan&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
   # Glättewarnung wenn nötig&lt;br /&gt;
   $msg .= &amp;quot; ACHTUNG!!! Es ist %TEMPERATURE%°C kalt! Somit könnte es glatt werden!&amp;quot; if (%ICE%);&lt;br /&gt;
 &lt;br /&gt;
   # Nachricht senden wenn vorhanden&lt;br /&gt;
   fhem &amp;quot;msg \@%RESIDENT% $msg&amp;quot; if ($msg);&lt;br /&gt;
 }&lt;br /&gt;
&#039;&#039;&#039;Beispielcode für &amp;quot;HomeCMDpresence-present-resident&amp;quot;:&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   # alle Ankommenden außer mir selbst&lt;br /&gt;
   if (&amp;quot;%RESIDENT%&amp;quot; ne &amp;quot;rr_Dan&amp;quot;)&lt;br /&gt;
   {&lt;br /&gt;
     # Benachrichtigung wenn jemand kommt&lt;br /&gt;
     fhem &amp;quot;msg audio %ALIAS% kommt gerade!&amp;quot; if (&amp;quot;%LOCATION%&amp;quot; ne &amp;quot;arrival&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
     # Nachricht an Ankommende(n) zusammensetzen&lt;br /&gt;
     my $g = &amp;quot;gute&amp;quot;;&lt;br /&gt;
     $g .= &amp;quot;n&amp;quot; if (&amp;quot;%DAYTIME%&amp;quot; ne &amp;quot;Nacht);&lt;br /&gt;
 &lt;br /&gt;
     # Nachricht an Ankommende(n) senden &lt;br /&gt;
     fhem &amp;quot;msg \@%RESIDENT% Willkommen und $g %DAYTIME% %ALIAS%!&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDpresence-&amp;amp;lt;absent/present&amp;amp;gt;-&amp;amp;lt;ROOMMATE/GUEST&amp;amp;gt;====&lt;br /&gt;
Befehle die bei Änderung von presence, ausgelöst durch einen bestimmten Resident, ausgeführt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung presence, ausgelöst durch bestimmten Resident&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====HomeCMDpresence-&amp;amp;lt;absent/present&amp;amp;gt;-&amp;amp;lt;ROOMMATE/GUEST&amp;amp;gt;-&amp;amp;lt;DEVICE&amp;amp;gt;====&lt;br /&gt;
Befehle die bei Änderung von presence, ausgelöst durch ein bestimmtes Presence Device eines bestimmten Resident, ausgeführt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Dieses Attribut ist nur verfügbar wenn ein Resident mehr als ein Presence Device hat&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung presence, ausgelöst durch bestimmtes Presence Device eines bestimmten Resident&lt;br /&gt;
&lt;br /&gt;
====HomeCMDseason====&lt;br /&gt;
Befehle die bei Änderung der Jahreszeit ausgeführt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung Jahreszeit&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel&#039;&#039;&#039;&lt;br /&gt;
 {&lt;br /&gt;
   my $t = &amp;quot;%SEASON%&amp;quot;;&lt;br /&gt;
   $t .= &amp;quot;s&amp;quot; if ($t eq &amp;quot;Frühling&amp;quot;);&lt;br /&gt;
   fhem &amp;quot;msg push Die Wohnung ist nun im $t-Modus!&amp;quot;;&lt;br /&gt;
   fhem &amp;quot;set Heizungen [FILTER=controlMode!=auto] controlMode auto&amp;quot; if ($t ne &amp;quot;Sommer&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
====HomeCMDseason-&amp;amp;lt;SEASON&amp;amp;gt;====&lt;br /&gt;
Befehle die bei Änderung der Jahreszeit in eine bestimmte Jahreszeit ausgeführt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung bestimmte Jahreszeit&lt;br /&gt;
&lt;br /&gt;
====HomeCMDtwilight====&lt;br /&gt;
Befehle die bei Änderung der Dämmerung ausgeführt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung Dämmerung&lt;br /&gt;
&lt;br /&gt;
====HomeCMDtwilight-&amp;amp;lt;sr/sr_astro/sr_civil/sr_indoor/sr_weather/ss/ss_astro/ss_civil/ss_indoor/ss_weather&amp;amp;gt;====&lt;br /&gt;
Befehle die bei Änderung zu bestimmter Dämmerung ausgeführt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Änderung zu bestimmter Dämmerung&lt;br /&gt;
&lt;br /&gt;
====HomeCMDuwz-warn====&lt;br /&gt;
Befehle die bei Beginn/Ende der UWZ Warnungen ausgeführt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Beginn/Ende der UWZ Warnungen&lt;br /&gt;
&lt;br /&gt;
====HomeCMDuwz-warn-begin====&lt;br /&gt;
Befehle die bei Beginn der UWZ Warnungen ausgeführt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Beginn der UWZ Warnungen&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 msg %UWZLONG%&lt;br /&gt;
&lt;br /&gt;
====HomeCMDuwz-warn-end====&lt;br /&gt;
Befehle die beim Ende der UWZ Warnungen ausgeführt werden sollen&amp;lt;br&amp;gt;&lt;br /&gt;
Auslöser: Ende der UWZ Warnungen&amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
 msg Alle Unwetterwarnungen sind nun beendet!&lt;br /&gt;
&lt;br /&gt;
=Platzhalter=&lt;br /&gt;
==verfügbar in allen HomeCMD Attributen==&lt;br /&gt;
===%ADDRESS%===&lt;br /&gt;
MAC Adresse des zuletzt ausgelösten Presence Geräts&lt;br /&gt;
&lt;br /&gt;
===%ALARM%===&lt;br /&gt;
Liste mit Namen der ausgelösten Alarm Geräte&amp;lt;br&amp;gt;&lt;br /&gt;
Wert ist 0 wenn kein Alarm Device ausgelöst ist&lt;br /&gt;
&lt;br /&gt;
===%ALARMCT%===&lt;br /&gt;
Anzahl der ausgelösten Alarm Geräte&lt;br /&gt;
&lt;br /&gt;
===%ALARMHR%===&lt;br /&gt;
Liste mit (human readable) Namen der ausgelösten Alarm Geräte&amp;lt;br&amp;gt;&lt;br /&gt;
Wert ist 0 wenn kein Alarm Device ausgelöst ist&amp;lt;br&amp;gt;&lt;br /&gt;
kann z.B. für msg benutzt werden&lt;br /&gt;
&lt;br /&gt;
===%ALIAS%===&lt;br /&gt;
Alias des zuletzt ausgelösten Resident&lt;br /&gt;
&lt;br /&gt;
===%AMODE%===&lt;br /&gt;
aktueller Alarm Mode&lt;br /&gt;
&lt;br /&gt;
===%AEAH%===&lt;br /&gt;
Wert von anyoneElseAtHome&amp;lt;br&amp;gt;&lt;br /&gt;
Wert ist 1 wenn on und 0 wenn off&lt;br /&gt;
&lt;br /&gt;
===%ARRIVERS%===&lt;br /&gt;
Alias-Liste der ROOMMATE/GUEST deren location auf arrival steht&amp;lt;br&amp;gt;&lt;br /&gt;
kann z.B. dafür benutzt werden um Residents zu begrüßen&amp;lt;br&amp;gt;&lt;br /&gt;
z.B. Peter, Paul und Marry&lt;br /&gt;
&lt;br /&gt;
===%AUDIO%===&lt;br /&gt;
Audio Device des zuletzt ausgelösten ROOMMATE/GUEST (Attribut msgContactAudio)&amp;lt;br&amp;gt;&lt;br /&gt;
wenn das Attribut msgContactAudio des jeweiligen Resident keinen Wert hat, so wird versucht den Wert des Attributs aus dem globalMsg (sofern vorhanden) auszulesen&amp;lt;br&amp;gt;&lt;br /&gt;
kann z.B. dafür benutzt werden um Resident spezifische msg(s) vom Typ audio zu senden, z.B. Nacht/Morgen Grüße/Wünsche&lt;br /&gt;
&lt;br /&gt;
===%BATTERYLOW%===&lt;br /&gt;
Alias des zu letzt gemeldeten Geräts mit niedrigem Batteriestand&lt;br /&gt;
&lt;br /&gt;
===%BATTERYLOWALL%===&lt;br /&gt;
Wert des Reading batteryLow_hr&lt;br /&gt;
&lt;br /&gt;
===%BATTERYLOWCT%===&lt;br /&gt;
Wert des Reading batteryLow_ct&lt;br /&gt;
&lt;br /&gt;
===%CONDITION%===&lt;br /&gt;
Wert des Reading condition des überwachten weather Device&amp;lt;br&amp;gt;&lt;br /&gt;
kann z.B. für Wetter(vorhersage) benutzt werden&lt;br /&gt;
&lt;br /&gt;
===%CONTACT%===&lt;br /&gt;
Wert des Reading lastContact (Name des zuletzt geöffneten Kontakt Sensor)&amp;lt;br&amp;gt;&lt;br /&gt;
kann z.B. dafür benutzt werden um msg zu versenden&lt;br /&gt;
&lt;br /&gt;
===%DAYTIME%===&lt;br /&gt;
Wert des Reading daytime&amp;lt;br&amp;gt;&lt;br /&gt;
kann z.B. dafür benutzt werden um Tageszeit spezifische Aktionen zu schalten&lt;br /&gt;
&lt;br /&gt;
===%DEVICE%===&lt;br /&gt;
Name des zuletzt ausgelösten Presence Gerät&lt;br /&gt;
&lt;br /&gt;
===%DEVICEA%===&lt;br /&gt;
Wert des Reading lastAbsentByPresenceDevice&lt;br /&gt;
&lt;br /&gt;
===%DEVICEP%===&lt;br /&gt;
Wert des Reading lastPresentByPresenceDevice&lt;br /&gt;
&lt;br /&gt;
===%DISABLED%===&lt;br /&gt;
Wert des Reading devicesDisabled&lt;br /&gt;
&lt;br /&gt;
===%DND%===&lt;br /&gt;
DND Status&amp;lt;br&amp;gt;&lt;br /&gt;
1 wenn an, 0 wenn aus&lt;br /&gt;
&lt;br /&gt;
===%DURABSENCE%===&lt;br /&gt;
Wert des Reading durTimerAbsence_cr des zu letzt ausgelösten ROOMMATE/GUEST&lt;br /&gt;
&lt;br /&gt;
===%DURABSENCELAST%===&lt;br /&gt;
Wert des Reading lastDurAbsence_cr des zu letzt ausgelösten ROOMMATE/GUEST&lt;br /&gt;
&lt;br /&gt;
===%DURPRESENCE%===&lt;br /&gt;
Wert des Reading durTimerPresence_cr des zu letzt ausgelösten ROOMMATE/GUEST&lt;br /&gt;
&lt;br /&gt;
===%DURPRESENCELAST%===&lt;br /&gt;
Wert des Reading lastDurPresence_cr des zu letzt ausgelösten ROOMMATE/GUEST&lt;br /&gt;
&lt;br /&gt;
===%DURSLEEP%===&lt;br /&gt;
Wert des Reading durTimerSleep_cr des zu letzt ausgelösten ROOMMATE/GUEST&lt;br /&gt;
&lt;br /&gt;
===%DURSLEEPLAST%===&lt;br /&gt;
Wert des Reading lastDurSleep_cr des zu letzt ausgelösten ROOMMATE/GUEST&lt;br /&gt;
&lt;br /&gt;
===%&amp;lt;CALENDARNAME&amp;gt;%===&lt;br /&gt;
Event des benannten Kalenders&amp;lt;br&amp;gt;&lt;br /&gt;
0 wenn kein gerade kein Event ist&lt;br /&gt;
&lt;br /&gt;
===%&amp;lt;CALENDARNAME-EVENTNAME&amp;gt;%===&lt;br /&gt;
0 wenn das benannte Event nicht aktiv ist&amp;lt;br&amp;gt;&lt;br /&gt;
1 wenn das benannte Event aktiv ist&lt;br /&gt;
&lt;br /&gt;
===%FORECAST%===&lt;br /&gt;
Wettervorhersage für morgen&lt;br /&gt;
&lt;br /&gt;
===%FORECASTTODAY%===&lt;br /&gt;
Wettervorhersage für heute&lt;br /&gt;
&lt;br /&gt;
===%HUMIDITY%===&lt;br /&gt;
Wert des Reading humidity von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%HUMIDITYTREND%===&lt;br /&gt;
Wert des Reading humidityTrend von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%ICE%===&lt;br /&gt;
0 wenn keine Eiswarnung besteht&amp;lt;br&amp;gt;&lt;br /&gt;
1 wenn Eiswarnung besteht&lt;br /&gt;
&lt;br /&gt;
===%IP%===&lt;br /&gt;
Wert des Reading publicIP von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%LIGHT%===&lt;br /&gt;
Wert des Reading light von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%LOCATION%===&lt;br /&gt;
Wert des Reading location von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%LOCATIONR%===&lt;br /&gt;
Wert des Reading location des zu letzt ausgelösten ROOMMATE/GUEST&lt;br /&gt;
&lt;br /&gt;
===%LUMINANCE%===&lt;br /&gt;
Wert des Reading luminance von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%LUMINANCETREND%===&lt;br /&gt;
Wert des Reading luminanceTrend von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%MODE%===&lt;br /&gt;
gerade aktiver Modus von HOMEMODE (Reading mode)&lt;br /&gt;
&lt;br /&gt;
===%MODEALARM%===&lt;br /&gt;
aktueller Alarm Mode (wie %AMODE%)&lt;br /&gt;
&lt;br /&gt;
===%MOTION%===&lt;br /&gt;
Wert des Reading lastMotion von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%NAME%===&lt;br /&gt;
Name des HOMEMODE Geräts selbst (identisch zu %SELF%)&lt;br /&gt;
&lt;br /&gt;
===%OPEN%===&lt;br /&gt;
Wert des Reading contactsOutsideOpen von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%OPENCT%===&lt;br /&gt;
Wert des Reading contactsOutsideOpen_ct von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%OPENHR%===&lt;br /&gt;
Wert des Reading contactsOutsideOpen_hr von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%PANIC%===&lt;br /&gt;
0 wenn panic ausgeschaltet ist&amp;lt;br&amp;gt;&lt;br /&gt;
1 wenn panic eingeschaltet ist&lt;br /&gt;
&lt;br /&gt;
===%RESIDENT%===&lt;br /&gt;
Name des zu letzt ausgelösten ROOMMATE/GUEST&lt;br /&gt;
&lt;br /&gt;
===%PRESENT%===&lt;br /&gt;
presence von HOMEMODE&lt;br /&gt;
0 wenn absent&lt;br /&gt;
1 wenn present&lt;br /&gt;
&lt;br /&gt;
===%PRESENTR%===&lt;br /&gt;
presence des zu letzt ausgelösten ROOMMATE/GUEST&lt;br /&gt;
0 wenn absent&lt;br /&gt;
1 wenn present&lt;br /&gt;
&lt;br /&gt;
===%PRESSURE%===&lt;br /&gt;
Wert des Reading pressure von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%PREVAMODE%===&lt;br /&gt;
vorheriger modeAlarm von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%PREVCONTACT%===&lt;br /&gt;
vorheriger geöffneter Kontaktsensor&lt;br /&gt;
&lt;br /&gt;
===%PREVMODE%===&lt;br /&gt;
vorheriger mode von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%PREVMODER%===&lt;br /&gt;
vorheriger state des zu letzt ausgelösten ROOMMATE/GUEST&lt;br /&gt;
&lt;br /&gt;
===%PREVMOTION%===&lt;br /&gt;
vorheriger geöffneter Bewegungsmelder&lt;br /&gt;
&lt;br /&gt;
===%SEASON%===&lt;br /&gt;
Wert des Reading season von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%SELF%===&lt;br /&gt;
Name des HOMEMODE Geräts selbst (identisch zu %NAME%)&lt;br /&gt;
&lt;br /&gt;
===%SENSORSBATTERY%===&lt;br /&gt;
Liste aus Internal SENSORSBATTERY&lt;br /&gt;
&lt;br /&gt;
===%SENSORSCONTACT%===&lt;br /&gt;
Liste aus Internal SENSORSCONTACT&lt;br /&gt;
&lt;br /&gt;
===%SENSORSENERGY%===&lt;br /&gt;
Liste aus Internal SENSORSENERGY&lt;br /&gt;
&lt;br /&gt;
===%SENSORSMOTION%===&lt;br /&gt;
Liste aus Internal SENSORSMOTION&lt;br /&gt;
&lt;br /&gt;
===%SENSORSSMOKE%===&lt;br /&gt;
Liste aus Internal SENSORSSMOKE&lt;br /&gt;
&lt;br /&gt;
===%SMOKE%===&lt;br /&gt;
Wert des Reading alarmSmoke von HOMEMODE&lt;br /&gt;
0 wenn kein Alarm&lt;br /&gt;
&lt;br /&gt;
===%SMOKECT%===&lt;br /&gt;
Wert des Reading alarmSmoke_ct von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%SMOKEHR%===&lt;br /&gt;
Wert des Reading alarmSmoke_hr von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%TAMPERED%===&lt;br /&gt;
Wert des Reading sensorsTampered von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%TAMPEREDCT%===&lt;br /&gt;
Wert des Reading sensorsTampered_ct von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%TAMPEREDHR%===&lt;br /&gt;
Wert des Reading sensorsTampered_hr von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%TEMPERATURE%===&lt;br /&gt;
Wert des Reading temperature von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%TEMPERATURETREND%===&lt;br /&gt;
Wert des Reading temperatureTrend von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%TOBE%===&lt;br /&gt;
are/sind oder is/ist der Wetterkondition&lt;br /&gt;
&lt;br /&gt;
===%TWILIGHT%===&lt;br /&gt;
Wert des Reading twilight von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%TWILIGHTEVENT%===&lt;br /&gt;
aktuelles twilight Event&lt;br /&gt;
&lt;br /&gt;
===%UWZ%===&lt;br /&gt;
UWZ Warnlevel&lt;br /&gt;
&lt;br /&gt;
===%UWZLONG%===&lt;br /&gt;
alle aktuellen UWZ Warnungen (lange Version)&lt;br /&gt;
&lt;br /&gt;
===%UWZSHORT%===&lt;br /&gt;
alle aktuellen UWZ Warnungen (kurze Version)&lt;br /&gt;
&lt;br /&gt;
===%WEATHER%===&lt;br /&gt;
Wert von &amp;quot;get &amp;lt;HOMEMODE&amp;gt; weather short&amp;quot;&lt;br /&gt;
&lt;br /&gt;
===%WEATHERLONG%===&lt;br /&gt;
Wert von &amp;quot;get &amp;lt;HOMEMODE&amp;gt; weather long&amp;quot;&lt;br /&gt;
&lt;br /&gt;
===%WIND%===&lt;br /&gt;
Wert des Reading wind von HOMEMODE&lt;br /&gt;
&lt;br /&gt;
===%WINDCHILL%===&lt;br /&gt;
Wert des Reading wind_chill vom eingebundenen Wetter Gerät&lt;br /&gt;
&lt;br /&gt;
==verfügbar in den HomeCMDcontact, HomeCMDmotion und HomeCMDalarm Attributen==&lt;br /&gt;
===%ALIAS%===&lt;br /&gt;
alias des zuletzt ausgelösten Kontakt/Bewegungs/Rauchsensors&lt;br /&gt;
&lt;br /&gt;
===%SENSOR%===&lt;br /&gt;
name des zuletzt ausgelösten Kontakt/Bewegungs/Rauchsensors&lt;br /&gt;
&lt;br /&gt;
===%STATE%===&lt;br /&gt;
state des zuletzt ausgelösten Kontakt/Bewegungs/Rauchsensors&lt;br /&gt;
&lt;br /&gt;
==verfügbar in den HomeTextWeatherForecast Attributen==&lt;br /&gt;
===%CONDITION%===&lt;br /&gt;
Wert des Readings condition des eather Geräts&lt;br /&gt;
&lt;br /&gt;
===%DAY%===&lt;br /&gt;
Tag der Wettervorhersage (1 - heute, 2 - morgen)&lt;br /&gt;
&lt;br /&gt;
===%HIGH%===&lt;br /&gt;
maximale Temperatur der Wettervorhersage&lt;br /&gt;
&lt;br /&gt;
===%LOW%===&lt;br /&gt;
minimale Temperatur der Wettervorhersage&lt;br /&gt;
&lt;br /&gt;
==verfügbar in den HomeCMDevent Attributen==&lt;br /&gt;
===%CALENDAR%===&lt;br /&gt;
Name der Kalenders&lt;br /&gt;
&lt;br /&gt;
===%DESCRIPTION%===&lt;br /&gt;
Beschreibung des aktuellen Event des Kalenders (nicht verfügbar bei holiday Geräten)&lt;br /&gt;
&lt;br /&gt;
===%EVENT%===&lt;br /&gt;
Name/Titel des aktuellen Event des Kalenders&lt;br /&gt;
&lt;br /&gt;
===%PREVEVENT%===&lt;br /&gt;
Name/Titel des vorherigen Event des Kalenders&lt;br /&gt;
&lt;br /&gt;
==verfügbar in den HomeCMDdevice Attributen==&lt;br /&gt;
===%DEVICE%===&lt;br /&gt;
name der deaktivierten Geräts&lt;br /&gt;
&lt;br /&gt;
===%ALIAS%===&lt;br /&gt;
alias der deaktivierten Geräts&lt;br /&gt;
&lt;br /&gt;
=Benötigte Events=&lt;br /&gt;
Folgende Events werden von HOMEMODE ausgewertet bzw. werden benötigt damit HOMEMODE vollumfänglich funktionieren kann.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;b&amp;gt;DEVICE-TYPE&amp;lt;/b&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;b&amp;gt;EVENT&amp;lt;/b&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;RESIDENTS&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;state&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;presence&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;ROOMMATE,GUEST&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;state&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;presence&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;wayhome&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;{SENSORSCONTACT}&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;state&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;sabotageError&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;quot;HomeReadings&amp;quot;&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;quot;HomeSensorsContactReadings&amp;quot;&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;{SENSORSMOTION}&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;state&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;sabotageError&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;quot;HomeReadings&amp;quot;&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;quot;HomeSensorsMotionReadings&amp;quot;&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;{SENSORSLUMINANCE}&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;luminance&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;quot;HomeSensorsLuminanceReading&amp;quot;&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;{SENSORSENERGY}&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;power&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;energy&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;quot;HomeSensorsPowerEnergyReadings&amp;quot;&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;{SENSORSBATTERY}&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;battery&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;quot;HomeSensorsBatteryReading&amp;quot;&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;quot;HomePresenceDeviceType&amp;quot;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;presence&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;quot;HomeWeatherDevice&amp;quot;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;humidity&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;temperature&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;wind&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;pressure&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;quot;HomeTwilightDevice&amp;quot;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;light&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;twilight&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;aktEvent&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;pressure&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;quot;HomeSensorTemperatureOutside&amp;quot;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;temperature&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;humidity&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;quot;HomeSensorHumidityOutside&amp;quot;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;humidity&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;quot;HomeSensorWindspeed&amp;quot;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;quot;HomeSensorWindspeed&amp;quot;&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;quot;HomeSensorAirpressure&amp;quot;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;quot;HomeSensorAirpressure&amp;quot;&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;quot;HomeEventsHolidayDevices&amp;quot;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;state&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
  &amp;lt;tr&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;&amp;quot;HomeUWZ&amp;quot;&amp;lt;/td&amp;gt;&lt;br /&gt;
    &amp;lt;td&amp;gt;WarnCount&amp;lt;/td&amp;gt;&lt;br /&gt;
  &amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=24925</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=24925"/>
		<updated>2018-01-31T07:23:09Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: &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=h&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
== Konfiguration ==&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;
=== Hinweis zu den Code Beispielen ===&lt;br /&gt;
Es handelt sich bei den Beispielen um eine Raw definition, siehe auch [[Import_von_Code_Snippets]]&lt;br /&gt;
&lt;br /&gt;
=== msgConfig ===&lt;br /&gt;
&lt;br /&gt;
Als erstes 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 userattr msgDialog_evalSpecials:textField-long msgDialog_msgCommand:textField&lt;br /&gt;
attr myMsgConfig msgContactPush &amp;lt;Name des TelegramBot-device&amp;gt;&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;
&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;
;msgDialog_evalSpecials&lt;br /&gt;
: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. Wenn der selbe Name im msgConfig und msgDialog definiert wurde, wird der Wert aus msgDialog verwendet.&lt;br /&gt;
&lt;br /&gt;
;msgDialog_msgCommand &amp;lt;command&amp;gt;&lt;br /&gt;
:Befehl zum Versenden einer Nachricht. Die Vorgabe ist &amp;quot;msg push \@$recipients $message&amp;quot;. Wenn nicht gesetzt, wird die Vorgabe verwendet.&lt;br /&gt;
&lt;br /&gt;
=== ROOMMATE / GUEST ===&lt;br /&gt;
Für jeden Dialog kann festgelegt werden welche Person 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 fhemMsgRcvPush ein Event erzeugt. Siehe auch Attribut &amp;quot;allowed&amp;quot; in msgDialog.&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;: &amp;quot;deletereading TYPE=msgDialog $recipient_history&amp;quot;,\&lt;br /&gt;
    &amp;quot;message&amp;quot;: [\&lt;br /&gt;
      &amp;quot;{return(&#039;(&#039; . join(&#039;) (&#039;, sort{lc($a) cmp lc($b)} (split(&#039;\n&#039;, fhem(&#039;get TYPE=msgDialog:FILTER=NAME!=$SELF:FILTER=allowed=.*($recipient|everyone).* trigger&#039;, 1)))) . &#039;) (abbrechen) &#039;)}&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;zurück&amp;quot;: {\&lt;br /&gt;
    &amp;quot;commands&amp;quot;: &amp;quot;set $recipient_history=.+ say @$recipient {(ReadingsVal($DEV, &#039;$recipient_history&#039;, &#039;&#039;) =~ m/((.+)\\|.+$)/;;;; return($2 || $1);;;;)}&amp;quot;\&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;: &amp;quot;deletereading TYPE=msgDialog $recipient_history&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;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;: &amp;quot;deletereading TYPE=msgDialog $recipient_history&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;Dialog beendet.&amp;quot;\&lt;br /&gt;
    ]\&lt;br /&gt;
  }\&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
attr meta_Dialog allowed everyone&lt;br /&gt;
&amp;lt;/pre&amp;gt;&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 &#039;&#039;&#039;DEF&#039;&#039;&#039; 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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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&lt;br /&gt;
:Kann einen einzelnen oder mehrere Befehle enthalten: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;commands&amp;quot;: &amp;quot;single command&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&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 &lt;br /&gt;
: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;: [&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;
&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;
=== 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;
=== 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;
=== 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;
== Hilfe bei der Fehlersuche ==&lt;br /&gt;
Hier entsteht eine Sammlung von Tipps bei der Fehlersuche. Die meisten dieser &amp;quot;Stolpersteine&amp;quot;&lt;br /&gt;
entstehen häufig bei der Erstellung eines ersten eigenen Dialoges.&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut allowed fehlt oder ist nicht korrekt gesetzt ===&lt;br /&gt;
Das allowed-Attribut dient dazu, einzelne Dialoge für alle  oder nur bestimmte Benutzer zu berechtigen.&lt;br /&gt;
Fehlt es, wird der Dialog dem aufrufenden Benutzer nicht angezeigt.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr Testdialog allowed everyone&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut msgDialog_evalSpecials fehlt oder ist nicht korrekt gesetzt ===&lt;br /&gt;
Dieses Attribut gehört dem msgConfig device und muss wie in 2.3 zu lesen&lt;br /&gt;
korrekt befüllt werden.&lt;br /&gt;
&amp;lt;pre&amp;gt;&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut utf8Special fehlt beim TelegramBot device ===&lt;br /&gt;
Dieses Attribut ist für die korrekte UTF-8 Kodierung zuständig und im Standard deaktiviert.&lt;br /&gt;
Der Satz &amp;quot;Was kann ich für dich tun?&amp;quot; aus dem Meta-Dialog enthält bereits einen Umlaut!&lt;br /&gt;
&lt;br /&gt;
=== JSON-Syntax Fehler ===&lt;br /&gt;
Das Modul prüft vor dem Abspeichern auf eine korrekte JSON-Syntax.&lt;br /&gt;
Meistens wird auch eine sprechende Meldung angezeigt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Usage: define &amp;lt;name&amp;gt; msgDialog {JSON}&lt;br /&gt;
&lt;br /&gt;
, or ] expected while parsing array, at character offset 73 (before &amp;quot;}\n}&amp;quot;) at ./FHEM/76_msgDialog.pm line 93.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Eine gute Anlaufstelle zur Überprüfung von JSON-Code ist hier: https://jsonlint.com/&lt;br /&gt;
 &lt;br /&gt;
=== Es werden keine Dialoge angezeigt ===&lt;br /&gt;
Ohne die Angabe einer normalen Nachricht wird bei Keyboards kein Dialog angezeigt: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Erst mit der Nachricht &amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot; erscheint der Dialog:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
&amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot;&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Innerhalb eines Dialogs fehlen einzelne Menüeinträge ===&lt;br /&gt;
Das liegt das meistens an einem fehlenden Leerzeichen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten)&amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Bei &amp;quot;Lampen ausschalten&amp;quot; ist dagegen korrekt ein Leerzeichen zu sehen und somit auch der Menüeintrag im Dialog.&lt;br /&gt;
&lt;br /&gt;
=== &amp;quot;:&amp;quot; bei Inline Keyboards ===&lt;br /&gt;
Bei Inline Keyboards wird der letzte : als Trennzeichen zwischen Nachricht und Befehl ausgewertet.&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;(Temperatur: [heizung:desiredTemperature]°C:setheiz) &amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
oder  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;([test:state]:weiter) &amp;quot; wenn [test:state] = &amp;quot;Status: ok&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&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 ==&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;
== JABBER ==&lt;br /&gt;
Hier wird die Verwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Verwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23448</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23448"/>
		<updated>2017-12-03T17:31:32Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: &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=h&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
== Konfiguration ==&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;
=== Hinweis zu den Code Beispielen ===&lt;br /&gt;
Es handelt sich bei den Beispielen um eine Raw definition, siehe auch [[Import_von_Code_Snippets]]&lt;br /&gt;
&lt;br /&gt;
=== msgConfig ===&lt;br /&gt;
&lt;br /&gt;
Als erstes 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 userattr msgDialog_evalSpecials:textField-long msgDialog_msgCommand:textField&lt;br /&gt;
attr myMsgConfig msgContactPush &amp;lt;Name des TelegramBot-device&amp;gt;&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;
&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;
;msgDialog_evalSpecials&lt;br /&gt;
: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. Wenn der selbe Name im msgConfig und msgDialog definiert wurde, wird der Wert aus msgDialog verwendet.&lt;br /&gt;
&lt;br /&gt;
;msgDialog_msgCommand &amp;lt;command&amp;gt;&lt;br /&gt;
:Befehl zum Versenden einer Nachricht. Die Vorgabe ist &amp;quot;msg push \@$recipients $message&amp;quot;. Wenn nicht gesetzt, wird die Vorgabe verwendet.&lt;br /&gt;
&lt;br /&gt;
=== ROOMMATE / GUEST ===&lt;br /&gt;
Für jeden Dialog kann festgelegt werden welche Person 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 fhemMsgRcvPush ein Event erzeugt. Siehe auch Attribut &amp;quot;allowed&amp;quot; in msgDialog.&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;: &amp;quot;deletereading TYPE=msgDialog $recipient_history&amp;quot;,\&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;abbrechen&#039;) . &#039;) &#039;)}&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;zurück&amp;quot;: {\&lt;br /&gt;
    &amp;quot;commands&amp;quot;: &amp;quot;set $recipient_history=.+|.+ say @$recipient {(ReadingsVal($DEV, &#039;$recipient_history&#039;, &#039;&#039;) =~ m/(.+)\\|.+$/;; return $2 ? $2 : $1;;)}&amp;quot;\&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;: &amp;quot;deletereading TYPE=msgDialog $recipient_history&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;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;: &amp;quot;deletereading TYPE=msgDialog $recipient_history&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;Dialog beendet.&amp;quot;\&lt;br /&gt;
    ]\&lt;br /&gt;
  }\&lt;br /&gt;
}&lt;br /&gt;
attr meta_Dialog allowed everyone&lt;br /&gt;
&amp;lt;/pre&amp;gt;&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 &#039;&#039;&#039;DEF&#039;&#039;&#039; 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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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&lt;br /&gt;
:Kann einen einzelnen oder mehrere Befehle enthalten: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;commands&amp;quot;: &amp;quot;single command&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&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 &lt;br /&gt;
: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;: [&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;
&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;
=== 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;
=== 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;
=== 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;
== Hilfe bei der Fehlersuche ==&lt;br /&gt;
Hier entsteht eine Sammlung von Tipps bei der Fehlersuche. Die meisten dieser &amp;quot;Stolpersteine&amp;quot;&lt;br /&gt;
entstehen häufig bei der Erstellung eines ersten eigenen Dialoges.&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut allowed fehlt oder ist nicht korrekt gesetzt ===&lt;br /&gt;
Das allowed-Attribut dient dazu, einzelne Dialoge für alle  oder nur bestimmte Benutzer zu berechtigen.&lt;br /&gt;
Fehlt es, wird der Dialog dem aufrufenden Benutzer nicht angezeigt.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr Testdialog allowed everyone&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut msgDialog_evalSpecials fehlt oder ist nicht korrekt gesetzt ===&lt;br /&gt;
Dieses Attribut gehört dem msgConfig device und muss wie in 2.3 zu lesen&lt;br /&gt;
korrekt befüllt werden.&lt;br /&gt;
&amp;lt;pre&amp;gt;&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut utf8Special fehlt beim TelegramBot device ===&lt;br /&gt;
Dieses Attribut ist für die korrekte UTF-8 Kodierung zuständig und im Standard deaktiviert.&lt;br /&gt;
Der Satz &amp;quot;Was kann ich für dich tun?&amp;quot; aus dem Meta-Dialog enthält bereits einen Umlaut!&lt;br /&gt;
&lt;br /&gt;
=== JSON-Syntax Fehler ===&lt;br /&gt;
Das Modul prüft vor dem Abspeichern auf eine korrekte JSON-Syntax.&lt;br /&gt;
Meistens wird auch eine sprechende Meldung angezeigt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Usage: define &amp;lt;name&amp;gt; msgDialog {JSON}&lt;br /&gt;
&lt;br /&gt;
, or ] expected while parsing array, at character offset 73 (before &amp;quot;}\n}&amp;quot;) at ./FHEM/76_msgDialog.pm line 93.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Eine gute Anlaufstelle zur Überprüfung von JSON-Code ist hier: https://jsonlint.com/&lt;br /&gt;
 &lt;br /&gt;
=== Es werden keine Dialoge angezeigt ===&lt;br /&gt;
Ohne die Angabe einer normalen Nachricht wird bei Keyboards kein Dialog angezeigt: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Erst mit der Nachricht &amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot; erscheint der Dialog:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
&amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot;&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Innerhalb eines Dialogs fehlen einzelne Menüeinträge ===&lt;br /&gt;
Das liegt das meistens an einem fehlenden Leerzeichen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten)&amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Bei &amp;quot;Lampen ausschalten&amp;quot; ist dagegen korrekt ein Leerzeichen zu sehen und somit auch der Menüeintrag im Dialog.&lt;br /&gt;
&lt;br /&gt;
=== &amp;quot;:&amp;quot; bei Inline Keyboards ===&lt;br /&gt;
Bei Inline Keyboards wird der letzte : als Trennzeichen zwischen Nachricht und Befehl ausgewertet.&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;(Temperatur: [heizung:desiredTemperature]°C:setheiz) &amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
oder  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;([test:state]:weiter) &amp;quot; wenn [test:state] = &amp;quot;Status: ok&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&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 ==&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;
== JABBER ==&lt;br /&gt;
Hier wird die Verwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Verwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23447</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23447"/>
		<updated>2017-12-03T17:17:13Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* Hilfe bei der Fehlersuche */&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=h&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
== Konfiguration ==&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;
=== Hinweis zu den Code Beispielen ===&lt;br /&gt;
Es handelt sich bei den Beispielen um eine Raw definition, siehe auch [[Import_von_Code_Snippets]]&lt;br /&gt;
&lt;br /&gt;
=== msgConfig ===&lt;br /&gt;
&lt;br /&gt;
Als erstes 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 userattr msgDialog_evalSpecials:textField-long msgDialog_msgCommand:textField&lt;br /&gt;
attr myMsgConfig msgContactPush &amp;lt;Name des TelegramBot-device&amp;gt;&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;
&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;
;msgDialog_evalSpecials&lt;br /&gt;
: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. Wenn der selbe Name im msgConfig und msgDialog definiert wurde, wird der Wert aus msgDialog verwendet.&lt;br /&gt;
&lt;br /&gt;
;msgDialog_msgCommand &amp;lt;command&amp;gt;&lt;br /&gt;
:Befehl zum Versenden einer Nachricht. Die Vorgabe ist &amp;quot;msg push \@$recipients $message&amp;quot;. Wenn nicht gesetzt, wird die Vorgabe verwendet.&lt;br /&gt;
&lt;br /&gt;
=== ROOMMATE / GUEST ===&lt;br /&gt;
Für jeden Dialog kann festgelegt werden welche Person 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 fhemMsgRcvPush ein Event erzeugt. Siehe auch Attribut &amp;quot;allowed&amp;quot; in msgDialog.&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;abbrechen&#039;) . &#039;) &#039;)}&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;zurück&amp;quot;: {\&lt;br /&gt;
    &amp;quot;commands&amp;quot;: &amp;quot;set $recipient_history=.+ say @$recipient {(ReadingsVal($DEV, &#039;$recipient_history&#039;, &#039;&#039;) =~ m/(.+)\\|.+$/;;;; return($2 ? $2 : $1;;;;)}&amp;quot;\&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;TelegramBot_MTYPE=queryInline (%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;TelegramBot_MTYPE=queryInline (%me%) &amp;quot;,\&lt;br /&gt;
      &amp;quot;Dialog beendet.&amp;quot;\&lt;br /&gt;
    ]\&lt;br /&gt;
  }\&lt;br /&gt;
}&lt;br /&gt;
attr meta_Dialog allowed everyone&lt;br /&gt;
&amp;lt;/pre&amp;gt;&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 &#039;&#039;&#039;DEF&#039;&#039;&#039; 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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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&lt;br /&gt;
:Kann einen einzelnen oder mehrere Befehle enthalten: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;commands&amp;quot;: &amp;quot;single command&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&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 &lt;br /&gt;
: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;: [&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;
&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;
=== 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;
=== 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;
=== 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;
== Hilfe bei der Fehlersuche ==&lt;br /&gt;
Hier entsteht eine Sammlung von Tipps bei der Fehlersuche. Die meisten dieser &amp;quot;Stolpersteine&amp;quot;&lt;br /&gt;
entstehen häufig bei der Erstellung eines ersten eigenen Dialoges.&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut allowed fehlt oder ist nicht korrekt gesetzt ===&lt;br /&gt;
Das allowed-Attribut dient dazu, einzelne Dialoge für alle  oder nur bestimmte Benutzer zu berechtigen.&lt;br /&gt;
Fehlt es, wird der Dialog dem aufrufenden Benutzer nicht angezeigt.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr Testdialog allowed everyone&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut msgDialog_evalSpecials fehlt oder ist nicht korrekt gesetzt ===&lt;br /&gt;
Dieses Attribut gehört dem msgConfig device und muss wie in 2.3 zu lesen&lt;br /&gt;
korrekt befüllt werden.&lt;br /&gt;
&amp;lt;pre&amp;gt;&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut utf8Special fehlt beim TelegramBot device ===&lt;br /&gt;
Dieses Attribut ist für die korrekte UTF-8 Kodierung zuständig und im Standard deaktiviert.&lt;br /&gt;
Der Satz &amp;quot;Was kann ich für dich tun?&amp;quot; aus dem Meta-Dialog enthält bereits einen Umlaut!&lt;br /&gt;
&lt;br /&gt;
=== JSON-Syntax Fehler ===&lt;br /&gt;
Das Modul prüft vor dem Abspeichern auf eine korrekte JSON-Syntax.&lt;br /&gt;
Meistens wird auch eine sprechende Meldung angezeigt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Usage: define &amp;lt;name&amp;gt; msgDialog {JSON}&lt;br /&gt;
&lt;br /&gt;
, or ] expected while parsing array, at character offset 73 (before &amp;quot;}\n}&amp;quot;) at ./FHEM/76_msgDialog.pm line 93.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Eine gute Anlaufstelle zur Überprüfung von JSON-Code ist hier: https://jsonlint.com/&lt;br /&gt;
 &lt;br /&gt;
=== Es werden keine Dialoge angezeigt ===&lt;br /&gt;
Ohne die Angabe einer normalen Nachricht wird bei Keyboards kein Dialog angezeigt: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Erst mit der Nachricht &amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot; erscheint der Dialog:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
&amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot;&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Innerhalb eines Dialogs fehlen einzelne Menüeinträge ===&lt;br /&gt;
Das liegt das meistens an einem fehlenden Leerzeichen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten)&amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Bei &amp;quot;Lampen ausschalten&amp;quot; ist dagegen korrekt ein Leerzeichen zu sehen und somit auch der Menüeintrag im Dialog.&lt;br /&gt;
&lt;br /&gt;
=== &amp;quot;:&amp;quot; bei Inline Keyboards ===&lt;br /&gt;
Bei Inline Keyboards wird der letzte : als Trennzeichen zwischen Nachricht und Befehl ausgewertet.&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;(Temperatur: [heizung:desiredTemperature]°C:setheiz) &amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
oder  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;([test:state]:weiter) &amp;quot; wenn [test:state] = &amp;quot;Status: ok&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&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 ==&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;
== JABBER ==&lt;br /&gt;
Hier wird die Verwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Verwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23446</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23446"/>
		<updated>2017-12-03T17:16:41Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* Hilfe bei der Fehlersuche */&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=h&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
== Konfiguration ==&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;
=== Hinweis zu den Code Beispielen ===&lt;br /&gt;
Es handelt sich bei den Beispielen um eine Raw definition, siehe auch [[Import_von_Code_Snippets]]&lt;br /&gt;
&lt;br /&gt;
=== msgConfig ===&lt;br /&gt;
&lt;br /&gt;
Als erstes 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 userattr msgDialog_evalSpecials:textField-long msgDialog_msgCommand:textField&lt;br /&gt;
attr myMsgConfig msgContactPush &amp;lt;Name des TelegramBot-device&amp;gt;&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;
&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;
;msgDialog_evalSpecials&lt;br /&gt;
: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. Wenn der selbe Name im msgConfig und msgDialog definiert wurde, wird der Wert aus msgDialog verwendet.&lt;br /&gt;
&lt;br /&gt;
;msgDialog_msgCommand &amp;lt;command&amp;gt;&lt;br /&gt;
:Befehl zum Versenden einer Nachricht. Die Vorgabe ist &amp;quot;msg push \@$recipients $message&amp;quot;. Wenn nicht gesetzt, wird die Vorgabe verwendet.&lt;br /&gt;
&lt;br /&gt;
=== ROOMMATE / GUEST ===&lt;br /&gt;
Für jeden Dialog kann festgelegt werden welche Person 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 fhemMsgRcvPush ein Event erzeugt. Siehe auch Attribut &amp;quot;allowed&amp;quot; in msgDialog.&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;abbrechen&#039;) . &#039;) &#039;)}&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;zurück&amp;quot;: {\&lt;br /&gt;
    &amp;quot;commands&amp;quot;: &amp;quot;set $recipient_history=.+ say @$recipient {(ReadingsVal($DEV, &#039;$recipient_history&#039;, &#039;&#039;) =~ m/(.+)\\|.+$/;;;; return($2 ? $2 : $1;;;;)}&amp;quot;\&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;TelegramBot_MTYPE=queryInline (%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;TelegramBot_MTYPE=queryInline (%me%) &amp;quot;,\&lt;br /&gt;
      &amp;quot;Dialog beendet.&amp;quot;\&lt;br /&gt;
    ]\&lt;br /&gt;
  }\&lt;br /&gt;
}&lt;br /&gt;
attr meta_Dialog allowed everyone&lt;br /&gt;
&amp;lt;/pre&amp;gt;&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 &#039;&#039;&#039;DEF&#039;&#039;&#039; 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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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&lt;br /&gt;
:Kann einen einzelnen oder mehrere Befehle enthalten: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;commands&amp;quot;: &amp;quot;single command&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&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 &lt;br /&gt;
: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;: [&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;
&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;
=== 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;
=== 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;
=== 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;
== Hilfe bei der Fehlersuche ==&lt;br /&gt;
Hier entsteht eine Sammlung von Tipps bei der Fehlersuche. Die meisten dieser &amp;quot;Stolpersteine&amp;quot;&lt;br /&gt;
entstehen häufig bei der Erstellung eines ersten eigenen Dialoges.&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut allowed fehlt oder ist nicht korrekt gesetzt ===&lt;br /&gt;
Das allowed-Attribut dient dazu, einzelne Dialoge für alle  oder nur bestimmte Benutzer zu berechtigen.&lt;br /&gt;
Fehlt es, wird der Dialog dem aufrufenden Benutzer nicht angezeigt.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr Testdialog allowed everyone&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut msgDialog_evalSpecials fehlt oder ist nicht korrekt gesetzt ===&lt;br /&gt;
Dieses Attribut gehört dem msgConfig device und muss wie in 2.3 zu lesen&lt;br /&gt;
korrekt befüllt werden.&lt;br /&gt;
&amp;lt;pre&amp;gt;&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut utf8Special fehlt beim TelegramBot device&lt;br /&gt;
Dieses Attribut ist für die korrekte UTF-8 Kodierung zuständig und im Standard deaktiviert.&lt;br /&gt;
Der Satz &amp;quot;Was kann ich für dich tun?&amp;quot; aus dem Meta-Dialog enthält bereits einen Umlaut!&lt;br /&gt;
&lt;br /&gt;
=== JSON-Syntax Fehler ===&lt;br /&gt;
Das Modul prüft vor dem Abspeichern auf eine korrekte JSON-Syntax.&lt;br /&gt;
Meistens wird auch eine sprechende Meldung angezeigt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Usage: define &amp;lt;name&amp;gt; msgDialog {JSON}&lt;br /&gt;
&lt;br /&gt;
, or ] expected while parsing array, at character offset 73 (before &amp;quot;}\n}&amp;quot;) at ./FHEM/76_msgDialog.pm line 93.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Eine gute Anlaufstelle zur Überprüfung von JSON-Code ist hier: https://jsonlint.com/&lt;br /&gt;
 &lt;br /&gt;
=== Es werden keine Dialoge angezeigt ===&lt;br /&gt;
Ohne die Angabe einer normalen Nachricht wird bei Keyboards kein Dialog angezeigt: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Erst mit der Nachricht &amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot; erscheint der Dialog:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
&amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot;&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Innerhalb eines Dialogs fehlen einzelne Menüeinträge ===&lt;br /&gt;
Das liegt das meistens an einem fehlenden Leerzeichen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten)&amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Bei &amp;quot;Lampen ausschalten&amp;quot; ist dagegen korrekt ein Leerzeichen zu sehen und somit auch der Menüeintrag im Dialog.&lt;br /&gt;
&lt;br /&gt;
=== &amp;quot;:&amp;quot; bei Inline Keyboards ===&lt;br /&gt;
Bei Inline Keyboards wird der letzte : als Trennzeichen zwischen Nachricht und Befehl ausgewertet.&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;(Temperatur: [heizung:desiredTemperature]°C:setheiz) &amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
oder  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;([test:state]:weiter) &amp;quot; wenn [test:state] = &amp;quot;Status: ok&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&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 ==&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;
== JABBER ==&lt;br /&gt;
Hier wird die Verwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Verwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23445</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23445"/>
		<updated>2017-12-03T17:16:25Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* Das Attribut msgDialog_evalSpecials fehlt oder ist nicht korrekt gesetzt */&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=h&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
== Konfiguration ==&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;
=== Hinweis zu den Code Beispielen ===&lt;br /&gt;
Es handelt sich bei den Beispielen um eine Raw definition, siehe auch [[Import_von_Code_Snippets]]&lt;br /&gt;
&lt;br /&gt;
=== msgConfig ===&lt;br /&gt;
&lt;br /&gt;
Als erstes 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 userattr msgDialog_evalSpecials:textField-long msgDialog_msgCommand:textField&lt;br /&gt;
attr myMsgConfig msgContactPush &amp;lt;Name des TelegramBot-device&amp;gt;&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;
&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;
;msgDialog_evalSpecials&lt;br /&gt;
: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. Wenn der selbe Name im msgConfig und msgDialog definiert wurde, wird der Wert aus msgDialog verwendet.&lt;br /&gt;
&lt;br /&gt;
;msgDialog_msgCommand &amp;lt;command&amp;gt;&lt;br /&gt;
:Befehl zum Versenden einer Nachricht. Die Vorgabe ist &amp;quot;msg push \@$recipients $message&amp;quot;. Wenn nicht gesetzt, wird die Vorgabe verwendet.&lt;br /&gt;
&lt;br /&gt;
=== ROOMMATE / GUEST ===&lt;br /&gt;
Für jeden Dialog kann festgelegt werden welche Person 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 fhemMsgRcvPush ein Event erzeugt. Siehe auch Attribut &amp;quot;allowed&amp;quot; in msgDialog.&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;abbrechen&#039;) . &#039;) &#039;)}&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;zurück&amp;quot;: {\&lt;br /&gt;
    &amp;quot;commands&amp;quot;: &amp;quot;set $recipient_history=.+ say @$recipient {(ReadingsVal($DEV, &#039;$recipient_history&#039;, &#039;&#039;) =~ m/(.+)\\|.+$/;;;; return($2 ? $2 : $1;;;;)}&amp;quot;\&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;TelegramBot_MTYPE=queryInline (%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;TelegramBot_MTYPE=queryInline (%me%) &amp;quot;,\&lt;br /&gt;
      &amp;quot;Dialog beendet.&amp;quot;\&lt;br /&gt;
    ]\&lt;br /&gt;
  }\&lt;br /&gt;
}&lt;br /&gt;
attr meta_Dialog allowed everyone&lt;br /&gt;
&amp;lt;/pre&amp;gt;&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 &#039;&#039;&#039;DEF&#039;&#039;&#039; 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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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&lt;br /&gt;
:Kann einen einzelnen oder mehrere Befehle enthalten: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;commands&amp;quot;: &amp;quot;single command&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&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 &lt;br /&gt;
: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;: [&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;
&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;
=== 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;
=== 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;
=== 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;
== Hilfe bei der Fehlersuche ==&lt;br /&gt;
Hier entsteht eine Sammlung von Tipps bei der Fehlersuche. Die meisten dieser &amp;quot;Stolpersteine&amp;quot;&lt;br /&gt;
entstehen häufig bei der Erstellung eines ersten eigenen Dialoges.&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut allowed fehlt oder ist nicht korrekt gesetzt ===&lt;br /&gt;
Das allowed-Attribut dient dazu, einzelne Dialoge für alle  oder nur bestimmte Benutzer zu berechtigen.&lt;br /&gt;
Fehlt es, wird der Dialog dem aufrufenden Benutzer nicht angezeigt.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr Testdialog allowed everyone&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut msgDialog_evalSpecials fehlt oder ist nicht korrekt gesetzt ===&lt;br /&gt;
Dieses Attribut gehört dem msgConfig device und muss wie in 2.3 zu lesen&lt;br /&gt;
korrekt befüllt werden.&lt;br /&gt;
&amp;lt;pre&amp;gt;&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== JSON-Syntax Fehler ===&lt;br /&gt;
Das Modul prüft vor dem Abspeichern auf eine korrekte JSON-Syntax.&lt;br /&gt;
Meistens wird auch eine sprechende Meldung angezeigt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Usage: define &amp;lt;name&amp;gt; msgDialog {JSON}&lt;br /&gt;
&lt;br /&gt;
, or ] expected while parsing array, at character offset 73 (before &amp;quot;}\n}&amp;quot;) at ./FHEM/76_msgDialog.pm line 93.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Eine gute Anlaufstelle zur Überprüfung von JSON-Code ist hier: https://jsonlint.com/&lt;br /&gt;
 &lt;br /&gt;
=== Es werden keine Dialoge angezeigt ===&lt;br /&gt;
Ohne die Angabe einer normalen Nachricht wird bei Keyboards kein Dialog angezeigt: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Erst mit der Nachricht &amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot; erscheint der Dialog:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
&amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot;&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Innerhalb eines Dialogs fehlen einzelne Menüeinträge ===&lt;br /&gt;
Das liegt das meistens an einem fehlenden Leerzeichen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten)&amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Bei &amp;quot;Lampen ausschalten&amp;quot; ist dagegen korrekt ein Leerzeichen zu sehen und somit auch der Menüeintrag im Dialog.&lt;br /&gt;
&lt;br /&gt;
=== &amp;quot;:&amp;quot; bei Inline Keyboards ===&lt;br /&gt;
Bei Inline Keyboards wird der letzte : als Trennzeichen zwischen Nachricht und Befehl ausgewertet.&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;(Temperatur: [heizung:desiredTemperature]°C:setheiz) &amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
oder  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;([test:state]:weiter) &amp;quot; wenn [test:state] = &amp;quot;Status: ok&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&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 ==&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;
== JABBER ==&lt;br /&gt;
Hier wird die Verwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Verwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23444</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23444"/>
		<updated>2017-12-03T17:15:31Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* Hilfe bei der Fehlersuche */&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=h&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
== Konfiguration ==&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;
=== Hinweis zu den Code Beispielen ===&lt;br /&gt;
Es handelt sich bei den Beispielen um eine Raw definition, siehe auch [[Import_von_Code_Snippets]]&lt;br /&gt;
&lt;br /&gt;
=== msgConfig ===&lt;br /&gt;
&lt;br /&gt;
Als erstes 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 userattr msgDialog_evalSpecials:textField-long msgDialog_msgCommand:textField&lt;br /&gt;
attr myMsgConfig msgContactPush &amp;lt;Name des TelegramBot-device&amp;gt;&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;
&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;
;msgDialog_evalSpecials&lt;br /&gt;
: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. Wenn der selbe Name im msgConfig und msgDialog definiert wurde, wird der Wert aus msgDialog verwendet.&lt;br /&gt;
&lt;br /&gt;
;msgDialog_msgCommand &amp;lt;command&amp;gt;&lt;br /&gt;
:Befehl zum Versenden einer Nachricht. Die Vorgabe ist &amp;quot;msg push \@$recipients $message&amp;quot;. Wenn nicht gesetzt, wird die Vorgabe verwendet.&lt;br /&gt;
&lt;br /&gt;
=== ROOMMATE / GUEST ===&lt;br /&gt;
Für jeden Dialog kann festgelegt werden welche Person 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 fhemMsgRcvPush ein Event erzeugt. Siehe auch Attribut &amp;quot;allowed&amp;quot; in msgDialog.&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;abbrechen&#039;) . &#039;) &#039;)}&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;zurück&amp;quot;: {\&lt;br /&gt;
    &amp;quot;commands&amp;quot;: &amp;quot;set $recipient_history=.+ say @$recipient {(ReadingsVal($DEV, &#039;$recipient_history&#039;, &#039;&#039;) =~ m/(.+)\\|.+$/;;;; return($2 ? $2 : $1;;;;)}&amp;quot;\&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;TelegramBot_MTYPE=queryInline (%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;TelegramBot_MTYPE=queryInline (%me%) &amp;quot;,\&lt;br /&gt;
      &amp;quot;Dialog beendet.&amp;quot;\&lt;br /&gt;
    ]\&lt;br /&gt;
  }\&lt;br /&gt;
}&lt;br /&gt;
attr meta_Dialog allowed everyone&lt;br /&gt;
&amp;lt;/pre&amp;gt;&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 &#039;&#039;&#039;DEF&#039;&#039;&#039; 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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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&lt;br /&gt;
:Kann einen einzelnen oder mehrere Befehle enthalten: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;commands&amp;quot;: &amp;quot;single command&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&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 &lt;br /&gt;
: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;: [&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;
&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;
=== 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;
=== 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;
=== 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;
== Hilfe bei der Fehlersuche ==&lt;br /&gt;
Hier entsteht eine Sammlung von Tipps bei der Fehlersuche. Die meisten dieser &amp;quot;Stolpersteine&amp;quot;&lt;br /&gt;
entstehen häufig bei der Erstellung eines ersten eigenen Dialoges.&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut allowed fehlt oder ist nicht korrekt gesetzt ===&lt;br /&gt;
Das allowed-Attribut dient dazu, einzelne Dialoge für alle  oder nur bestimmte Benutzer zu berechtigen.&lt;br /&gt;
Fehlt es, wird der Dialog dem aufrufenden Benutzer nicht angezeigt.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr Testdialog allowed everyone&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut msgDialog_evalSpecials fehlt oder ist nicht korrekt gesetzt ===&lt;br /&gt;
Dieses Attribut gehört dem msgConfig device und muss wie in 2.3 zu lesen&lt;br /&gt;
korrekt befüllt werden.&lt;br /&gt;
&amp;lt;pre&amp;gt;&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut utf8Special fehlt beim TelegramBot device&lt;br /&gt;
Dieses Attribut ist für die korrekte UTF-8 Kodierung zuständig und im Standard deaktiviert.&lt;br /&gt;
Der Satz &amp;quot;Was kann ich für dich tun?&amp;quot; aus dem Meta-Dialog enthält bereits einen Umlaut! &lt;br /&gt;
&lt;br /&gt;
=== JSON-Syntax Fehler ===&lt;br /&gt;
Das Modul prüft vor dem Abspeichern auf eine korrekte JSON-Syntax.&lt;br /&gt;
Meistens wird auch eine sprechende Meldung angezeigt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Usage: define &amp;lt;name&amp;gt; msgDialog {JSON}&lt;br /&gt;
&lt;br /&gt;
, or ] expected while parsing array, at character offset 73 (before &amp;quot;}\n}&amp;quot;) at ./FHEM/76_msgDialog.pm line 93.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Eine gute Anlaufstelle zur Überprüfung von JSON-Code ist hier: https://jsonlint.com/&lt;br /&gt;
 &lt;br /&gt;
=== Es werden keine Dialoge angezeigt ===&lt;br /&gt;
Ohne die Angabe einer normalen Nachricht wird bei Keyboards kein Dialog angezeigt: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Erst mit der Nachricht &amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot; erscheint der Dialog:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
&amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot;&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Innerhalb eines Dialogs fehlen einzelne Menüeinträge ===&lt;br /&gt;
Das liegt das meistens an einem fehlenden Leerzeichen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten)&amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Bei &amp;quot;Lampen ausschalten&amp;quot; ist dagegen korrekt ein Leerzeichen zu sehen und somit auch der Menüeintrag im Dialog.&lt;br /&gt;
&lt;br /&gt;
=== &amp;quot;:&amp;quot; bei Inline Keyboards ===&lt;br /&gt;
Bei Inline Keyboards wird der letzte : als Trennzeichen zwischen Nachricht und Befehl ausgewertet.&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;(Temperatur: [heizung:desiredTemperature]°C:setheiz) &amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
oder  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;([test:state]:weiter) &amp;quot; wenn [test:state] = &amp;quot;Status: ok&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&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 ==&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;
== JABBER ==&lt;br /&gt;
Hier wird die Verwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Verwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23255</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23255"/>
		<updated>2017-11-12T08:02:33Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* &amp;quot;:&amp;quot; bei Inline Keyboards */&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=h&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
== Konfiguration ==&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;
=== Hinweis zu den Code Beispielen ===&lt;br /&gt;
Es handelt sich bei den Beispielen um eine Raw definition, siehe auch [[Import_von_Code_Snippets]]&lt;br /&gt;
&lt;br /&gt;
=== msgConfig ===&lt;br /&gt;
&lt;br /&gt;
Als erstes 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 userattr msgDialog_evalSpecials:textField-long msgDialog_msgCommand:textField&lt;br /&gt;
attr myMsgConfig msgContactPush &amp;lt;Name des TelegramBot-device&amp;gt;&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;
&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;
;msgDialog_evalSpecials&lt;br /&gt;
: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. Wenn der selbe Name im msgConfig und msgDialog definiert wurde, wird der Wert aus msgDialog verwendet.&lt;br /&gt;
&lt;br /&gt;
;msgDialog_msgCommand &amp;lt;command&amp;gt;&lt;br /&gt;
:Befehl zum Versenden einer Nachricht. Die Vorgabe ist &amp;quot;msg push \@$recipients $message&amp;quot;. Wenn nicht gesetzt, wird die Vorgabe verwendet.&lt;br /&gt;
&lt;br /&gt;
=== ROOMMATE / GUEST ===&lt;br /&gt;
Für jeden Dialog kann festgelegt werden welche Person 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 fhemMsgRcvPush ein Event erzeugt. Siehe auch Attribut &amp;quot;allowed&amp;quot; in msgDialog.&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;abbrechen&#039;) . &#039;) &#039;)}&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;zurück&amp;quot;: {\&lt;br /&gt;
    &amp;quot;commands&amp;quot;: &amp;quot;set $recipient_history=.+ say @$recipient {(ReadingsVal($DEV, &#039;$recipient_history&#039;, &#039;&#039;) =~ m/(.+)\\|.+$/;;;; return($2 ? $2 : $1;;;;)}&amp;quot;\&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;TelegramBot_MTYPE=queryInline (%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;TelegramBot_MTYPE=queryInline (%me%) &amp;quot;,\&lt;br /&gt;
      &amp;quot;Dialog beendet.&amp;quot;\&lt;br /&gt;
    ]\&lt;br /&gt;
  }\&lt;br /&gt;
}&lt;br /&gt;
attr meta_Dialog allowed everyone&lt;br /&gt;
&amp;lt;/pre&amp;gt;&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 &#039;&#039;&#039;DEF&#039;&#039;&#039; 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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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&lt;br /&gt;
:Kann einen einzelnen oder mehrere Befehle enthalten: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;commands&amp;quot;: &amp;quot;single command&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&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 &lt;br /&gt;
: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;: [&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;
&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;
=== 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;
=== 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;
=== 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;
== Hilfe bei der Fehlersuche ==&lt;br /&gt;
Hier entsteht eine Sammlung von Tipps bei der Fehlersuche. Die meisten dieser &amp;quot;Stolpersteine&amp;quot;&lt;br /&gt;
entstehen häufig bei der Erstellung eines ersten eigenen Dialoges.&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut allowed fehlt oder ist nicht korrekt gesetzt ===&lt;br /&gt;
Das allowed-Attribut dient dazu, einzelne Dialoge für alle  oder nur bestimmte Benutzer zu berechtigen.&lt;br /&gt;
Fehlt es, wird der Dialog dem aufrufenden Benutzer nicht angezeigt.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr Testdialog allowed everyone&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut msgDialog_evalSpecials fehlt oder ist nicht korrekt gesetzt ===&lt;br /&gt;
Dieses Attribut gehört dem msgConfig device und muss wie in 2.3 zu lesen&lt;br /&gt;
korrekt befüllt werden.&lt;br /&gt;
&amp;lt;pre&amp;gt;&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== JSON-Syntax Fehler ===&lt;br /&gt;
Das Modul prüft vor dem Abspeichern auf eine korrekte JSON-Syntax.&lt;br /&gt;
Meistens wird auch eine sprechende Meldung angezeigt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Usage: define &amp;lt;name&amp;gt; msgDialog {JSON}&lt;br /&gt;
&lt;br /&gt;
, or ] expected while parsing array, at character offset 73 (before &amp;quot;}\n}&amp;quot;) at ./FHEM/76_msgDialog.pm line 93.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Eine gute Anlaufstelle zur Überprüfung von JSON-Code ist hier: https://jsonlint.com/&lt;br /&gt;
 &lt;br /&gt;
=== Es werden keine Dialoge angezeigt ===&lt;br /&gt;
Ohne die Angabe einer normalen Nachricht wird bei Keyboards kein Dialog angezeigt: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Erst mit der Nachricht &amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot; erscheint der Dialog:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
&amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot;&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Innerhalb eines Dialogs fehlen einzelne Menüeinträge ===&lt;br /&gt;
Das liegt das meistens an einem fehlenden Leerzeichen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten)&amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Bei &amp;quot;Lampen ausschalten&amp;quot; ist dagegen korrekt ein Leerzeichen zu sehen und somit auch der Menüeintrag im Dialog.&lt;br /&gt;
&lt;br /&gt;
=== &amp;quot;:&amp;quot; bei Inline Keyboards ===&lt;br /&gt;
Bei Inline Keyboards wird der letzte : als Trennzeichen zwischen Nachricht und Befehl ausgewertet.&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;(Temperatur: [heizung:desiredTemperature]°C:setheiz) &amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
oder  &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;([test:state]:weiter) &amp;quot; wenn [test:state] = &amp;quot;Status: ok&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&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 ==&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;
== JABBER ==&lt;br /&gt;
Hier wird die Verwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Verwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23254</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23254"/>
		<updated>2017-11-12T07:58:35Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* Hilfe bei der Fehlersuche */&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=h&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
== Konfiguration ==&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;
=== Hinweis zu den Code Beispielen ===&lt;br /&gt;
Es handelt sich bei den Beispielen um eine Raw definition, siehe auch [[Import_von_Code_Snippets]]&lt;br /&gt;
&lt;br /&gt;
=== msgConfig ===&lt;br /&gt;
&lt;br /&gt;
Als erstes 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 userattr msgDialog_evalSpecials:textField-long msgDialog_msgCommand:textField&lt;br /&gt;
attr myMsgConfig msgContactPush &amp;lt;Name des TelegramBot-device&amp;gt;&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;
&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;
;msgDialog_evalSpecials&lt;br /&gt;
: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. Wenn der selbe Name im msgConfig und msgDialog definiert wurde, wird der Wert aus msgDialog verwendet.&lt;br /&gt;
&lt;br /&gt;
;msgDialog_msgCommand &amp;lt;command&amp;gt;&lt;br /&gt;
:Befehl zum Versenden einer Nachricht. Die Vorgabe ist &amp;quot;msg push \@$recipients $message&amp;quot;. Wenn nicht gesetzt, wird die Vorgabe verwendet.&lt;br /&gt;
&lt;br /&gt;
=== ROOMMATE / GUEST ===&lt;br /&gt;
Für jeden Dialog kann festgelegt werden welche Person 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 fhemMsgRcvPush ein Event erzeugt. Siehe auch Attribut &amp;quot;allowed&amp;quot; in msgDialog.&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;abbrechen&#039;) . &#039;) &#039;)}&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;zurück&amp;quot;: {\&lt;br /&gt;
    &amp;quot;commands&amp;quot;: &amp;quot;set $recipient_history=.+ say @$recipient {(ReadingsVal($DEV, &#039;$recipient_history&#039;, &#039;&#039;) =~ m/(.+)\\|.+$/;;;; return($2 ? $2 : $1;;;;)}&amp;quot;\&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;TelegramBot_MTYPE=queryInline (%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;TelegramBot_MTYPE=queryInline (%me%) &amp;quot;,\&lt;br /&gt;
      &amp;quot;Dialog beendet.&amp;quot;\&lt;br /&gt;
    ]\&lt;br /&gt;
  }\&lt;br /&gt;
}&lt;br /&gt;
attr meta_Dialog allowed everyone&lt;br /&gt;
&amp;lt;/pre&amp;gt;&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 &#039;&#039;&#039;DEF&#039;&#039;&#039; 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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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&lt;br /&gt;
:Kann einen einzelnen oder mehrere Befehle enthalten: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;commands&amp;quot;: &amp;quot;single command&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&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 &lt;br /&gt;
: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;: [&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;
&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;
=== 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;
=== 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;
=== 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;
== Hilfe bei der Fehlersuche ==&lt;br /&gt;
Hier entsteht eine Sammlung von Tipps bei der Fehlersuche. Die meisten dieser &amp;quot;Stolpersteine&amp;quot;&lt;br /&gt;
entstehen häufig bei der Erstellung eines ersten eigenen Dialoges.&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut allowed fehlt oder ist nicht korrekt gesetzt ===&lt;br /&gt;
Das allowed-Attribut dient dazu, einzelne Dialoge für alle  oder nur bestimmte Benutzer zu berechtigen.&lt;br /&gt;
Fehlt es, wird der Dialog dem aufrufenden Benutzer nicht angezeigt.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr Testdialog allowed everyone&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut msgDialog_evalSpecials fehlt oder ist nicht korrekt gesetzt ===&lt;br /&gt;
Dieses Attribut gehört dem msgConfig device und muss wie in 2.3 zu lesen&lt;br /&gt;
korrekt befüllt werden.&lt;br /&gt;
&amp;lt;pre&amp;gt;&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== JSON-Syntax Fehler ===&lt;br /&gt;
Das Modul prüft vor dem Abspeichern auf eine korrekte JSON-Syntax.&lt;br /&gt;
Meistens wird auch eine sprechende Meldung angezeigt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Usage: define &amp;lt;name&amp;gt; msgDialog {JSON}&lt;br /&gt;
&lt;br /&gt;
, or ] expected while parsing array, at character offset 73 (before &amp;quot;}\n}&amp;quot;) at ./FHEM/76_msgDialog.pm line 93.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Eine gute Anlaufstelle zur Überprüfung von JSON-Code ist hier: https://jsonlint.com/&lt;br /&gt;
 &lt;br /&gt;
=== Es werden keine Dialoge angezeigt ===&lt;br /&gt;
Ohne die Angabe einer normalen Nachricht wird bei Keyboards kein Dialog angezeigt: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Erst mit der Nachricht &amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot; erscheint der Dialog:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
&amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot;&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Innerhalb eines Dialogs fehlen einzelne Menüeinträge ===&lt;br /&gt;
Das liegt das meistens an einem fehlenden Leerzeichen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten)&amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Bei &amp;quot;Lampen ausschalten&amp;quot; ist dagegen korrekt ein Leerzeichen zu sehen und somit auch der Menüeintrag im Dialog.&lt;br /&gt;
&lt;br /&gt;
=== &amp;quot;:&amp;quot; bei Inline Keyboards ===&lt;br /&gt;
Bei Inline Keyboards wird der letzte : als Trennzeichen zwischen Nachricht und Befehl ausgewertet.&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;(Temperatur: [heizung:desiredTemperature]°C:setheiz) &amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&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 ==&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;
== JABBER ==&lt;br /&gt;
Hier wird die Verwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Verwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23253</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23253"/>
		<updated>2017-11-12T07:46:58Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* Es werden keine Dialoge angezeigt */&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=h&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
== Konfiguration ==&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;
=== Hinweis zu den Code Beispielen ===&lt;br /&gt;
Es handelt sich bei den Beispielen um eine Raw definition, siehe auch [[Import_von_Code_Snippets]]&lt;br /&gt;
&lt;br /&gt;
=== msgConfig ===&lt;br /&gt;
&lt;br /&gt;
Als erstes 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 userattr msgDialog_evalSpecials:textField-long msgDialog_msgCommand:textField&lt;br /&gt;
attr myMsgConfig msgContactPush &amp;lt;Name des TelegramBot-device&amp;gt;&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;
&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;
;msgDialog_evalSpecials&lt;br /&gt;
: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. Wenn der selbe Name im msgConfig und msgDialog definiert wurde, wird der Wert aus msgDialog verwendet.&lt;br /&gt;
&lt;br /&gt;
;msgDialog_msgCommand &amp;lt;command&amp;gt;&lt;br /&gt;
:Befehl zum Versenden einer Nachricht. Die Vorgabe ist &amp;quot;msg push \@$recipients $message&amp;quot;. Wenn nicht gesetzt, wird die Vorgabe verwendet.&lt;br /&gt;
&lt;br /&gt;
=== ROOMMATE / GUEST ===&lt;br /&gt;
Für jeden Dialog kann festgelegt werden welche Person 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 fhemMsgRcvPush ein Event erzeugt. Siehe auch Attribut &amp;quot;allowed&amp;quot; in msgDialog.&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;abbrechen&#039;) . &#039;) &#039;)}&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;zurück&amp;quot;: {\&lt;br /&gt;
    &amp;quot;commands&amp;quot;: &amp;quot;set $recipient_history=.+ say @$recipient {(ReadingsVal($DEV, &#039;$recipient_history&#039;, &#039;&#039;) =~ m/(.+)\\|.+$/;;;; return($2 ? $2 : $1;;;;)}&amp;quot;\&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;TelegramBot_MTYPE=queryInline (%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;TelegramBot_MTYPE=queryInline (%me%) &amp;quot;,\&lt;br /&gt;
      &amp;quot;Dialog beendet.&amp;quot;\&lt;br /&gt;
    ]\&lt;br /&gt;
  }\&lt;br /&gt;
}&lt;br /&gt;
attr meta_Dialog allowed everyone&lt;br /&gt;
&amp;lt;/pre&amp;gt;&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 &#039;&#039;&#039;DEF&#039;&#039;&#039; 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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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&lt;br /&gt;
:Kann einen einzelnen oder mehrere Befehle enthalten: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;commands&amp;quot;: &amp;quot;single command&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&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 &lt;br /&gt;
: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;: [&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;
&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;
=== 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;
=== 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;
=== 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;
== Hilfe bei der Fehlersuche ==&lt;br /&gt;
Hier entsteht eine Sammlung von Tipps bei der Fehlersuche. Die meisten dieser &amp;quot;Stolpersteine&amp;quot;&lt;br /&gt;
entstehen häufig bei der Erstellung eines ersten eigenen Dialoges.&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut allowed fehlt oder ist nicht korrekt gesetzt ===&lt;br /&gt;
Das allowed-Attribut dient dazu, einzelne Dialoge für alle  oder nur bestimmte Benutzer zu berechtigen.&lt;br /&gt;
Fehlt es, wird der Dialog dem aufrufenden Benutzer nicht angezeigt.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr Testdialog allowed everyone&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut msgDialog_evalSpecials fehlt oder ist nicht korrekt gesetzt ===&lt;br /&gt;
Dieses Attribut gehört dem msgConfig device und muss wie in 2.3 zu lesen&lt;br /&gt;
korrekt befüllt werden.&lt;br /&gt;
&amp;lt;pre&amp;gt;&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== JSON-Syntax Fehler ===&lt;br /&gt;
Das Modul prüft vor dem Abspeichern auf eine korrekte JSON-Syntax.&lt;br /&gt;
Meistens wird auch eine sprechende Meldung angezeigt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Usage: define &amp;lt;name&amp;gt; msgDialog {JSON}&lt;br /&gt;
&lt;br /&gt;
, or ] expected while parsing array, at character offset 73 (before &amp;quot;}\n}&amp;quot;) at ./FHEM/76_msgDialog.pm line 93.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Eine gute Anlaufstelle zur Überprüfung von JSON-Code ist hier: https://jsonlint.com/&lt;br /&gt;
 &lt;br /&gt;
=== Es werden keine Dialoge angezeigt ===&lt;br /&gt;
Ohne die Angabe einer normalen Nachricht wird bei Keyboards kein Dialog angezeigt: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Erst mit der Nachricht &amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot; erscheint der Dialog:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
&amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot;&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Innerhalb eines Dialogs fehlen einzelne Menüeinträge ===&lt;br /&gt;
Das liegt das meistens an einem fehlenden Leerzeichen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten)&amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Bei &amp;quot;Lampen ausschalten&amp;quot; ist dagegen korrekt ein Leerzeichen zu sehen und somit auch der Menüeintrag im Dialog.&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 ==&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;
== JABBER ==&lt;br /&gt;
Hier wird die Verwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Verwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23252</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23252"/>
		<updated>2017-11-12T07:45:50Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* Define */&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=h&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
== Konfiguration ==&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;
=== Hinweis zu den Code Beispielen ===&lt;br /&gt;
Es handelt sich bei den Beispielen um eine Raw definition, siehe auch [[Import_von_Code_Snippets]]&lt;br /&gt;
&lt;br /&gt;
=== msgConfig ===&lt;br /&gt;
&lt;br /&gt;
Als erstes 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 userattr msgDialog_evalSpecials:textField-long msgDialog_msgCommand:textField&lt;br /&gt;
attr myMsgConfig msgContactPush &amp;lt;Name des TelegramBot-device&amp;gt;&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;
&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;
;msgDialog_evalSpecials&lt;br /&gt;
: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. Wenn der selbe Name im msgConfig und msgDialog definiert wurde, wird der Wert aus msgDialog verwendet.&lt;br /&gt;
&lt;br /&gt;
;msgDialog_msgCommand &amp;lt;command&amp;gt;&lt;br /&gt;
:Befehl zum Versenden einer Nachricht. Die Vorgabe ist &amp;quot;msg push \@$recipients $message&amp;quot;. Wenn nicht gesetzt, wird die Vorgabe verwendet.&lt;br /&gt;
&lt;br /&gt;
=== ROOMMATE / GUEST ===&lt;br /&gt;
Für jeden Dialog kann festgelegt werden welche Person 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 fhemMsgRcvPush ein Event erzeugt. Siehe auch Attribut &amp;quot;allowed&amp;quot; in msgDialog.&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;abbrechen&#039;) . &#039;) &#039;)}&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;zurück&amp;quot;: {\&lt;br /&gt;
    &amp;quot;commands&amp;quot;: &amp;quot;set $recipient_history=.+ say @$recipient {(ReadingsVal($DEV, &#039;$recipient_history&#039;, &#039;&#039;) =~ m/(.+)\\|.+$/;;;; return($2 ? $2 : $1;;;;)}&amp;quot;\&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;TelegramBot_MTYPE=queryInline (%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;TelegramBot_MTYPE=queryInline (%me%) &amp;quot;,\&lt;br /&gt;
      &amp;quot;Dialog beendet.&amp;quot;\&lt;br /&gt;
    ]\&lt;br /&gt;
  }\&lt;br /&gt;
}&lt;br /&gt;
attr meta_Dialog allowed everyone&lt;br /&gt;
&amp;lt;/pre&amp;gt;&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 &#039;&#039;&#039;DEF&#039;&#039;&#039; 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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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&lt;br /&gt;
:Kann einen einzelnen oder mehrere Befehle enthalten: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;commands&amp;quot;: &amp;quot;single command&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&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 &lt;br /&gt;
: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;: [&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;
&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;
=== 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;
=== 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;
=== 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;
== Hilfe bei der Fehlersuche ==&lt;br /&gt;
Hier entsteht eine Sammlung von Tipps bei der Fehlersuche. Die meisten dieser &amp;quot;Stolpersteine&amp;quot;&lt;br /&gt;
entstehen häufig bei der Erstellung eines ersten eigenen Dialoges.&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut allowed fehlt oder ist nicht korrekt gesetzt ===&lt;br /&gt;
Das allowed-Attribut dient dazu, einzelne Dialoge für alle  oder nur bestimmte Benutzer zu berechtigen.&lt;br /&gt;
Fehlt es, wird der Dialog dem aufrufenden Benutzer nicht angezeigt.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr Testdialog allowed everyone&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut msgDialog_evalSpecials fehlt oder ist nicht korrekt gesetzt ===&lt;br /&gt;
Dieses Attribut gehört dem msgConfig device und muss wie in 2.3 zu lesen&lt;br /&gt;
korrekt befüllt werden.&lt;br /&gt;
&amp;lt;pre&amp;gt;&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== JSON-Syntax Fehler ===&lt;br /&gt;
Das Modul prüft vor dem Abspeichern auf eine korrekte JSON-Syntax.&lt;br /&gt;
Meistens wird auch eine sprechende Meldung angezeigt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Usage: define &amp;lt;name&amp;gt; msgDialog {JSON}&lt;br /&gt;
&lt;br /&gt;
, or ] expected while parsing array, at character offset 73 (before &amp;quot;}\n}&amp;quot;) at ./FHEM/76_msgDialog.pm line 93.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Eine gute Anlaufstelle zur Überprüfung von JSON-Code ist hier: https://jsonlint.com/&lt;br /&gt;
 &lt;br /&gt;
=== Es werden keine Dialoge angezeigt ===&lt;br /&gt;
Ohne die Angabe einer normalen Nachricht wird kein Dialog angezeigt: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Erst mit der Nachricht &amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot; erscheint der Dialog:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
&amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot;&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
=== Innerhalb eines Dialogs fehlen einzelne Menüeinträge ===&lt;br /&gt;
Das liegt das meistens an einem fehlenden Leerzeichen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten)&amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Bei &amp;quot;Lampen ausschalten&amp;quot; ist dagegen korrekt ein Leerzeichen zu sehen und somit auch der Menüeintrag im Dialog.&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 ==&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;
== JABBER ==&lt;br /&gt;
Hier wird die Verwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Verwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23251</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23251"/>
		<updated>2017-11-12T07:44:55Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* Define */&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=h&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
== Konfiguration ==&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;
=== Hinweis zu den Code Beispielen ===&lt;br /&gt;
Es handelt sich bei den Beispielen um eine Raw definition, siehe auch [[Import_von_Code_Snippets]]&lt;br /&gt;
&lt;br /&gt;
=== msgConfig ===&lt;br /&gt;
&lt;br /&gt;
Als erstes 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 userattr msgDialog_evalSpecials:textField-long msgDialog_msgCommand:textField&lt;br /&gt;
attr myMsgConfig msgContactPush &amp;lt;Name des TelegramBot-device&amp;gt;&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;
&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;
;msgDialog_evalSpecials&lt;br /&gt;
: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. Wenn der selbe Name im msgConfig und msgDialog definiert wurde, wird der Wert aus msgDialog verwendet.&lt;br /&gt;
&lt;br /&gt;
;msgDialog_msgCommand &amp;lt;command&amp;gt;&lt;br /&gt;
:Befehl zum Versenden einer Nachricht. Die Vorgabe ist &amp;quot;msg push \@$recipients $message&amp;quot;. Wenn nicht gesetzt, wird die Vorgabe verwendet.&lt;br /&gt;
&lt;br /&gt;
=== ROOMMATE / GUEST ===&lt;br /&gt;
Für jeden Dialog kann festgelegt werden welche Person 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 fhemMsgRcvPush ein Event erzeugt. Siehe auch Attribut &amp;quot;allowed&amp;quot; in msgDialog.&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;abbrechen&#039;) . &#039;) &#039;)}&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;zurück&amp;quot;: {\&lt;br /&gt;
    &amp;quot;commands&amp;quot;: &amp;quot;set $recipient_history=.+ say @$recipient {(ReadingsVal($DEV, &#039;$recipient_history&#039;, &#039;&#039;) =~ m/(.+)\\|.+$/;;;; return($2 ? $2 : $1;;;;)}&amp;quot;\&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;TelegramBot_MTYPE=queryInline (%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;TelegramBot_MTYPE=queryInline (%me%) &amp;quot;,\&lt;br /&gt;
      &amp;quot;Dialog beendet.&amp;quot;\&lt;br /&gt;
    ]\&lt;br /&gt;
  }\&lt;br /&gt;
}&lt;br /&gt;
attr meta_Dialog allowed everyone&lt;br /&gt;
&amp;lt;/pre&amp;gt;&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 &#039;&#039;&#039;DEF&#039;&#039;&#039; 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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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&lt;br /&gt;
:Kann einen einzelnen oder mehrere Befehle enthalten: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;commands&amp;quot;: &amp;quot;single command&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&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 &lt;br /&gt;
: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;
&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;
=== 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;
=== 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;
=== 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;
== Hilfe bei der Fehlersuche ==&lt;br /&gt;
Hier entsteht eine Sammlung von Tipps bei der Fehlersuche. Die meisten dieser &amp;quot;Stolpersteine&amp;quot;&lt;br /&gt;
entstehen häufig bei der Erstellung eines ersten eigenen Dialoges.&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut allowed fehlt oder ist nicht korrekt gesetzt ===&lt;br /&gt;
Das allowed-Attribut dient dazu, einzelne Dialoge für alle  oder nur bestimmte Benutzer zu berechtigen.&lt;br /&gt;
Fehlt es, wird der Dialog dem aufrufenden Benutzer nicht angezeigt.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr Testdialog allowed everyone&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut msgDialog_evalSpecials fehlt oder ist nicht korrekt gesetzt ===&lt;br /&gt;
Dieses Attribut gehört dem msgConfig device und muss wie in 2.3 zu lesen&lt;br /&gt;
korrekt befüllt werden.&lt;br /&gt;
&amp;lt;pre&amp;gt;&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== JSON-Syntax Fehler ===&lt;br /&gt;
Das Modul prüft vor dem Abspeichern auf eine korrekte JSON-Syntax.&lt;br /&gt;
Meistens wird auch eine sprechende Meldung angezeigt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Usage: define &amp;lt;name&amp;gt; msgDialog {JSON}&lt;br /&gt;
&lt;br /&gt;
, or ] expected while parsing array, at character offset 73 (before &amp;quot;}\n}&amp;quot;) at ./FHEM/76_msgDialog.pm line 93.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Eine gute Anlaufstelle zur Überprüfung von JSON-Code ist hier: https://jsonlint.com/&lt;br /&gt;
 &lt;br /&gt;
=== Es werden keine Dialoge angezeigt ===&lt;br /&gt;
Ohne die Angabe einer normalen Nachricht wird kein Dialog angezeigt: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Erst mit der Nachricht &amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot; erscheint der Dialog:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
&amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot;&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
=== Innerhalb eines Dialogs fehlen einzelne Menüeinträge ===&lt;br /&gt;
Das liegt das meistens an einem fehlenden Leerzeichen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten)&amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Bei &amp;quot;Lampen ausschalten&amp;quot; ist dagegen korrekt ein Leerzeichen zu sehen und somit auch der Menüeintrag im Dialog.&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 ==&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;
== JABBER ==&lt;br /&gt;
Hier wird die Verwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Verwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23250</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23250"/>
		<updated>2017-11-12T07:43:31Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* Define */&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=h&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
== Konfiguration ==&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;
=== Hinweis zu den Code Beispielen ===&lt;br /&gt;
Es handelt sich bei den Beispielen um eine Raw definition, siehe auch [[Import_von_Code_Snippets]]&lt;br /&gt;
&lt;br /&gt;
=== msgConfig ===&lt;br /&gt;
&lt;br /&gt;
Als erstes 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 userattr msgDialog_evalSpecials:textField-long msgDialog_msgCommand:textField&lt;br /&gt;
attr myMsgConfig msgContactPush &amp;lt;Name des TelegramBot-device&amp;gt;&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;
&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;
;msgDialog_evalSpecials&lt;br /&gt;
: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. Wenn der selbe Name im msgConfig und msgDialog definiert wurde, wird der Wert aus msgDialog verwendet.&lt;br /&gt;
&lt;br /&gt;
;msgDialog_msgCommand &amp;lt;command&amp;gt;&lt;br /&gt;
:Befehl zum Versenden einer Nachricht. Die Vorgabe ist &amp;quot;msg push \@$recipients $message&amp;quot;. Wenn nicht gesetzt, wird die Vorgabe verwendet.&lt;br /&gt;
&lt;br /&gt;
=== ROOMMATE / GUEST ===&lt;br /&gt;
Für jeden Dialog kann festgelegt werden welche Person 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 fhemMsgRcvPush ein Event erzeugt. Siehe auch Attribut &amp;quot;allowed&amp;quot; in msgDialog.&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;abbrechen&#039;) . &#039;) &#039;)}&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;zurück&amp;quot;: {\&lt;br /&gt;
    &amp;quot;commands&amp;quot;: &amp;quot;set $recipient_history=.+ say @$recipient {(ReadingsVal($DEV, &#039;$recipient_history&#039;, &#039;&#039;) =~ m/(.+)\\|.+$/;;;; return($2 ? $2 : $1;;;;)}&amp;quot;\&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;TelegramBot_MTYPE=queryInline (%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;TelegramBot_MTYPE=queryInline (%me%) &amp;quot;,\&lt;br /&gt;
      &amp;quot;Dialog beendet.&amp;quot;\&lt;br /&gt;
    ]\&lt;br /&gt;
  }\&lt;br /&gt;
}&lt;br /&gt;
attr meta_Dialog allowed everyone&lt;br /&gt;
&amp;lt;/pre&amp;gt;&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 &#039;&#039;&#039;DEF&#039;&#039;&#039; 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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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;
&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;
=== 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;
=== 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;
=== 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;
== Hilfe bei der Fehlersuche ==&lt;br /&gt;
Hier entsteht eine Sammlung von Tipps bei der Fehlersuche. Die meisten dieser &amp;quot;Stolpersteine&amp;quot;&lt;br /&gt;
entstehen häufig bei der Erstellung eines ersten eigenen Dialoges.&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut allowed fehlt oder ist nicht korrekt gesetzt ===&lt;br /&gt;
Das allowed-Attribut dient dazu, einzelne Dialoge für alle  oder nur bestimmte Benutzer zu berechtigen.&lt;br /&gt;
Fehlt es, wird der Dialog dem aufrufenden Benutzer nicht angezeigt.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr Testdialog allowed everyone&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut msgDialog_evalSpecials fehlt oder ist nicht korrekt gesetzt ===&lt;br /&gt;
Dieses Attribut gehört dem msgConfig device und muss wie in 2.3 zu lesen&lt;br /&gt;
korrekt befüllt werden.&lt;br /&gt;
&amp;lt;pre&amp;gt;&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== JSON-Syntax Fehler ===&lt;br /&gt;
Das Modul prüft vor dem Abspeichern auf eine korrekte JSON-Syntax.&lt;br /&gt;
Meistens wird auch eine sprechende Meldung angezeigt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Usage: define &amp;lt;name&amp;gt; msgDialog {JSON}&lt;br /&gt;
&lt;br /&gt;
, or ] expected while parsing array, at character offset 73 (before &amp;quot;}\n}&amp;quot;) at ./FHEM/76_msgDialog.pm line 93.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Eine gute Anlaufstelle zur Überprüfung von JSON-Code ist hier: https://jsonlint.com/&lt;br /&gt;
 &lt;br /&gt;
=== Es werden keine Dialoge angezeigt ===&lt;br /&gt;
Ohne die Angabe einer normalen Nachricht wird kein Dialog angezeigt: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Erst mit der Nachricht &amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot; erscheint der Dialog:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
&amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot;&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
=== Innerhalb eines Dialogs fehlen einzelne Menüeinträge ===&lt;br /&gt;
Das liegt das meistens an einem fehlenden Leerzeichen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten)&amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Bei &amp;quot;Lampen ausschalten&amp;quot; ist dagegen korrekt ein Leerzeichen zu sehen und somit auch der Menüeintrag im Dialog.&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 ==&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;
== JABBER ==&lt;br /&gt;
Hier wird die Verwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Verwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23249</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23249"/>
		<updated>2017-11-12T07:42:52Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* msgConfig */&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=h&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
== Konfiguration ==&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;
=== Hinweis zu den Code Beispielen ===&lt;br /&gt;
Es handelt sich bei den Beispielen um eine Raw definition, siehe auch [[Import_von_Code_Snippets]]&lt;br /&gt;
&lt;br /&gt;
=== msgConfig ===&lt;br /&gt;
&lt;br /&gt;
Als erstes 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 userattr msgDialog_evalSpecials:textField-long msgDialog_msgCommand:textField&lt;br /&gt;
attr myMsgConfig msgContactPush &amp;lt;Name des TelegramBot-device&amp;gt;&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;
&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;
;msgDialog_evalSpecials&lt;br /&gt;
: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. Wenn der selbe Name im msgConfig und msgDialog definiert wurde, wird der Wert aus msgDialog verwendet.&lt;br /&gt;
&lt;br /&gt;
;msgDialog_msgCommand &amp;lt;command&amp;gt;&lt;br /&gt;
:Befehl zum Versenden einer Nachricht. Die Vorgabe ist &amp;quot;msg push \@$recipients $message&amp;quot;. Wenn nicht gesetzt, wird die Vorgabe verwendet.&lt;br /&gt;
&lt;br /&gt;
=== ROOMMATE / GUEST ===&lt;br /&gt;
Für jeden Dialog kann festgelegt werden welche Person 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 fhemMsgRcvPush ein Event erzeugt. Siehe auch Attribut &amp;quot;allowed&amp;quot; in msgDialog.&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;
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 &#039;&#039;&#039;DEF&#039;&#039;&#039; 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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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;
&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;
=== 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;
=== 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;
=== 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;
== Hilfe bei der Fehlersuche ==&lt;br /&gt;
Hier entsteht eine Sammlung von Tipps bei der Fehlersuche. Die meisten dieser &amp;quot;Stolpersteine&amp;quot;&lt;br /&gt;
entstehen häufig bei der Erstellung eines ersten eigenen Dialoges.&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut allowed fehlt oder ist nicht korrekt gesetzt ===&lt;br /&gt;
Das allowed-Attribut dient dazu, einzelne Dialoge für alle  oder nur bestimmte Benutzer zu berechtigen.&lt;br /&gt;
Fehlt es, wird der Dialog dem aufrufenden Benutzer nicht angezeigt.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr Testdialog allowed everyone&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut msgDialog_evalSpecials fehlt oder ist nicht korrekt gesetzt ===&lt;br /&gt;
Dieses Attribut gehört dem msgConfig device und muss wie in 2.3 zu lesen&lt;br /&gt;
korrekt befüllt werden.&lt;br /&gt;
&amp;lt;pre&amp;gt;&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== JSON-Syntax Fehler ===&lt;br /&gt;
Das Modul prüft vor dem Abspeichern auf eine korrekte JSON-Syntax.&lt;br /&gt;
Meistens wird auch eine sprechende Meldung angezeigt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Usage: define &amp;lt;name&amp;gt; msgDialog {JSON}&lt;br /&gt;
&lt;br /&gt;
, or ] expected while parsing array, at character offset 73 (before &amp;quot;}\n}&amp;quot;) at ./FHEM/76_msgDialog.pm line 93.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Eine gute Anlaufstelle zur Überprüfung von JSON-Code ist hier: https://jsonlint.com/&lt;br /&gt;
 &lt;br /&gt;
=== Es werden keine Dialoge angezeigt ===&lt;br /&gt;
Ohne die Angabe einer normalen Nachricht wird kein Dialog angezeigt: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Erst mit der Nachricht &amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot; erscheint der Dialog:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
&amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot;&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
=== Innerhalb eines Dialogs fehlen einzelne Menüeinträge ===&lt;br /&gt;
Das liegt das meistens an einem fehlenden Leerzeichen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten)&amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Bei &amp;quot;Lampen ausschalten&amp;quot; ist dagegen korrekt ein Leerzeichen zu sehen und somit auch der Menüeintrag im Dialog.&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 ==&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;
== JABBER ==&lt;br /&gt;
Hier wird die Verwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Verwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23236</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23236"/>
		<updated>2017-11-10T18:10:43Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* Innerhalb eines Dialogs fehlen einzelne Menüeinträge */&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=h&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
== Konfiguration ==&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;
=== Hinweis zu den Code Beispielen ===&lt;br /&gt;
Es handelt sich bei den Beispielen um eine Raw definition, siehe auch [[Import_von_Code_Snippets]]&lt;br /&gt;
&lt;br /&gt;
=== msgConfig ===&lt;br /&gt;
&lt;br /&gt;
Als erstes 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;
;msgDialog_evalSpecials&lt;br /&gt;
: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. Wenn der selbe Name im msgConfig und msgDialog definiert wurde, wird der Wert aus msgDialog verwendet.&lt;br /&gt;
&lt;br /&gt;
;msgDialog_msgCommand &amp;lt;command&amp;gt;&lt;br /&gt;
:Befehl zum Versenden einer Nachricht. Die Vorgabe ist &amp;quot;msg push \@$recipients $message&amp;quot;. Wenn nicht gesetzt, wird die Vorgabe verwendet.&lt;br /&gt;
&lt;br /&gt;
=== ROOMMATE / GUEST ===&lt;br /&gt;
Für jeden Dialog kann festgelegt werden welche Person 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 fhemMsgRcvPush ein Event erzeugt. Siehe auch Attribut &amp;quot;allowed&amp;quot; in msgDialog.&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;
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 &#039;&#039;&#039;DEF&#039;&#039;&#039; 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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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;
&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;
=== 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;
=== 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;
=== 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;
== Hilfe bei der Fehlersuche ==&lt;br /&gt;
Hier entsteht eine Sammlung von Tipps bei der Fehlersuche. Die meisten dieser &amp;quot;Stolpersteine&amp;quot;&lt;br /&gt;
entstehen häufig bei der Erstellung eines ersten eigenen Dialoges.&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut allowed fehlt oder ist nicht korrekt gesetzt ===&lt;br /&gt;
Das allowed-Attribut dient dazu, einzelne Dialoge für alle  oder nur bestimmte Benutzer zu berechtigen.&lt;br /&gt;
Fehlt es, wird der Dialog dem aufrufenden Benutzer nicht angezeigt.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr Testdialog allowed everyone&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut msgDialog_evalSpecials fehlt oder ist nicht korrekt gesetzt ===&lt;br /&gt;
Dieses Attribut gehört dem msgConfig device und muss wie in 2.3 zu lesen&lt;br /&gt;
korrekt befüllt werden.&lt;br /&gt;
&amp;lt;pre&amp;gt;&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== JSON-Syntax Fehler ===&lt;br /&gt;
Das Modul prüft vor dem Abspeichern auf eine korrekte JSON-Syntax.&lt;br /&gt;
Meistens wird auch eine sprechende Meldung angezeigt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Usage: define &amp;lt;name&amp;gt; msgDialog {JSON}&lt;br /&gt;
&lt;br /&gt;
, or ] expected while parsing array, at character offset 73 (before &amp;quot;}\n}&amp;quot;) at ./FHEM/76_msgDialog.pm line 93.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Eine gute Anlaufstelle zur Überprüfung von JSON-Code ist hier: https://jsonlint.com/&lt;br /&gt;
 &lt;br /&gt;
=== Es werden keine Dialoge angezeigt ===&lt;br /&gt;
Ohne die Angabe einer normalen Nachricht wird kein Dialog angezeigt: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Erst mit der Nachricht &amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot; erscheint der Dialog:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
&amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot;&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
=== Innerhalb eines Dialogs fehlen einzelne Menüeinträge ===&lt;br /&gt;
Das liegt das meistens an einem fehlenden Leerzeichen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten)&amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Bei &amp;quot;Lampen ausschalten&amp;quot; ist dagegen korrekt ein Leerzeichen zu sehen und somit auch der Menüeintrag im Dialog.&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 ==&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;
== JABBER ==&lt;br /&gt;
Hier wird die Verwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Verwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23235</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23235"/>
		<updated>2017-11-10T18:08:06Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* Das Attribut msgDialog_evalSpecials fehlt oder ist nicht korrekt gesetzt */&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=h&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
== Konfiguration ==&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;
=== Hinweis zu den Code Beispielen ===&lt;br /&gt;
Es handelt sich bei den Beispielen um eine Raw definition, siehe auch [[Import_von_Code_Snippets]]&lt;br /&gt;
&lt;br /&gt;
=== msgConfig ===&lt;br /&gt;
&lt;br /&gt;
Als erstes 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;
;msgDialog_evalSpecials&lt;br /&gt;
: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. Wenn der selbe Name im msgConfig und msgDialog definiert wurde, wird der Wert aus msgDialog verwendet.&lt;br /&gt;
&lt;br /&gt;
;msgDialog_msgCommand &amp;lt;command&amp;gt;&lt;br /&gt;
:Befehl zum Versenden einer Nachricht. Die Vorgabe ist &amp;quot;msg push \@$recipients $message&amp;quot;. Wenn nicht gesetzt, wird die Vorgabe verwendet.&lt;br /&gt;
&lt;br /&gt;
=== ROOMMATE / GUEST ===&lt;br /&gt;
Für jeden Dialog kann festgelegt werden welche Person 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 fhemMsgRcvPush ein Event erzeugt. Siehe auch Attribut &amp;quot;allowed&amp;quot; in msgDialog.&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;
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 &#039;&#039;&#039;DEF&#039;&#039;&#039; 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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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;
&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;
=== 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;
=== 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;
=== 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;
== Hilfe bei der Fehlersuche ==&lt;br /&gt;
Hier entsteht eine Sammlung von Tipps bei der Fehlersuche. Die meisten dieser &amp;quot;Stolpersteine&amp;quot;&lt;br /&gt;
entstehen häufig bei der Erstellung eines ersten eigenen Dialoges.&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut allowed fehlt oder ist nicht korrekt gesetzt ===&lt;br /&gt;
Das allowed-Attribut dient dazu, einzelne Dialoge für alle  oder nur bestimmte Benutzer zu berechtigen.&lt;br /&gt;
Fehlt es, wird der Dialog dem aufrufenden Benutzer nicht angezeigt.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr Testdialog allowed everyone&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut msgDialog_evalSpecials fehlt oder ist nicht korrekt gesetzt ===&lt;br /&gt;
Dieses Attribut gehört dem msgConfig device und muss wie in 2.3 zu lesen&lt;br /&gt;
korrekt befüllt werden.&lt;br /&gt;
&amp;lt;pre&amp;gt;&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;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== JSON-Syntax Fehler ===&lt;br /&gt;
Das Modul prüft vor dem Abspeichern auf eine korrekte JSON-Syntax.&lt;br /&gt;
Meistens wird auch eine sprechende Meldung angezeigt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Usage: define &amp;lt;name&amp;gt; msgDialog {JSON}&lt;br /&gt;
&lt;br /&gt;
, or ] expected while parsing array, at character offset 73 (before &amp;quot;}\n}&amp;quot;) at ./FHEM/76_msgDialog.pm line 93.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Eine gute Anlaufstelle zur Überprüfung von JSON-Code ist hier: https://jsonlint.com/&lt;br /&gt;
 &lt;br /&gt;
=== Es werden keine Dialoge angezeigt ===&lt;br /&gt;
Ohne die Angabe einer normalen Nachricht wird kein Dialog angezeigt: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Erst mit der Nachricht &amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot; erscheint der Dialog:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
&amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot;&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
=== Innerhalb eines Dialogs fehlen einzelne Menüeinträge ===&lt;br /&gt;
Fehlen einzelne Menüeinträge innerhalb eines Dialogs, liegt das meistens an einem&lt;br /&gt;
fehlenden Leerzeichen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten)&amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Bei &amp;quot;Lampen ausschalten&amp;quot; ist dagegen korrekt ein Leerzeichen zu sehen und somit auch der Menüeintrag im Dialog.&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 ==&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;
== JABBER ==&lt;br /&gt;
Hier wird die Verwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Verwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23234</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23234"/>
		<updated>2017-11-10T18:06:58Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* Hilfe bei der Fehlersuche */&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=h&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
== Konfiguration ==&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;
=== Hinweis zu den Code Beispielen ===&lt;br /&gt;
Es handelt sich bei den Beispielen um eine Raw definition, siehe auch [[Import_von_Code_Snippets]]&lt;br /&gt;
&lt;br /&gt;
=== msgConfig ===&lt;br /&gt;
&lt;br /&gt;
Als erstes 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;
;msgDialog_evalSpecials&lt;br /&gt;
: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. Wenn der selbe Name im msgConfig und msgDialog definiert wurde, wird der Wert aus msgDialog verwendet.&lt;br /&gt;
&lt;br /&gt;
;msgDialog_msgCommand &amp;lt;command&amp;gt;&lt;br /&gt;
:Befehl zum Versenden einer Nachricht. Die Vorgabe ist &amp;quot;msg push \@$recipients $message&amp;quot;. Wenn nicht gesetzt, wird die Vorgabe verwendet.&lt;br /&gt;
&lt;br /&gt;
=== ROOMMATE / GUEST ===&lt;br /&gt;
Für jeden Dialog kann festgelegt werden welche Person 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 fhemMsgRcvPush ein Event erzeugt. Siehe auch Attribut &amp;quot;allowed&amp;quot; in msgDialog.&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;
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 &#039;&#039;&#039;DEF&#039;&#039;&#039; 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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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;
&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;
=== 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;
=== 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;
=== 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;
== Hilfe bei der Fehlersuche ==&lt;br /&gt;
Hier entsteht eine Sammlung von Tipps bei der Fehlersuche. Die meisten dieser &amp;quot;Stolpersteine&amp;quot;&lt;br /&gt;
entstehen häufig bei der Erstellung eines ersten eigenen Dialoges.&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut allowed fehlt oder ist nicht korrekt gesetzt ===&lt;br /&gt;
Das allowed-Attribut dient dazu, einzelne Dialoge für alle  oder nur bestimmte Benutzer zu berechtigen.&lt;br /&gt;
Fehlt es, wird der Dialog dem aufrufenden Benutzer nicht angezeigt.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr Testdialog allowed everyone&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut msgDialog_evalSpecials fehlt oder ist nicht korrekt gesetzt ===&lt;br /&gt;
Dieses Attribut gehört dem msgConfig device und muss wie in 2.3 zu lesen&lt;br /&gt;
korrekt befüllt werden.&lt;br /&gt;
&lt;br /&gt;
=== JSON-Syntax Fehler ===&lt;br /&gt;
Das Modul prüft vor dem Abspeichern auf eine korrekte JSON-Syntax.&lt;br /&gt;
Meistens wird auch eine sprechende Meldung angezeigt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Usage: define &amp;lt;name&amp;gt; msgDialog {JSON}&lt;br /&gt;
&lt;br /&gt;
, or ] expected while parsing array, at character offset 73 (before &amp;quot;}\n}&amp;quot;) at ./FHEM/76_msgDialog.pm line 93.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Eine gute Anlaufstelle zur Überprüfung von JSON-Code ist hier: https://jsonlint.com/&lt;br /&gt;
 &lt;br /&gt;
=== Es werden keine Dialoge angezeigt ===&lt;br /&gt;
Ohne die Angabe einer normalen Nachricht wird kein Dialog angezeigt: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Erst mit der Nachricht &amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot; erscheint der Dialog:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
&amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot;&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
=== Innerhalb eines Dialogs fehlen einzelne Menüeinträge ===&lt;br /&gt;
Fehlen einzelne Menüeinträge innerhalb eines Dialogs, liegt das meistens an einem&lt;br /&gt;
fehlenden Leerzeichen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten)&amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Bei &amp;quot;Lampen ausschalten&amp;quot; ist dagegen korrekt ein Leerzeichen zu sehen und somit auch der Menüeintrag im Dialog.&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 ==&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;
== JABBER ==&lt;br /&gt;
Hier wird die Verwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Verwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23233</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23233"/>
		<updated>2017-11-10T18:02:19Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* Hilfe bei der Fehlersuche */&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=h&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
== Konfiguration ==&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;
=== Hinweis zu den Code Beispielen ===&lt;br /&gt;
Es handelt sich bei den Beispielen um eine Raw definition, siehe auch [[Import_von_Code_Snippets]]&lt;br /&gt;
&lt;br /&gt;
=== msgConfig ===&lt;br /&gt;
&lt;br /&gt;
Als erstes 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;
;msgDialog_evalSpecials&lt;br /&gt;
: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. Wenn der selbe Name im msgConfig und msgDialog definiert wurde, wird der Wert aus msgDialog verwendet.&lt;br /&gt;
&lt;br /&gt;
;msgDialog_msgCommand &amp;lt;command&amp;gt;&lt;br /&gt;
:Befehl zum Versenden einer Nachricht. Die Vorgabe ist &amp;quot;msg push \@$recipients $message&amp;quot;. Wenn nicht gesetzt, wird die Vorgabe verwendet.&lt;br /&gt;
&lt;br /&gt;
=== ROOMMATE / GUEST ===&lt;br /&gt;
Für jeden Dialog kann festgelegt werden welche Person 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 fhemMsgRcvPush ein Event erzeugt. Siehe auch Attribut &amp;quot;allowed&amp;quot; in msgDialog.&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;
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 &#039;&#039;&#039;DEF&#039;&#039;&#039; 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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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;
&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;
=== 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;
=== 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;
=== 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;
== Hilfe bei der Fehlersuche ==&lt;br /&gt;
Hier entsteht eine Sammlung von Tipps bei der Fehlersuche. Die meisten dieser &amp;quot;Stolpersteine&amp;quot;&lt;br /&gt;
entstehen häufig bei der Erstellung eines ersten eigenen Dialoges.&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut allowed fehlt oder ist nicht korrekt gesetzt ===&lt;br /&gt;
Das allowed-Attribut dient dazu, einzelne Dialoge für alle  oder nur bestimmte Benutzer zu berechtigen.&lt;br /&gt;
Fehlt es, wird der Dialog dem aufrufenden Benutzer nicht angezeigt.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr Testdialog allowed everyone&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== JSON-Syntax Fehler ===&lt;br /&gt;
Das Modul prüft vor dem Abspeichern auf eine korrekte JSON-Syntax.&lt;br /&gt;
Meistens wird auch eine sprechende Meldung angezeigt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Usage: define &amp;lt;name&amp;gt; msgDialog {JSON}&lt;br /&gt;
&lt;br /&gt;
, or ] expected while parsing array, at character offset 73 (before &amp;quot;}\n}&amp;quot;) at ./FHEM/76_msgDialog.pm line 93.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Eine gute Anlaufstelle zur Überprüfung von JSON-Code ist hier: https://jsonlint.com/&lt;br /&gt;
 &lt;br /&gt;
=== Es werden keine Dialoge angezeigt ===&lt;br /&gt;
Ohne die Angabe einer normalen Nachricht wird kein Dialog angezeigt: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Erst mit der Nachricht &amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot; erscheint der Dialog:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
&amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot;&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
=== Innerhalb eines Dialogs fehlen einzelne Menüeinträge ===&lt;br /&gt;
Fehlen einzelne Menüeinträge innerhalb eines Dialogs, liegt das meistens an einem&lt;br /&gt;
fehlenden Leerzeichen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten)&amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Bei &amp;quot;Lampen ausschalten&amp;quot; ist dagegen korrekt ein Leerzeichen zu sehen und somit auch der Menüeintrag im Dialog.&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 ==&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;
== JABBER ==&lt;br /&gt;
Hier wird die Verwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Verwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23232</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23232"/>
		<updated>2017-11-10T17:58:06Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* Hilfe bei der Fehlersuche */&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=h&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
== Konfiguration ==&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;
=== Hinweis zu den Code Beispielen ===&lt;br /&gt;
Es handelt sich bei den Beispielen um eine Raw definition, siehe auch [[Import_von_Code_Snippets]]&lt;br /&gt;
&lt;br /&gt;
=== msgConfig ===&lt;br /&gt;
&lt;br /&gt;
Als erstes 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;
;msgDialog_evalSpecials&lt;br /&gt;
: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. Wenn der selbe Name im msgConfig und msgDialog definiert wurde, wird der Wert aus msgDialog verwendet.&lt;br /&gt;
&lt;br /&gt;
;msgDialog_msgCommand &amp;lt;command&amp;gt;&lt;br /&gt;
:Befehl zum Versenden einer Nachricht. Die Vorgabe ist &amp;quot;msg push \@$recipients $message&amp;quot;. Wenn nicht gesetzt, wird die Vorgabe verwendet.&lt;br /&gt;
&lt;br /&gt;
=== ROOMMATE / GUEST ===&lt;br /&gt;
Für jeden Dialog kann festgelegt werden welche Person 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 fhemMsgRcvPush ein Event erzeugt. Siehe auch Attribut &amp;quot;allowed&amp;quot; in msgDialog.&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;
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 &#039;&#039;&#039;DEF&#039;&#039;&#039; 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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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;
&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;
=== 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;
=== 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;
=== 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;
== Hilfe bei der Fehlersuche ==&lt;br /&gt;
Hier entsteht eine Sammlung von Tipps bei der Fehlersuche. Die meisten dieser &amp;quot;Stolpersteine&amp;quot;&lt;br /&gt;
entstehen häufig bei der Erstellung eines ersten eigenen Dialoges.&lt;br /&gt;
&lt;br /&gt;
=== Das Attribut allowed fehlt oder ist nicht korrekt gesetzt ===&lt;br /&gt;
Das allowed-Attribut dient dazu, einzelne Dialoge für alle  oder nur bestimmte Benutzer zu berechtigen.&lt;br /&gt;
Fehlt es, wird der Dialog dem aufrufenden Benutzer nicht angezeigt.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr Testdialog allowed everyone&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== JSON-Syntax Fehler ===&lt;br /&gt;
Das Modul prüft vor dem Abspeichern auf eine korrekte JSON-Syntax.&lt;br /&gt;
Meistens wird auch eine sprechende Meldung angezeigt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Usage: define &amp;lt;name&amp;gt; msgDialog {JSON}&lt;br /&gt;
&lt;br /&gt;
, or ] expected while parsing array, at character offset 73 (before &amp;quot;}\n}&amp;quot;) at ./FHEM/76_msgDialog.pm line 93.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Eine gute Anlaufstelle zur Überprüfung von JSON-Code ist hier.&lt;br /&gt;
 &lt;br /&gt;
=== Es werden keine Dialoge angezeigt ===&lt;br /&gt;
Ohne die Angabe einer normalen Nachricht wird kein Dialog angezeigt: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Erst mit der Nachricht &amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot; erscheint der Dialog:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
&amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot;&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
=== Innerhalb eines Dialogs fehlen einzelne Menüeinträge ===&lt;br /&gt;
Fehlen einzelne Menüeinträge innerhalb eines Dialogs, liegt das meistens an einem&lt;br /&gt;
fehlenden Leerzeichen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten)&amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Bei &amp;quot;Lampen ausschalten&amp;quot; ist dagegen korrekt ein Leerzeichen zu sehen und somit auch der Menüeintrag im Dialog.&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 ==&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;
== JABBER ==&lt;br /&gt;
Hier wird die Verwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Verwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23231</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23231"/>
		<updated>2017-11-10T17:47:05Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* Innerhalb eines Dialogs fehlen einzelne Menüeinträge */&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=h&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
== Konfiguration ==&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;
=== Hinweis zu den Code Beispielen ===&lt;br /&gt;
Es handelt sich bei den Beispielen um eine Raw definition, siehe auch [[Import_von_Code_Snippets]]&lt;br /&gt;
&lt;br /&gt;
=== msgConfig ===&lt;br /&gt;
&lt;br /&gt;
Als erstes 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;
;msgDialog_evalSpecials&lt;br /&gt;
: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. Wenn der selbe Name im msgConfig und msgDialog definiert wurde, wird der Wert aus msgDialog verwendet.&lt;br /&gt;
&lt;br /&gt;
;msgDialog_msgCommand &amp;lt;command&amp;gt;&lt;br /&gt;
:Befehl zum Versenden einer Nachricht. Die Vorgabe ist &amp;quot;msg push \@$recipients $message&amp;quot;. Wenn nicht gesetzt, wird die Vorgabe verwendet.&lt;br /&gt;
&lt;br /&gt;
=== ROOMMATE / GUEST ===&lt;br /&gt;
Für jeden Dialog kann festgelegt werden welche Person 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 fhemMsgRcvPush ein Event erzeugt. Siehe auch Attribut &amp;quot;allowed&amp;quot; in msgDialog.&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;
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 &#039;&#039;&#039;DEF&#039;&#039;&#039; 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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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;
&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;
=== 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;
=== 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;
=== 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;
== Hilfe bei der Fehlersuche ==&lt;br /&gt;
Hier entsteht eine Sammlung von Tipps bei der Fehlersuche. Die meisten dieser &amp;quot;Stolpersteine&amp;quot;&lt;br /&gt;
entstehen häufig bei der Erstellung eines ersten eigenen Dialoges.&lt;br /&gt;
&lt;br /&gt;
=== Es werden keine Dialoge angezeigt ===&lt;br /&gt;
Ohne die Angabe einer normalen Nachricht wird kein Dialog angezeigt: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Erst mit der Nachricht &amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot; erscheint der Dialog:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
&amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot;&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
=== Innerhalb eines Dialogs fehlen einzelne Menüeinträge ===&lt;br /&gt;
Fehlen einzelne Menüeinträge innerhalb eines Dialogs, liegt das meistens an einem&lt;br /&gt;
fehlenden Leerzeichen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten)&amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Bei &amp;quot;Lampen ausschalten&amp;quot; ist dagegen korrekt ein Leerzeichen zu sehen und somit auch der Menüeintrag im Dialog.&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 ==&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;
== JABBER ==&lt;br /&gt;
Hier wird die Verwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Verwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23230</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23230"/>
		<updated>2017-11-10T17:46:26Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* Hilfe bei der Fehlersuche */&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=h&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
== Konfiguration ==&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;
=== Hinweis zu den Code Beispielen ===&lt;br /&gt;
Es handelt sich bei den Beispielen um eine Raw definition, siehe auch [[Import_von_Code_Snippets]]&lt;br /&gt;
&lt;br /&gt;
=== msgConfig ===&lt;br /&gt;
&lt;br /&gt;
Als erstes 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;
;msgDialog_evalSpecials&lt;br /&gt;
: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. Wenn der selbe Name im msgConfig und msgDialog definiert wurde, wird der Wert aus msgDialog verwendet.&lt;br /&gt;
&lt;br /&gt;
;msgDialog_msgCommand &amp;lt;command&amp;gt;&lt;br /&gt;
:Befehl zum Versenden einer Nachricht. Die Vorgabe ist &amp;quot;msg push \@$recipients $message&amp;quot;. Wenn nicht gesetzt, wird die Vorgabe verwendet.&lt;br /&gt;
&lt;br /&gt;
=== ROOMMATE / GUEST ===&lt;br /&gt;
Für jeden Dialog kann festgelegt werden welche Person 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 fhemMsgRcvPush ein Event erzeugt. Siehe auch Attribut &amp;quot;allowed&amp;quot; in msgDialog.&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;
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 &#039;&#039;&#039;DEF&#039;&#039;&#039; 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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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;
&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;
=== 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;
=== 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;
=== 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;
== Hilfe bei der Fehlersuche ==&lt;br /&gt;
Hier entsteht eine Sammlung von Tipps bei der Fehlersuche. Die meisten dieser &amp;quot;Stolpersteine&amp;quot;&lt;br /&gt;
entstehen häufig bei der Erstellung eines ersten eigenen Dialoges.&lt;br /&gt;
&lt;br /&gt;
=== Es werden keine Dialoge angezeigt ===&lt;br /&gt;
Ohne die Angabe einer normalen Nachricht wird kein Dialog angezeigt: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Erst mit der Nachricht &amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot; erscheint der Dialog:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
&amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot;&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
=== Innerhalb eines Dialogs fehlen einzelne Menüeinträge ===&lt;br /&gt;
Fehlen einzelne Menüeinträge innerhalb eines Dialogs, liegt das meistens an einem&lt;br /&gt;
fehlenden Leerzeichen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten)&amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Das wird durch ein fehlendes Leerzeichen nach der geschlossenen runden Klammer verursacht.&lt;br /&gt;
Bei &amp;quot;Lampen ausschalten&amp;quot; ist dagegen korrekt ein Leerzeichen zu sehen.&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 ==&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;
== JABBER ==&lt;br /&gt;
Hier wird die Verwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Verwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23229</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23229"/>
		<updated>2017-11-10T17:43:03Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* Hilfe bei der Fehlersuche */&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=h&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
== Konfiguration ==&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;
=== Hinweis zu den Code Beispielen ===&lt;br /&gt;
Es handelt sich bei den Beispielen um eine Raw definition, siehe auch [[Import_von_Code_Snippets]]&lt;br /&gt;
&lt;br /&gt;
=== msgConfig ===&lt;br /&gt;
&lt;br /&gt;
Als erstes 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;
;msgDialog_evalSpecials&lt;br /&gt;
: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. Wenn der selbe Name im msgConfig und msgDialog definiert wurde, wird der Wert aus msgDialog verwendet.&lt;br /&gt;
&lt;br /&gt;
;msgDialog_msgCommand &amp;lt;command&amp;gt;&lt;br /&gt;
:Befehl zum Versenden einer Nachricht. Die Vorgabe ist &amp;quot;msg push \@$recipients $message&amp;quot;. Wenn nicht gesetzt, wird die Vorgabe verwendet.&lt;br /&gt;
&lt;br /&gt;
=== ROOMMATE / GUEST ===&lt;br /&gt;
Für jeden Dialog kann festgelegt werden welche Person 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 fhemMsgRcvPush ein Event erzeugt. Siehe auch Attribut &amp;quot;allowed&amp;quot; in msgDialog.&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;
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 &#039;&#039;&#039;DEF&#039;&#039;&#039; 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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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;
&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;
=== 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;
=== 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;
=== 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;
== Hilfe bei der Fehlersuche ==&lt;br /&gt;
Hier entsteht eine Sammlung von Tipps bei der Fehlersuche. Die meisten dieser &amp;quot;Stolpersteine&amp;quot;&lt;br /&gt;
entstehen häufig bei der Erstellung eines ersten eigenen Dialoges.&lt;br /&gt;
&lt;br /&gt;
;Es werden keine Dialoge angezeigt, in diesem Beispiel &amp;quot;Beleuchtung&amp;quot;:&lt;br /&gt;
: Dieses Problem entsteht häufig beider Erstellung eines ersten eigenen Dialoges:&lt;br /&gt;
: Ohne die Angabe einer normalen Nachricht wird kein Dialog angezeigt: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Mit der Nachricht &amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot; erscheint der Dialog&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
&amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot;&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
;Innerhalb eines Dialogs fehlen einzelne Menüeinträge, in diesem Beispiel &amp;quot;Lampen einschalten&amp;quot;:&lt;br /&gt;
: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten)&amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
: Das wird durch ein fehlendes Leerzeichen nach der geschlossenen runden Klammer verursacht.&lt;br /&gt;
: Bei &amp;quot;Lampen ausschalten&amp;quot; ist dagegen korrekt ein Leerzeichen zu sehen.&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 ==&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;
== JABBER ==&lt;br /&gt;
Hier wird die Verwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Verwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23228</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23228"/>
		<updated>2017-11-10T17:42:39Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: &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=h&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
== Konfiguration ==&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;
=== Hinweis zu den Code Beispielen ===&lt;br /&gt;
Es handelt sich bei den Beispielen um eine Raw definition, siehe auch [[Import_von_Code_Snippets]]&lt;br /&gt;
&lt;br /&gt;
=== msgConfig ===&lt;br /&gt;
&lt;br /&gt;
Als erstes 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;
;msgDialog_evalSpecials&lt;br /&gt;
: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. Wenn der selbe Name im msgConfig und msgDialog definiert wurde, wird der Wert aus msgDialog verwendet.&lt;br /&gt;
&lt;br /&gt;
;msgDialog_msgCommand &amp;lt;command&amp;gt;&lt;br /&gt;
:Befehl zum Versenden einer Nachricht. Die Vorgabe ist &amp;quot;msg push \@$recipients $message&amp;quot;. Wenn nicht gesetzt, wird die Vorgabe verwendet.&lt;br /&gt;
&lt;br /&gt;
=== ROOMMATE / GUEST ===&lt;br /&gt;
Für jeden Dialog kann festgelegt werden welche Person 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 fhemMsgRcvPush ein Event erzeugt. Siehe auch Attribut &amp;quot;allowed&amp;quot; in msgDialog.&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;
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 &#039;&#039;&#039;DEF&#039;&#039;&#039; 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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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;
&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;
=== 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;
=== 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;
=== 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;
=== Hilfe bei der Fehlersuche ===&lt;br /&gt;
Hier entsteht eine Sammlung von Tipps bei der Fehlersuche. Die meisten dieser &amp;quot;Stolpersteine&amp;quot;&lt;br /&gt;
entstehen häufig bei der Erstellung eines ersten eigenen Dialoges.&lt;br /&gt;
&lt;br /&gt;
;Es werden keine Dialoge angezeigt, in diesem Beispiel &amp;quot;Beleuchtung&amp;quot;:&lt;br /&gt;
: Dieses Problem entsteht häufig beider Erstellung eines ersten eigenen Dialoges:&lt;br /&gt;
: Ohne die Angabe einer normalen Nachricht wird kein Dialog angezeigt: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Mit der Nachricht &amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot; erscheint der Dialog&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
&amp;quot;Möchtest Du Lampen ein oder ausschalten?&amp;quot;&lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
&lt;br /&gt;
;Innerhalb eines Dialogs fehlen einzelne Menüeinträge, in diesem Beispiel &amp;quot;Lampen einschalten&amp;quot;:&lt;br /&gt;
: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;quot;message&amp;quot;: [&lt;br /&gt;
&amp;quot;(Lampen einschalten)&amp;quot;,&lt;br /&gt;
&amp;quot;(Lampen ausschalten) &amp;quot;,&lt;br /&gt;
&amp;quot;(zurück:%me%) &amp;quot;, &lt;br /&gt;
],&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
: Das wird durch ein fehlendes Leerzeichen nach der geschlossenen runden Klammer verursacht.&lt;br /&gt;
: Bei &amp;quot;Lampen ausschalten&amp;quot; ist dagegen korrekt ein Leerzeichen zu sehen.&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 ==&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;
== JABBER ==&lt;br /&gt;
Hier wird die Verwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Verwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23125</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23125"/>
		<updated>2017-10-31T09:40:08Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* Define */&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=h&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
== Konfiguration ==&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;
=== Hinweis zu den Code Beispielen ===&lt;br /&gt;
Es handelt sich bei den Beispielen um eine Raw definition, siehe auch [[Import_von_Code_Snippets]]&lt;br /&gt;
&lt;br /&gt;
=== msgConfig ===&lt;br /&gt;
&lt;br /&gt;
Als erstes 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;
;msgDialog_evalSpecials&lt;br /&gt;
: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. Wenn der selbe Name im msgConfig und msgDialog definiert wurde, wird der Wert aus msgDialog verwendet.&lt;br /&gt;
&lt;br /&gt;
;msgDialog_msgCommand &amp;lt;command&amp;gt;&lt;br /&gt;
:Befehl zum Versenden einer Nachricht. Die Vorgabe ist &amp;quot;msg push \@$recipients $message&amp;quot;. Wenn nicht gesetzt, wird die Vorgabe verwendet.&lt;br /&gt;
&lt;br /&gt;
=== ROOMMATE / GUEST ===&lt;br /&gt;
Für jeden Dialog kann festgelegt werden welche Person 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 fhemMsgRcvPush ein Event erzeugt. Siehe auch Attribut &amp;quot;allowed&amp;quot; in msgDialog.&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;
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 &#039;&#039;&#039;DEF&#039;&#039;&#039; 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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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;
&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;
=== 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;
=== 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;
=== 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 ==&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;
== JABBER ==&lt;br /&gt;
Hier wird die Verwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Verwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23124</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23124"/>
		<updated>2017-10-31T09:38:42Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* msgConfig */&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=h&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
== Konfiguration ==&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;
=== Hinweis zu den Code Beispielen ===&lt;br /&gt;
Es handelt sich bei den Beispielen um eine Raw definition, siehe auch [[Import_von_Code_Snippets]]&lt;br /&gt;
&lt;br /&gt;
=== msgConfig ===&lt;br /&gt;
&lt;br /&gt;
Als erstes 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;
;msgDialog_evalSpecials&lt;br /&gt;
: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. Wenn der selbe Name im msgConfig und msgDialog definiert wurde, wird der Wert aus msgDialog verwendet.&lt;br /&gt;
&lt;br /&gt;
;msgDialog_msgCommand &amp;lt;command&amp;gt;&lt;br /&gt;
:Befehl zum Versenden einer Nachricht. Die Vorgabe ist &amp;quot;msg push \@$recipients $message&amp;quot;. Wenn nicht gesetzt, wird die Vorgabe verwendet.&lt;br /&gt;
&lt;br /&gt;
=== ROOMMATE / GUEST ===&lt;br /&gt;
Für jeden Dialog kann festgelegt werden welche Person 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 fhemMsgRcvPush ein Event erzeugt. Siehe auch Attribut &amp;quot;allowed&amp;quot; in msgDialog.&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;
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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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;
&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;
=== 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;
=== 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;
=== 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 ==&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;
== JABBER ==&lt;br /&gt;
Hier wird die Verwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Verwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23123</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23123"/>
		<updated>2017-10-31T09:35:57Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* Define */&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=h&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
== Konfiguration ==&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;
=== Hinweis zu den Code Beispielen ===&lt;br /&gt;
Es handelt sich bei den Beispielen um eine Raw definition, siehe auch [[Import_von_Code_Snippets]]&lt;br /&gt;
&lt;br /&gt;
=== msgConfig ===&lt;br /&gt;
&lt;br /&gt;
Als erstes 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;
;msgDialog_evalSpecials&lt;br /&gt;
: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. Wenn der selbe Name im msgConfig und msgDialog definiert wurde, wird der Wert aus msgDialog verwendet.&lt;br /&gt;
&lt;br /&gt;
;msgDialog_msgCommand &amp;lt;command&amp;gt;&lt;br /&gt;
:Befehl zum Versenden einer Nachricht. Die Vorgabe ist &amp;quot;msg push \@$recipients $message&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== ROOMMATE / GUEST ===&lt;br /&gt;
Für jeden Dialog kann festgelegt werden welche Person 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 fhemMsgRcvPush ein Event erzeugt. Siehe auch Attribut &amp;quot;allowed&amp;quot; in msgDialog.&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;
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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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;
&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;
=== 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;
=== 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;
=== 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 ==&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;
== JABBER ==&lt;br /&gt;
Hier wird die Verwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Verwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23122</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23122"/>
		<updated>2017-10-31T09:35:27Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* Define */&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=h&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
== Konfiguration ==&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;
=== Hinweis zu den Code Beispielen ===&lt;br /&gt;
Es handelt sich bei den Beispielen um eine Raw definition, siehe auch [[Import_von_Code_Snippets]]&lt;br /&gt;
&lt;br /&gt;
=== msgConfig ===&lt;br /&gt;
&lt;br /&gt;
Als erstes 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;
;msgDialog_evalSpecials&lt;br /&gt;
: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. Wenn der selbe Name im msgConfig und msgDialog definiert wurde, wird der Wert aus msgDialog verwendet.&lt;br /&gt;
&lt;br /&gt;
;msgDialog_msgCommand &amp;lt;command&amp;gt;&lt;br /&gt;
:Befehl zum Versenden einer Nachricht. Die Vorgabe ist &amp;quot;msg push \@$recipients $message&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== ROOMMATE / GUEST ===&lt;br /&gt;
Für jeden Dialog kann festgelegt werden welche Person 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 fhemMsgRcvPush ein Event erzeugt. Siehe auch Attribut &amp;quot;allowed&amp;quot; in msgDialog.&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;
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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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&lt;br /&gt;
: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 &lt;br /&gt;
: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;
&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;
=== 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;
=== 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;
=== 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 ==&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;
== JABBER ==&lt;br /&gt;
Hier wird die Verwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Verwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23121</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23121"/>
		<updated>2017-10-31T09:33:24Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* msgConfig */&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=h&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
== Konfiguration ==&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;
=== Hinweis zu den Code Beispielen ===&lt;br /&gt;
Es handelt sich bei den Beispielen um eine Raw definition, siehe auch [[Import_von_Code_Snippets]]&lt;br /&gt;
&lt;br /&gt;
=== msgConfig ===&lt;br /&gt;
&lt;br /&gt;
Als erstes 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;
;msgDialog_evalSpecials&lt;br /&gt;
: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. Wenn der selbe Name im msgConfig und msgDialog definiert wurde, wird der Wert aus msgDialog verwendet.&lt;br /&gt;
&lt;br /&gt;
;msgDialog_msgCommand &amp;lt;command&amp;gt;&lt;br /&gt;
:Befehl zum Versenden einer Nachricht. Die Vorgabe ist &amp;quot;msg push \@$recipients $message&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== ROOMMATE / GUEST ===&lt;br /&gt;
Für jeden Dialog kann festgelegt werden welche Person 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 fhemMsgRcvPush ein Event erzeugt. Siehe auch Attribut &amp;quot;allowed&amp;quot; in msgDialog.&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;
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;
&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;
=== 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;
=== 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;
=== 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 ==&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;
== JABBER ==&lt;br /&gt;
Hier wird die Verwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Verwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23120</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23120"/>
		<updated>2017-10-31T09:31:45Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* ROOMMATE / GUEST */&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=h&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
== Konfiguration ==&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;
=== Hinweis zu den Code Beispielen ===&lt;br /&gt;
Es handelt sich bei den Beispielen um eine Raw definition, siehe auch [[Import_von_Code_Snippets]]&lt;br /&gt;
&lt;br /&gt;
=== msgConfig ===&lt;br /&gt;
&lt;br /&gt;
Als erstes 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;
* msgDialog_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. Wenn der selbe Name im msgConfig und msgDialog definiert wurde, wird der Wert aus msgDialog verwendet.&lt;br /&gt;
&lt;br /&gt;
*msgDialog_msgCommand &amp;lt;command&amp;gt;: Befehl zum Versenden einer Nachricht. Die Vorgabe ist &amp;quot;msg push \@$recipients $message&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== ROOMMATE / GUEST ===&lt;br /&gt;
Für jeden Dialog kann festgelegt werden welche Person 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 fhemMsgRcvPush ein Event erzeugt. Siehe auch Attribut &amp;quot;allowed&amp;quot; in msgDialog.&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;
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;
&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;
=== 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;
=== 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;
=== 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 ==&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;
== JABBER ==&lt;br /&gt;
Hier wird die Verwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Verwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23119</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23119"/>
		<updated>2017-10-31T09:27:49Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* msgConfig */&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=h&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
== Konfiguration ==&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;
=== Hinweis zu den Code Beispielen ===&lt;br /&gt;
Es handelt sich bei den Beispielen um eine Raw definition, siehe auch [[Import_von_Code_Snippets]]&lt;br /&gt;
&lt;br /&gt;
=== msgConfig ===&lt;br /&gt;
&lt;br /&gt;
Als erstes 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;
* msgDialog_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. Wenn der selbe Name im msgConfig und msgDialog definiert wurde, wird der Wert aus msgDialog verwendet.&lt;br /&gt;
&lt;br /&gt;
*msgDialog_msgCommand &amp;lt;command&amp;gt;: Befehl zum Versenden einer Nachricht. Die Vorgabe ist &amp;quot;msg push \@$recipients $message&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== ROOMMATE / GUEST ===&lt;br /&gt;
Für jeden Dialog kann festgelegt werden welche Person 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 fhemMsgRcvPush ein Event erzeugt.&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;
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;
&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;
=== 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;
=== 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;
=== 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 ==&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;
== JABBER ==&lt;br /&gt;
Hier wird die Verwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Verwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23118</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23118"/>
		<updated>2017-10-31T09:27:34Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* msgConfig */&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=h&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
== Konfiguration ==&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;
=== Hinweis zu den Code Beispielen ===&lt;br /&gt;
Es handelt sich bei den Beispielen um eine Raw definition, siehe auch [[Import_von_Code_Snippets]]&lt;br /&gt;
&lt;br /&gt;
=== msgConfig ===&lt;br /&gt;
&lt;br /&gt;
Als erstes 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;
* msgDialog_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. Wenn der selbe Name im msgConfig und msgDialog definiert wurde, wird der Wert aus msgDialog verwendet.&lt;br /&gt;
&lt;br /&gt;
*msgDialog_msgCommand &amp;lt;command&amp;gt;:&lt;br /&gt;
Befehl zum Versenden einer Nachricht. Die Vorgabe ist &amp;quot;msg push \@$recipients $message&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== ROOMMATE / GUEST ===&lt;br /&gt;
Für jeden Dialog kann festgelegt werden welche Person 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 fhemMsgRcvPush ein Event erzeugt.&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;
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;
&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;
=== 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;
=== 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;
=== 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 ==&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;
== JABBER ==&lt;br /&gt;
Hier wird die Verwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Verwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23117</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23117"/>
		<updated>2017-10-31T09:26:37Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* msgConfig */&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=h&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
== Konfiguration ==&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;
=== Hinweis zu den Code Beispielen ===&lt;br /&gt;
Es handelt sich bei den Beispielen um eine Raw definition, siehe auch [[Import_von_Code_Snippets]]&lt;br /&gt;
&lt;br /&gt;
=== msgConfig ===&lt;br /&gt;
&lt;br /&gt;
Als erstes 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;
* msgDialog_evalSpecials:&lt;br /&gt;
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. Wenn der selbe Name im msgConfig und msgDialog definiert wurde, wird der Wert aus msgDialog verwendet.&lt;br /&gt;
&lt;br /&gt;
*msgDialog_msgCommand &amp;lt;command&amp;gt;:&lt;br /&gt;
Befehl zum Versenden einer Nachricht. Die Vorgabe ist &amp;quot;msg push \@$recipients $message&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== ROOMMATE / GUEST ===&lt;br /&gt;
Für jeden Dialog kann festgelegt werden welche Person 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 fhemMsgRcvPush ein Event erzeugt.&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;
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;
&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;
=== 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;
=== 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;
=== 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 ==&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;
== JABBER ==&lt;br /&gt;
Hier wird die Verwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Verwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23116</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23116"/>
		<updated>2017-10-31T09:20:09Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* ROOMMATE / GUEST */&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=h&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
== Konfiguration ==&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;
=== Hinweis zu den Code Beispielen ===&lt;br /&gt;
Es handelt sich bei den Beispielen um eine Raw definition, siehe auch [[Import_von_Code_Snippets]]&lt;br /&gt;
&lt;br /&gt;
=== msgConfig ===&lt;br /&gt;
&lt;br /&gt;
Als erstes 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;
=== ROOMMATE / GUEST ===&lt;br /&gt;
Für jeden Dialog kann festgelegt werden welche Person 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 fhemMsgRcvPush ein Event erzeugt.&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;
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;
&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;
=== 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;
=== 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;
=== 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 ==&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;
== JABBER ==&lt;br /&gt;
Hier wird die Verwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Verwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23115</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23115"/>
		<updated>2017-10-31T09:03:47Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* TelegramBot: Inline Keyboard verwenden */&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=h&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
== Konfiguration ==&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;
=== Hinweis zu den Code Beispielen ===&lt;br /&gt;
Es handelt sich bei den Beispielen um eine Raw definition, siehe auch [[Import_von_Code_Snippets]]&lt;br /&gt;
&lt;br /&gt;
=== msgConfig ===&lt;br /&gt;
&lt;br /&gt;
Als erstes 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;
=== ROOMMATE / GUEST ===&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;
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;
&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;
=== 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;
=== 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;
=== 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 ==&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;
== JABBER ==&lt;br /&gt;
Hier wird die Verwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Verwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23114</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23114"/>
		<updated>2017-10-31T09:02:49Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* JABBER */&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=h&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
== Konfiguration ==&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;
=== Hinweis zu den Code Beispielen ===&lt;br /&gt;
Es handelt sich bei den Beispielen um eine Raw definition, siehe auch [[Import_von_Code_Snippets]]&lt;br /&gt;
&lt;br /&gt;
=== msgConfig ===&lt;br /&gt;
&lt;br /&gt;
Als erstes 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;
=== ROOMMATE / GUEST ===&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;
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;
&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;
=== 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;
=== 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;
=== 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;
== JABBER ==&lt;br /&gt;
Hier wird die Verwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Verwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23113</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23113"/>
		<updated>2017-10-31T09:02:32Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* WhatsApp */&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=h&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
== Konfiguration ==&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;
=== Hinweis zu den Code Beispielen ===&lt;br /&gt;
Es handelt sich bei den Beispielen um eine Raw definition, siehe auch [[Import_von_Code_Snippets]]&lt;br /&gt;
&lt;br /&gt;
=== msgConfig ===&lt;br /&gt;
&lt;br /&gt;
Als erstes 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;
=== ROOMMATE / GUEST ===&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;
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;
&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;
=== 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;
=== 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;
=== 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;
== JABBER ==&lt;br /&gt;
Hier wird die Vewrwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Verwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23112</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23112"/>
		<updated>2017-10-31T09:02:12Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: &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=h&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
== Konfiguration ==&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;
=== Hinweis zu den Code Beispielen ===&lt;br /&gt;
Es handelt sich bei den Beispielen um eine Raw definition, siehe auch [[Import_von_Code_Snippets]]&lt;br /&gt;
&lt;br /&gt;
=== msgConfig ===&lt;br /&gt;
&lt;br /&gt;
Als erstes 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;
=== ROOMMATE / GUEST ===&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;
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;
&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;
=== 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;
=== 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;
=== 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;
== JABBER ==&lt;br /&gt;
Hier wird die Vewrwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Vewrwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23111</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23111"/>
		<updated>2017-10-31T09:01:39Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: &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=h&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
=== Hinweis zu den Code Beispielen ===&lt;br /&gt;
Es handelt sich bei den Beispielen um eine Raw definition, siehe auch [[Import_von_Code_Snippets]]&lt;br /&gt;
&lt;br /&gt;
=== msgConfig ===&lt;br /&gt;
&lt;br /&gt;
Als erstes 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;
=== ROOMMATE / GUEST ===&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;
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;
&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;
=== 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;
=== 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;
=== 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;
== JABBER ==&lt;br /&gt;
Hier wird die Vewrwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Vewrwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23110</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23110"/>
		<updated>2017-10-31T08:57:34Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: &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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
=== msgConfig ===&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;
=== ROOMMATE / GUEST ===&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;
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;
&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;
=== 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;
=== 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;
=== 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;
== JABBER ==&lt;br /&gt;
Hier wird die Vewrwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Vewrwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23109</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23109"/>
		<updated>2017-10-31T08:26:53Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* WHatsApp */&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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
=== msgConfig ===&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;
=== ROOMMATE / GUEST ===&lt;br /&gt;
&lt;br /&gt;
=== DEFINE ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;
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;
&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;
=== 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;
=== 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;
=== 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;
== JABBER ==&lt;br /&gt;
Hier wird die Vewrwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WhatsApp ==&lt;br /&gt;
Hier wird die Vewrwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23108</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23108"/>
		<updated>2017-10-31T08:26:31Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: &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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
=== msgConfig ===&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;
=== ROOMMATE / GUEST ===&lt;br /&gt;
&lt;br /&gt;
=== DEFINE ===&lt;br /&gt;
&lt;br /&gt;
Definition des metaDialogs:&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;
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;
&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;
=== 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;
=== 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;
=== 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;
== JABBER ==&lt;br /&gt;
Hier wird die Vewrwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WHatsApp ==&lt;br /&gt;
Hier wird die Vewrwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23107</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23107"/>
		<updated>2017-10-31T08:23:25Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: &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;
Ein zentrale Anforderung an die Haus-Automation ist die Kommunikation mit den Anwendern. Fast jeder Anwender möchte über bestimmte Ereignisse informiert werden und Einstellungen vornehmen. FHEM bietet schon seit längerem die Unterstützung für verschiedene Messaging Dienste an.&lt;br /&gt;
Mit dem msgDialog Modul können vordefinierte Dialoge erstellt werden. Die Kommunikation erfolgt dabei über den [[msg]] Befehl welcher zurzeit die bidirektionale Kommunikation über [[TelegramBot]], [[Jabber]] und [[yowsup]] (WhatsApp) unterstützt. Eingehende Nachrichten werden einem ROMMATE oder GUEST zugeordnet. Darüber werden auch die Berechtigungen für die einzelnen Dialoge festgelegt.&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;
=== msgConfig ===&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;
=== ROOMMATE / GUEST ===&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;
=== DEFINE ===&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;
&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;
=== 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;
=== 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;
=== 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;
== JABBER ==&lt;br /&gt;
Hier wird die Vewrwendung mit Jabber beschrieben...&lt;br /&gt;
&lt;br /&gt;
== WHatsApp ==&lt;br /&gt;
Hier wird die Vewrwendung mit yowsup/WhatsApp beschrieben...&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:Hilfsmodul]]&lt;/div&gt;</summary>
		<author><name>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23036</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23036"/>
		<updated>2017-10-23T13:32:56Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* TelegramBot: Inline Keyboard verwenden */&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 ROOMATE ===&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>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23034</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23034"/>
		<updated>2017-10-23T13:28:02Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* TelegramBot: Inline Keyboard verwenden */&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 ROOMATE ===&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;
Hier noch ein kleines notify, welches über einen dummy geschaltet werden kann:&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>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23033</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23033"/>
		<updated>2017-10-23T13:22:24Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: &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 ROOMATE ===&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]]  [[Datei:76msgDialog menu inline.PNG]]&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;
Hier noch ein kleines notify, welches über einen dummy geschaltet werden kann:&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>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23032</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23032"/>
		<updated>2017-10-23T13:07:24Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: &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 ROOMATE ===&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 true gestellt wird kann der Dialog an dieser Stelle nicht durch eingehnde Nachrichten ausgelöst werden, sondern nur über &amp;quot;get &amp;lt;name&amp;gt; say TRIGGER&amp;quot;.&lt;br /&gt;
Dies kann dazu genutzt werden um einen Dialog von FHEM zu aus zu initieren.&lt;br /&gt;
&lt;br /&gt;
*commands: Kann einen einzelnen oder mehrere Befehle enthalten:&lt;br /&gt;
&amp;quot;commands&amp;quot;: &amp;quot;single command&amp;quot;&lt;br /&gt;
&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;
&lt;br /&gt;
*message: Kann einen einzelnen oder mehrere Textte enthalten die mit einen Zeilenumbruch verbunden werden:&lt;br /&gt;
&amp;quot;message&amp;quot;: &amp;quot;text&amp;quot;&lt;br /&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;
&lt;br /&gt;
Bei mehrstufigen Dialogen wird diese Struktur ineinander verschachtelt angegeben.&lt;br /&gt;
&lt;br /&gt;
Es werden Variablen und unter dem Attribut evalSpecials definierte Platzhalter 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 TRIGGERN um den aktuellen Zustand des Dialogs zu sichern. Für jeden Dialogpartner wird ein Readings 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]]  [[Datei:76msgDialog menu inline.PNG]]&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;
Hier noch ein kleines notify, welches über einen dummy geschaltet werden kann:&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>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23031</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23031"/>
		<updated>2017-10-23T12:52:25Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* Hinweise */&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 ROOMATE ===&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;
== 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]]  [[Datei:76msgDialog menu inline.PNG]]&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;
Hier noch ein kleines notify, welches über einen dummy geschaltet werden kann:&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>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23013</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=23013"/>
		<updated>2017-10-22T06:59:16Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* TelegramBot: Inline Keyboard verwenden */&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;
&#039;&#039;&#039;Telegram:&#039;&#039;&#039; 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;
&#039;&#039;&#039;Jabber:&#039;&#039;&#039; 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;
&#039;&#039;&#039;WhatsApp (yowsup):&#039;&#039;&#039; Bisher konnten noch keine Erfahrungen gemacht werden.&lt;br /&gt;
&lt;br /&gt;
=== msgDialog und ROOMATE ===&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;
== 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]]  [[Datei:76msgDialog menu inline.PNG]]&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;
Hier noch ein kleines notify, welches über einen dummy geschaltet werden kann:&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>Binford6000</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=22997</id>
		<title>MsgDialog</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=MsgDialog&amp;diff=22997"/>
		<updated>2017-10-20T16:13:05Z</updated>

		<summary type="html">&lt;p&gt;Binford6000: /* Zielsetzung */&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;
&#039;&#039;&#039;Telegram:&#039;&#039;&#039; 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;
&#039;&#039;&#039;Jabber:&#039;&#039;&#039; 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;
&#039;&#039;&#039;WhatsApp (yowsup):&#039;&#039;&#039; Bisher konnten noch keine Erfahrungen gemacht werden.&lt;br /&gt;
&lt;br /&gt;
=== msgDialog und ROOMATE ===&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;
== 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]]  [[Datei:76msgDialog menu inline.PNG]]&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;
&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>Binford6000</name></author>
	</entry>
</feed>