<?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=Drhirn</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=Drhirn"/>
	<link rel="alternate" type="text/html" href="http://wiki.fhem.de/wiki/Spezial:Beitr%C3%A4ge/Drhirn"/>
	<updated>2026-04-09T10:50:46Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.43.6</generator>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Signalbot&amp;diff=40547</id>
		<title>Signalbot</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Signalbot&amp;diff=40547"/>
		<updated>2025-12-14T16:06:57Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: /* Troubleshooting / FAQ */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=Senden und Empfangen von Nachrichten (Text und Fotos) mit dem freien Messenger Signal&lt;br /&gt;
|ModType=d&lt;br /&gt;
|ModForumArea=Unterstützende Dienste&lt;br /&gt;
|ModFTopic=118370&lt;br /&gt;
|ModTechName=50_Signalbot.pm&lt;br /&gt;
|ModOwner=Adimarantis ({{Link2FU|39402|Forum}}/[[Benutzer Diskussion:Adimarantis‎|Wiki]])}}&lt;br /&gt;
Das Modul [[Signalbot]] ermöglicht den Versand von Nachrichten über den Instant-Messaging-Dienst [https://signal.org Signal] aus FHEM heraus.&lt;br /&gt;
&lt;br /&gt;
== Beschreibung ==&lt;br /&gt;
Beschreibung in Kurzform:&lt;br /&gt;
&lt;br /&gt;
Signalbot stellt eine Schnittstelle von FHEM zum Signal Messenger unter Linux zur Verfügung. Dazu wird das Tool [https://github.com/AsamK/signal-cli signal-cli] im DBus-Daemon Modus verwendet, welches dann letztendlich mit Signal kommuniziert.&lt;br /&gt;
&lt;br /&gt;
Aktuell unterstützte Funktionen aus FHEM:&lt;br /&gt;
* Senden und Empfangen von Nachrichten an Gruppen oder Einzelempfänger&lt;br /&gt;
* Versenden von einem oder mehreren Attachments (Bilder) sowie Plots von SVG und DOIF&lt;br /&gt;
* Einlesen, Speichern und Übersetzen von Gruppennamen (statt base64 Strings)&lt;br /&gt;
* Setzen, Empfangen und Übersetzen von Kontaktnamen (statt Telefonnummern)&lt;br /&gt;
* Einschränken von Gruppen oder Kontakten, auf die FHEM reagieren soll&lt;br /&gt;
* Direkte Verknüpfung mit dem [[Modul Babble|Babble]] Modul zur Interpretation von Befehlen&lt;br /&gt;
* Authentifizierte Befehle an FHEM senden ({{Link2CmdRef|Anker=GoogleAuth}}) mit Favoriten&lt;br /&gt;
* Blockieren von Kontakten und Gruppen&lt;br /&gt;
* Verwalten und Betreten/Verlassen von Gruppen&lt;br /&gt;
&lt;br /&gt;
* Registrierung von neuen Nummern inklusive Hilfestellung für Captchas&lt;br /&gt;
* Linken von bestehenden Accounts zu FHEM&lt;br /&gt;
Die Installation von signal-cli ist aktuell je nach Linux Kenntnissen durchaus anspruchsvoll. Daher gibt es ein Installationsscript welches für aktuelle Ubuntu und Raspian Distributionen getestet ist (höchstwahrscheinlich aber auch für andere Debian basierte Distributionen funktioniert).&lt;br /&gt;
&lt;br /&gt;
Signalbot ist weitgehend kompatibel mit SiSi, verfolgt aber technisch ein paar andere Ansätze und stellt zusätzliche Funktionalitäten zur Verfügung:&lt;br /&gt;
* Signalbot erzeugt keinen eigenen Prozess sondern integriert sich voll in die laufende FHEM Instanz (ist dadurch hoffentlich stabiler und verbraucht auch weniger Speicher)&lt;br /&gt;
* Gruppen werden grundsätzlich mit ihren Klarnamen verwendet und können auch nur mit einem vorangestellten &amp;quot;#&amp;quot; (statt &amp;quot;@#&amp;quot;) gekennzeichnet werden.&lt;br /&gt;
* Kontakte werden soweit möglich auch mit Klarnamen (statt +49....) unterstützt. Diese kommen aus dem internen Adressbuch und können über &amp;quot;setContact&amp;quot; definiert werden, bzw. kommen bei verlinkten Accounts aus dem Adressbuch des Hauptgeräts. &lt;br /&gt;
* Die Möglichkeit von SVG oder DOIF Plots zu versenden (mit &amp;amp; wie bei anderen Anhängen, Details in den Beispielen) &lt;br /&gt;
* Wurde mit und für die aktuelle Version von signal-cli entwickelt, die auch die neuen &amp;quot;V2&amp;quot; Gruppen unterstützt, ebenso wird die neuste Version vom Perl Modul Protocol::DBus (aktuell 0.22) benötigt&lt;br /&gt;
* Wird aktiv (Januar 2024) gewartet (letztes Update für SiSi auf github ist von August 2018)&lt;br /&gt;
&lt;br /&gt;
=== &amp;quot;set&amp;quot; Funktionen im Detail ===&lt;br /&gt;
&lt;br /&gt;
==== send [@&amp;lt;Recipient1&amp;gt; ... @&amp;lt;RecipientN&amp;gt;] [#&amp;lt;Group1&amp;gt; ... #&amp;lt;GroupN&amp;gt;] [&amp;amp;&amp;lt;Attachment1&amp;gt;; ... &amp;amp;&amp;lt;AttachmentN&amp;gt;] [&amp;lt;Text&amp;gt;] ====&lt;br /&gt;
* &#039;&#039;&#039;Recipient:&#039;&#039;&#039; Nummer mit Ländervorwahl (+49....) oder Kontaktname aus dem internen Adressbuch&lt;br /&gt;
* &#039;&#039;&#039;Group:&#039;&#039;&#039; Gruppenname, wie in Signal definiert im Klartext&lt;br /&gt;
* &#039;&#039;&#039;Attachment&#039;&#039;&#039;: Dateiname (Pfad für muss für fhem lesbar und absolut oder relativ zum fhem home sein) oder Stream einer Bilddatei (z.B.)SVG&lt;br /&gt;
* &#039;&#039;&#039;Text:&#039;&#039;&#039; Die eigentlich Textnachricht, kann Leerzeichen und Umbrüche (mit &amp;quot;\n&amp;quot; oder \0x0a) enthalten&lt;br /&gt;
* Sofern ein Recipient, Group oder Attachment Leerzeichen enthält, den ganzen Teilstring in Anführungszeichen setzen: z.B. &amp;quot;@Max Mustermann&amp;quot;&lt;br /&gt;
* Wenn ein FHEM Befehl ausgeführt werden soll, dann diesen in runde Klammern setzen z.B. &amp;amp;({plotAsPng(&#039;SVG_Aussentemperatur&#039;)})&lt;br /&gt;
&lt;br /&gt;
Ein paar Beispiele &lt;br /&gt;
  send @+498514711 Hallo Signal&lt;br /&gt;
  send #FHEM &amp;amp;/tmp/foto.jpg                             Ein Bild schicken&lt;br /&gt;
  send &amp;quot;@Mein Freund&amp;quot;                                   Leerzeichen durch Anführungszeichen um den ganzen Teilbefehl&lt;br /&gt;
  send @Joerg #FHEM #Familie                            Jeder Empfänger, jede Gruppe und Attachments können mehrfach vorkommen&lt;br /&gt;
  send &amp;quot;@({my $var=\&amp;quot;Joerg\&amp;quot;;; return $var;;})&amp;quot;         Perl Code mit Leerzeichen ausführen&lt;br /&gt;
  send @(define dummy1 dummy)                           FHEM Befehl ausführen, wird aber nicht gesendet, da kein gültiger Empfänger zurück geliefert wird&lt;br /&gt;
  send @Joerg &amp;amp;({plotAsPng(\&#039;SVG_Aussentemperatur\&#039;)})  Einen FHEM SVG Plot verschicken oder&lt;br /&gt;
  send @Joerg &amp;quot;&amp;amp;({plotAsPng(&#039;SVG_Aussentemperatur&#039;)})&amp;quot;  so - oder&lt;br /&gt;
  send @Joerg &amp;amp;SVG_Aussentemperatur                     so - oder&lt;br /&gt;
  send @Joerg &amp;quot;&amp;amp;SVG_Aussentemperatur,day,-1&amp;quot;            SVG Plot vom voherigen Tag&lt;br /&gt;
  send @Joerg &amp;amp;DI_uitable                               Sende erstes Widget aus einem DOIF mit definiertem uiTable&lt;br /&gt;
  send @Joerg &amp;quot;&amp;amp;DI_uitable,dev=outtemp,state&amp;quot;           Sende erstes Widget dass Werte aus der Device &amp;quot;outtemp&amp;quot; verwendet aus definiertem uiState &lt;br /&gt;
  send @Joerg Mehrzeilige Ausgabe:\nNeue Zeile&lt;br /&gt;
  send @Joerg Umlaute öäü und Emojis 🙃😆🤗🤑🤪 sowie 𝐅𝐨𝐫𝐦𝐚𝐭𝐢𝐞𝐫𝐮𝐧𝐠𝐞𝐧 direkt senden oder&lt;br /&gt;
  send @Joerg &amp;lt;nowiki&amp;gt;&amp;lt;b&amp;gt;Fetter&amp;lt;/b&amp;gt;&amp;lt;/nowiki&amp;gt; Text und Emojis :) :smile: - siehe get helpUnicode für Details&lt;br /&gt;
  send @Joerg Die Aussentemperatur ist [out_temp:temperature] Grad&lt;br /&gt;
&#039;&#039;&#039;Tipp zu den Formatierungen&#039;&#039;&#039;: Auf z.B. https://yaytext.com/ kann man sich seine UTF8 Kodierungen erstellen und nach FHEM per copy&amp;amp;paste einfügen. Vorrausetzung dürfte sein, dass die &amp;quot;locale&amp;quot; des Systems auf UTF8 eingestellt ist&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Signalbot bietet in den Device Details eine &amp;quot;send message&amp;quot; Zeile um bequem Nachrichten zu versenden. Hier gibt es jedoch durch das Webinterface einige Einschränkungen, z.B. in der Verwendung von Anführungszeichen. Für komplexere Nachrichten, daher möglichst &amp;quot;set send&amp;quot; verwenden.&lt;br /&gt;
&lt;br /&gt;
===== Details zum Versenden von Plots =====&lt;br /&gt;
Seit Signalbot V3.5 wird eine vereinfachte Form der Versendung von SVG Plots und sogar von DOIF uiTable Widgets unterstützt (siehe [[DOIF/uiTable Schnelleinstieg]]). Entspricht der mit &amp;quot;&amp;amp;&amp;quot; übergebene Anhang einem FHEM Device, und ist dies vom Typ SVG oder DOIF, wird dies besonders behandelt.&lt;br /&gt;
&lt;br /&gt;
Für SVG wird die Funktion &amp;quot;plotAsPng&amp;quot; dann intern aufgerufen. Es können dabei mit Komma getrennt noch der &amp;quot;Zoom&amp;quot; und das &amp;quot;Offset&amp;quot; angegeben werden, als &#039;&#039;&amp;quot;&amp;amp;SVG_Device,Zoom,Offset&amp;quot;&#039;&#039;. Es wird empfohlen den Term in Anführungszeichen zu setzen, das z.B. DOIF die Kommas sonst als FHEM Befehlstrenner interpretiert. Zoom ändert nicht die Größe! Diese bitte ggf. im SVG Device anpassen.&lt;br /&gt;
&lt;br /&gt;
Erlaubte Werte für Zoom: hour, qday, day, week, month, year, 10years, 20years&lt;br /&gt;
&lt;br /&gt;
Offset dürfte üblicherweise eine negative Zahl sein, und gibt an wie oft man zurückblättert (Zoom gibt dabei die Einheit an).&lt;br /&gt;
&lt;br /&gt;
Die Unterstützung der DOIF Widgets verwendet einige Internas von DOIF und daher kann die Kompatibilität mit zukünftigen DOIF Versionen leider nicht garantiert werden. Falls es nach einem DOIF update nicht mehr funktioniert, bitte in Forum posten. Widgets werden primär aus dem Attribut uiTable genommen, ist dies nicht vorhanden, oder wird der Parameter &amp;quot;state&amp;quot; angeben, schaut Signalbot auch in uiState nach. Eine spezielle Fehlerbehandlung gibt es derzeit nicht, sondern es kommt nur die Meldung, dass die Datei nicht gefunden wurde.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Syntax&#039;&#039;&#039;: &#039;&#039;&amp;quot;&amp;amp;DI_device,param1=wert1,param2=wert2&amp;quot; -&#039;&#039; die Verwendung von Anführungszeichen ist bei der Verwendung innerhalb eines DOIF nötig, das die Kommas sonst als Befehlstrenner interpretiert werden.&lt;br /&gt;
&lt;br /&gt;
Mögliche Parameter:&lt;br /&gt;
* id : Sequentielle Nummer des Widgets welches angezeigt werden soll. Dabei zählen auch seperate Beschriftungen. &amp;quot;id=&amp;quot; kann auch weggelassen werden und nur die Zahl angegeben werden. &amp;quot;id&amp;quot; hat Vorrang vor &amp;quot;dev&amp;quot; oder &amp;quot;val&amp;quot;&lt;br /&gt;
* dev : Identifiziert das Widget über das FHEM Device aus welchem das Widget seine Daten holt. Ist dies nicht eindeutig, wird das Erste in der Liste verwendet - kann mit &amp;quot;val&amp;quot; kombiniert werden&lt;br /&gt;
* val : dentifiziert das Widget über das FHEM Reading aus welchem das Widget seine Daten holt. Ist dies nicht eindeutig, wird das Erste in der Liste verwendet - kann mit &amp;quot;dev&amp;quot; kombiniert werden&lt;br /&gt;
* zoom: Zoomfaktor bei der SVG-&amp;gt;PNG Umwandlung. Dies ändert nicht die Größe des Bildes so dass ggf. Teile abgeschnitten werden.&lt;br /&gt;
* sizex / sizey: Ändert die Größe des Bildes, aber nicht des Widgets. Es sollten also üblicherweise zoom, sizex und sizey kombiniert werden bis das Ergebnis passt oder die Größe gleich im DOIF Widget angepasst werden.&lt;br /&gt;
* state : (ohne =) Hole die Widget Definition nicht aus uiTable sondern aus uiState&lt;br /&gt;
&#039;&#039;&#039;Achtung&#039;&#039;&#039;: Es gibt einen bekannten Fehler, dass die SVG library die &#039;&#039;&#039;Halbring&#039;&#039;&#039;-Darstellung in der uiTable card nicht verdaut und diese daher nicht verwendet werden kann&lt;br /&gt;
&lt;br /&gt;
==== setContact &amp;lt;Number&amp;gt; &amp;lt;Contactname&amp;gt; ====&lt;br /&gt;
Definiert einen Kontakteintrag im internen Adressbuch. Es kann beim &#039;&#039;&#039;send&#039;&#039;&#039; Befehl dann der &#039;&#039;ContactName&#039;&#039; statt der Nummer verwendet werden.&lt;br /&gt;
&lt;br /&gt;
==== reinit ====&lt;br /&gt;
Verbindung zum DBus wiederherstellen. Dies sollte nicht nötig sein, außer der signal-cli Service funktionierte nicht richtig und wurde korrigiert. Ich rate hier aber eher zu einem FHEM Neustart.&lt;br /&gt;
&lt;br /&gt;
==== createGroup &amp;lt;Groupname&amp;gt; [&amp;amp;&amp;lt;path to picture&amp;gt;] ====&lt;br /&gt;
Erzeugt eine neue Signalgruppe und versieht diese (optional) mit einem Gruppenbild.&lt;br /&gt;
&lt;br /&gt;
==== updateGroup &amp;lt;Groupname&amp;gt; [&amp;lt;new Groupname&amp;gt;] [&amp;amp;&amp;lt;path to picture&amp;gt;] ====&lt;br /&gt;
Aktualisiert den Namen und/oder das Gruppenbild einer Gruppe.&lt;br /&gt;
&lt;br /&gt;
==== invite &amp;lt;Groupname&amp;gt; &amp;lt;Contact1&amp;gt; [&amp;lt;Contact2&amp;gt;...] ====&lt;br /&gt;
Lädt einen oder mehrere Kontakte (per Namen oder Nummer) in eine bestehende Gruppe ein.&lt;br /&gt;
&lt;br /&gt;
==== joinGroup &amp;lt;group link&amp;gt; ====&lt;br /&gt;
Einer bestehenden Gruppe beitreten. Dazu ist eine Einladung über einen &amp;quot;group link&amp;quot; nötig, der das Format &amp;lt;nowiki&amp;gt;https://signal.group/ https://signal.group/....&amp;lt;/nowiki&amp;gt; hat. Der einfachste Weg hierzu ist es, wenn aus der Signal App die Funktion &amp;quot;group link&amp;quot; verwendet wird und der Link dann per Signal an den FHEM User gesendet wird. Sofern das &#039;&#039;autoJoin&#039;&#039; Attribut gesetzt ist, wird dieser erkannt und FHEM tritt der Gruppe automatisch bei.&lt;br /&gt;
&lt;br /&gt;
==== reply &amp;lt;message&amp;gt; ====&lt;br /&gt;
Wie &amp;quot;send&amp;quot;, nur kann der Empfänger weggelassen werden - stattdessen wird die Nachricht an den Absender der zuletzt empfangenen Nachricht gesendet&lt;br /&gt;
&lt;br /&gt;
==== trust &amp;lt;Contact|&amp;quot;all&amp;quot;&amp;gt; ====&lt;br /&gt;
Setzt den entsprechenden Kontakt - oder mit &amp;quot;all&amp;quot; alle bekannten Kontakte auf &amp;quot;TRUSTED_UNVERIFIED&amp;quot;. Dies ist manchmal nötig um von diesem Kontakt problemlos Nachrichten zu empfangen. Der Kontakt ist damit nicht vollständig verifiziert - dazu gibt es &amp;quot;trustVerified&amp;quot;. Details über den Status eines Kontakts gibt es per &amp;quot;get identityDetails&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Die Liste ist mit Kontakten vorbefüllt, die noch &amp;quot;UNTRUSTED&amp;quot; sind - steht dort nur &amp;quot;all&amp;quot; sind also alle bekannten Kontakte mindestens &amp;quot;TRUSTED_UNVERIFIED&amp;quot;. Sofern die Liste der Kontakte länger als 20 ist, ist die Nummer allerdings in ein Textfeld einzugeben, da das Dropdown sonst zu lang werden würde.&lt;br /&gt;
&lt;br /&gt;
==== trustVerified &amp;lt;Contact&amp;gt; &amp;lt;SafetyNumber&amp;gt; ====&lt;br /&gt;
Validiert einen Kontakt als &amp;quot;TRUSTED_VERIFIED&amp;quot;. Die SafetyNumber sollte üblicherweise auf einem sicheren Weg vom jeweiligen Kontakt übermittelt werden (z.B. vom persönlich vom Display abtippen oder über einen verifizierten Kommunikationskanal senden). Die Nummer ist aber symmetrisch (also für jedes Sender und Empfänger Paar gleich) und wird mit &amp;quot;get identityDetails&amp;quot; angezeigt und kann dort verglichen und dann einfach mit copy&amp;amp;paste übernommen werden. Kontakte denen voll vertraut wird, können via Signal Kommandos an FHEM senden, sofern &#039;&#039;authTrusted=yes&#039;&#039; gesetzt ist.&lt;br /&gt;
&lt;br /&gt;
==== quitGroup &amp;lt;Groupname&amp;gt; ====&lt;br /&gt;
Aus einer Gruppe austreten. Die Gruppe wird dabei lediglich auf &amp;quot;inaktiv&amp;quot; gesetzt und ist mit &#039;&#039;get groups&#039;&#039; weiterhin als solche sichtbar. Eine Möglichkeit die Gruppe komplett aus dem Profil zu löschen besteht aktuell nicht.&lt;br /&gt;
&lt;br /&gt;
==== block #&amp;lt;Groupname&amp;gt;|&amp;lt;Contact&amp;gt; ====&lt;br /&gt;
Blockiert eine Gruppe oder einen Kontakt (per Namen oder Nummer) serverseitig. Signalbot bekommt dann keine Nachrichten dieser Absender mehr (im Gegensatz zu &#039;&#039;allowedPeer&#039;&#039; bei der FHEM die Nachrichten noch bekommt, diese aber ignoriert.)&lt;br /&gt;
&lt;br /&gt;
==== unblock #&amp;lt;Groupname&amp;gt;|&amp;lt;Contact&amp;gt; ====&lt;br /&gt;
Hebt die Blockierung wieder auf.&lt;br /&gt;
&lt;br /&gt;
==== updateProfile &amp;lt;name&amp;gt; [&amp;amp;&amp;lt;Avatar picture&amp;gt;] ====&lt;br /&gt;
Setzt den Namen des Anwenders und optional ein Avatar Bild.&lt;br /&gt;
&lt;br /&gt;
=== &amp;quot;set&amp;quot; Sonderfunktionen zur Registrierung ===&lt;br /&gt;
&lt;br /&gt;
==== signalAccount &amp;lt;Telefonnummer&amp;gt; ====&lt;br /&gt;
Setzt eine bereits registrierte oder gelinkte Telefonnummer aktiv. Die bekannten Nummern werden als Pulldown zur Verfügung gestellt. Falls eine Nummer fehlen sollte, kann diese mit &amp;quot;set reinit&amp;quot; aktualisiert werden.&lt;br /&gt;
&lt;br /&gt;
Ist nur eine Telefonnummer registriert, wird diese automatisch verwendet.&lt;br /&gt;
&lt;br /&gt;
Wenn mehrere Nummern gleichzeitig verwendet werden sollen, braucht jede Nummer eine eigenen Instanz des Moduls.&lt;br /&gt;
&lt;br /&gt;
==== register &amp;lt;Telefonnummer&amp;gt; ====&lt;br /&gt;
Eine neue Nummer für Signal registrieren. Die Telefonnummer muss in Internationaler Schreibweise (+49.....) angegeben werden.&lt;br /&gt;
&lt;br /&gt;
Signalbot führt den Anwender in einer Art Wizard (Detailtexte auf der Modulseite) durch den Registrierungsprozess. Der erste Schritt ist, eine Nummer festzulegen. Üblicherweise ist das eine Festnetznummer, was die normale Verwendung der Nummer nicht beinträchtigt. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Achtung:&#039;&#039;&#039; Hier nicht die Handynummer eines Smartphones verwenden auf dem Signal schon installiert ist. Das Handy würde dadurch von Signal abgemeldet. Dazu kann &amp;quot;link&amp;quot; verwendet werden.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Wichtig:&#039;&#039;&#039; Im Laufe der Registrierung wird eine Verifikationsnummer übermittelt, normalerweise per SMS. Für Festnetznummern sollte man das aber üblicherweise auf Sprachanruf umstellen. Dazu das Attribut &amp;quot;registerMethod&amp;quot; auf &amp;quot;Voice&amp;quot; umstellen.&lt;br /&gt;
&lt;br /&gt;
Die Registrierung wird meistens durch ein Captcha geschützt. Details dazu weiter unten.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;captcha &amp;lt;signalcaptcha://.......&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Setzen des Captcha String im Rahmen der Registrierung. Details dazu, wie man den bekommt und wie der Prozess teilweise automatisiert werden kann weiter unten&lt;br /&gt;
&lt;br /&gt;
==== verify &amp;lt;Verifizierungscode&amp;gt; ====&lt;br /&gt;
Setzen des Codes, den man im Rahmen der Registrierung per SMS oder Sprachanruf übermittelt bekommen hat.&lt;br /&gt;
&lt;br /&gt;
Dies ist der letzte Schritt der Registrierung. Danach ist Signalbot einsatzbereit.&lt;br /&gt;
&lt;br /&gt;
==== link &amp;lt;Name&amp;gt; ====&lt;br /&gt;
Zeigt einen QR Code an, den man mit der Signal App auf dem Smartphone scannen kann um FHEM als &amp;quot;Mitbenutzer&amp;quot; zu registrieren. FHEM erhält dann alle Nachrichten und gesendete Nachrichten haben den Absender des Telefons. Dies ist ein einfacher und schneller Weg um Signalbot auszuprobieren, sollte aber nicht für die produktive Benutzung verwendet werden, um unerwünschte Nebeneffekte zu vermeiden. Da FHEM nicht benachrichtigt wird, wenn der &amp;quot;link&amp;quot; zustande gekomme ist, muss danach manuell ein &amp;quot;set reinit&amp;quot; durchgeführt werden.&lt;br /&gt;
&lt;br /&gt;
Der optionale Name (wenn leer wird &amp;quot;FHEM&amp;quot; verwendet) dient zur Identifizierung. &lt;br /&gt;
&lt;br /&gt;
Die angezeigte URI kann mittels &amp;quot;addDevice&amp;quot; auch dafür verwendet werden zwei FHEM Instanzen miteinander zu verküpfen, welches auf der Hauptinstanz ausgeführt wird.&lt;br /&gt;
&lt;br /&gt;
==== addDevice &amp;lt;device URI&amp;gt; ====&lt;br /&gt;
Fügt eine andere Instanz als &amp;quot;Mitbenutzer&amp;quot; hinzu. Die URI wird mit &amp;quot;set link&amp;quot; auf der anderen (nicht registrierten) FHEM Instanz erzeugt.&lt;br /&gt;
&lt;br /&gt;
Dabei ist zu beachten, dass alle Nachrichten/Befehle an beide Instanzen gehen, was bei entsprechenden Triggern zu beachten ist. Ansätze dazu sind mit &amp;quot;allowedPeer&amp;quot; auf unterschiedliche Sender zu reagieren, unterschiedliche cmdKeyWord&#039;s zu setzen etc.&lt;br /&gt;
&lt;br /&gt;
==== removeDevice &amp;lt;deviceID&amp;gt; ====&lt;br /&gt;
Entfernt einen Mitbenutzer anhand seiner deviceID. Diese kann mit &amp;quot;get devices&amp;quot; abgefragt werden. Wenn nur Mitbenutzer verlinkt ist, ist da üblicherweise &amp;quot;2&amp;quot; da &amp;quot;1&amp;quot; dem Hauptbenutzer zugeordnet wird.&lt;br /&gt;
&lt;br /&gt;
=== &amp;quot;get&amp;quot; Funktionen im Detail ===&lt;br /&gt;
&lt;br /&gt;
==== contacts all|nonblocked ====&lt;br /&gt;
Öffnet ein Fenster mit allen bekannten Kontakten mit Telefonnummer und Kontaktname sowie deren &amp;quot;blocked&amp;quot; Status. Mit dem Parameter &amp;quot;nonblocked&amp;quot; werden geblockte Kontakte ausgeblendet. Als Name wird primär der selbstdefinierte Kontaktname angezeigt. Sofern keiner definiert ist, wird der durch den Kontakt selbst definierte Profilname angezeigt. &lt;br /&gt;
&lt;br /&gt;
==== chat &amp;lt;Contact|Group&amp;gt; ====&lt;br /&gt;
Signalbot speichert eine kurze Chat Historie per Kontakt oder Gruppe die hiermit abgerufen wird. Die Gruppen sind aktuell mit &amp;quot;+&amp;quot; statt &amp;quot;#&amp;quot; gekennzeichnet, da es mit dem &amp;quot;#&amp;quot; Zeichen Probleme in der Implementierung gab. &lt;br /&gt;
&lt;br /&gt;
Die Historie wird nicht abgespeichert, ist also nach einem Neustart wieder weg und beschränkt sich auf 20 Zeilen. &lt;br /&gt;
&lt;br /&gt;
==== groups all|active|nonblocked ====&lt;br /&gt;
Öffnet ein Fenster mit allen bekannten Gruppen. Es wird der Gruppenname, der &amp;quot;Active&amp;quot; Status (ist FHEM Mitglied der Gruppe), der &amp;quot;Blocked&amp;quot; Status sowie die Liste der anderen Gruppenmitglieder angezeigt. Mit dem Parameter &amp;quot;active&amp;quot; wird die Liste auf Gruppen beschränkt, in denen FHEM Mitglied ist, mit &amp;quot;nonblocked&amp;quot; werden zusätzlich noch geblockte Gruppen ausgeblendet.&lt;br /&gt;
&lt;br /&gt;
==== accounts ====&lt;br /&gt;
Zeigt alle aktuell in signal-cli registierten Telefonnummern an, die mit &amp;quot;set signalAccount&amp;quot; verwendet werden können.&lt;br /&gt;
&lt;br /&gt;
==== devices ====&lt;br /&gt;
Zeigt alle verlinkten Mitbenutzer an. Üblicherweise hat dies nur einen Eintrag (den Hauptbenutzer = aktuelle Instanz). Die ID Nummer können mit &amp;quot;removeDevice&amp;quot; verwendet werden um Mitbenutzer zu entfernen.&lt;br /&gt;
&lt;br /&gt;
==== favorites ====&lt;br /&gt;
Listet die definierten Favoriten im Attribut &amp;quot;favorites&amp;quot; (siehe unten) in tabellarischer Form auf. Nützlich um zu prüfen ob das Attribut korrekt befüllt ist.&lt;br /&gt;
&lt;br /&gt;
==== helpUnicode ====&lt;br /&gt;
Zeigt alle unterstützten Tags zur Formattierung von Nachrichten mittels HTML oder Markdown Tags. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Achtung&#039;&#039;&#039;: Die Funktion muss über dass Attribut &#039;&#039;formatting&#039;&#039; aktiviert werden.&lt;br /&gt;
&lt;br /&gt;
==== identityDetails &amp;lt;Contact&amp;gt; ====&lt;br /&gt;
Zeigt Systemdetails zu einem Kontakt an. Neben dem vollen Namen, dem Trust Level (UNTRUSTED,TRUSTED_UNVERIFIED oder TRUSTED_VERIFIED), die SafetyNumer die mit &amp;quot;set trustVerified&amp;quot; verwendet werden kann um den TRUSTED_VERIFIED Status zu setzen, wann der Kontakt zu signal-cli hinzugefügt wurde sowie einen QR-Code der mit der Signal App gescannt werden kann um umgekehrt TRUSTED_VERIFIED für FHEM auf dem Telefon zu setzen.&lt;br /&gt;
&lt;br /&gt;
=== Attribute im Detail ===&lt;br /&gt;
==== authTimeout ====&lt;br /&gt;
Gibt bei Verwendung des {{Link2CmdRef|Anker=GoogleAuth|Label=GoogleAuth}} device die Dauer in Sekunden an, die ein Nutzer authentifiziert bleibt. Siehe &#039;&#039;commandKeyword&#039;&#039; für mehr Infos.&lt;br /&gt;
&lt;br /&gt;
==== authDev ====&lt;br /&gt;
Name des genutzten GoogleAuth device. Dies wird üblicherweise automatisch gesetzt, sofern bereits ein GoogleAuth device im System definiert ist, sobald das &#039;&#039;authTimeout&#039;&#039; gesetzt wird.&lt;br /&gt;
&lt;br /&gt;
==== authTrusted ====&lt;br /&gt;
Falls auf &amp;quot;yes&amp;quot; gesetzt, dürfen Kontakte die den Vertrauensstatus &amp;quot;TRUSTED_VERIFIED&amp;quot; haben auch ohne GoogleAuth Kommandos an FHEM senden. Da Signal z.B. mit diesem Mechanismus vor Accountübernahme, Handywechsel etc. schützt, ist die Identität des Kontakts zweifelsfrei sichergestellt und die umständliche Eingabe eines Codes von GoogleAuth kann entfallen.&lt;br /&gt;
&lt;br /&gt;
==== autoJoin 0|1 ====&lt;br /&gt;
Falls auf 1 gesetzt, reagiert FHEM automatisch auf Einladungslinks (siehe &#039;&#039;joinGroup&#039;&#039;) und tritt der Gruppe bei&lt;br /&gt;
&lt;br /&gt;
==== cmdKeyword ====&lt;br /&gt;
Eine Zeichenkette aus einem oder mehreren Zeichen, die am Anfang einer Nachricht stehen kann, damit FHEM die restliche Nachricht ungefiltert als Kommando ausführt. Die Funktion ist über GoogleAuth geschützt, d.h. ein Benutzer muss sich erst mit einem gültigen GoogleAuth Token legitimieren und bleibt entsprechend des &#039;&#039;authTimeout&#039;&#039; Attributs für gewisse Zeit authorisiert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Beispiel:&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
Man setzt &#039;&#039;cmdKeyword&#039;&#039; auf &amp;quot;=&amp;quot; , dann kann man &#039;&#039;&amp;quot;=123456 set lamp off&amp;quot;&#039;&#039; senden. Im weiteren Verlauf reicht &#039;&#039;&amp;quot;=set lamp on&amp;quot;&#039;&#039; solange bis der Timeout abgelaufen ist.&lt;br /&gt;
&lt;br /&gt;
Zur Authorisierung muss nicht zwingend gleich ein Befehl mitgesendet werden. Sofern &#039;&#039;allowedPeer&#039;&#039; gesetzt ist, muss der Absender zusätzlich in dieser Liste stehen.&lt;br /&gt;
&lt;br /&gt;
==== defaultPeer ====&lt;br /&gt;
Gruppe, Kontaktname oder Nummer an die &#039;&#039;&#039;send&#039;&#039;&#039; eine Nachricht schicken soll, wenn kein Empfänger mit @ oder # definiert wurde.&lt;br /&gt;
&lt;br /&gt;
==== allowedPeer ====&lt;br /&gt;
Komma getrennte Liste von Gruppen, Kontaktnamen oder Nummern auf die Signalbot reagieren soll (also bei empfangenen Nachrichten Readings aktualisiert). Ist dieses Attribut nicht gesetzt, reagiert Signalbot auf alle Nachrichten.&lt;br /&gt;
&lt;br /&gt;
==== babblePeer ====&lt;br /&gt;
Komma getrennte Liste von Gruppen, Kontaktnamen oder Nummern auf die Signalbot reagieren soll indem es die Nachricht an das über &#039;&#039;&#039;babbleDev&#039;&#039;&#039; (nicht zu verwechseln mit &#039;&#039;babbleDevice&#039;&#039;) definierte [[Modul Babble|Babble]] Modul schickt. Die Nachrichten werden zuerst (beschränkt auf allowedPeer) normal verarbeitet (also Readings aktualisiert) und nur nach Babble gesendet wenn diese Attribut gesetzt ist.&lt;br /&gt;
&lt;br /&gt;
Der Absender der Nachricht (Gruppe hat Prio über individuellem Absender) wird Babble als &#039;&#039;$PARM0&#039;&#039; übergeben. Dazu in Babble noch das Attribut helpFunc wie folgt setzen&lt;br /&gt;
 {fhem(&amp;quot;set SignalBot send \@$PARM0 $HELP&amp;quot;)}&lt;br /&gt;
Sollen die rivescript Spracherweiterungen genutzt werden muss außerdem &amp;quot;noChatbot&amp;quot; auf 0 stehen.&lt;br /&gt;
&lt;br /&gt;
Nach dem selben Prinzip können in der Babble Definition auch Antworten spezfisch für Devices angelegt werden, z.B. als Aktion für out-temp -&amp;gt; Temperatur -&amp;gt; draußen -&amp;gt; sagen -&amp;gt; Status:&lt;br /&gt;
 set SignalBot send @$PARM0 Die Temperatur draußen ist [out_temp:temperature] Grad&lt;br /&gt;
Womit die Frage (ohne Fragezeichen!) &amp;quot;Wie ist die Temperatur draußen&amp;quot; entsprechend quittiert wird.&lt;br /&gt;
&lt;br /&gt;
==== babbleDev ====&lt;br /&gt;
Name des definierten Babble Device.Wird beim Setzen vom babblePeer automatisch mit der ersten &amp;quot;Babble&amp;quot; Device gefüllt sofern vorhanden.&lt;br /&gt;
&lt;br /&gt;
==== babbleExclude ====&lt;br /&gt;
Regulärer Ausdruck auf den Nachrichtentext um bestimmte Nachrichten von der Weiterleitung zu Babble auszuschließen (ein Event wird trotzdem generiert und kann mit Notify, DOIF etc. verarbeitet werden).&lt;br /&gt;
&lt;br /&gt;
==== registerMethod &amp;lt;SMS|Voice&amp;gt; ====&lt;br /&gt;
Stellt die Registrierungsmethode (Rückmeldung des Verifizierungscodes) auf SMS oder Sprachanruf um.&lt;br /&gt;
&lt;br /&gt;
==== cmdFavorites ====&lt;br /&gt;
Definiert eine Zeichensequenz die bei remote Befehlen (siehe &#039;&#039;cmdKeyword&#039;&#039;) als Favorit interpretiert wird. Details siehe unter &#039;&#039;favorites&#039;&#039;. Da Favoriten vor FHEM Befehlen ausgewertet werden, sollte z.B. &amp;quot;set&amp;quot; nicht verwendet werden.&lt;br /&gt;
&lt;br /&gt;
==== formatting &amp;lt;none|html|markdown|both&amp;gt; ====&lt;br /&gt;
Aktiviert die Ersetzung von html-ähnlichen Formatierungen (z.B. &amp;lt;nowiki&amp;gt;&amp;lt;b&amp;gt;bold text&amp;lt;/b&amp;gt;&amp;lt;/nowiki&amp;gt;) und/oder Markdown (z.B. __italic text__) um diese direkt in ASCII angeben zu können, anstatt nur per copy&amp;amp;paste.&lt;br /&gt;
&lt;br /&gt;
Die komplette Liste von Tags/Ersetzungen kann über die &#039;&#039;get helpUnicode&#039;&#039; Funktion direkt im Model angezeigt werden.&lt;br /&gt;
&lt;br /&gt;
==== favorites &amp;lt;[alias1]&amp;gt;&amp;lt;-&amp;gt;&amp;lt;command1&amp;gt;;&amp;lt;[alias2]&amp;gt;&amp;lt;-&amp;gt;&amp;lt;command2&amp;gt;;.... ====&lt;br /&gt;
Definiert Favoriten um remote Befehle (siehe &#039;&#039;cmdKeyword&#039;&#039;) abzukürzen.&lt;br /&gt;
&lt;br /&gt;
Einträge werden durch Semikolon getrennt und automatisch durchnummeriert.&lt;br /&gt;
&lt;br /&gt;
Optional kann in eckigen Klammern &amp;quot;[]&amp;quot; ein alias angebenben werden, sowie ebenfalls optional dem Befehle ein Minuszeichen &amp;quot;-&amp;quot; vorangestellt werden, womit für diesen Befehl keine vorherige GoogleAuth Authentifizierung zu erfolgen hat.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Wichtig:&#039;&#039;&#039; Favoriten funktionieren nur wenn &#039;&#039;cmdKeyword, cmdFavorites, authTimeout, authDev&#039;&#039; und &#039;&#039;favorites&#039;&#039; gesetzt sind.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiele&#039;&#039;&#039; (angenommen cmdKeyword=&amp;quot;/&amp;quot; , cmdFavorites=&amp;quot;fav&amp;quot;, favorites=&amp;quot;set lamp on;[off]set lamp off;[hi]-set talk say Jemand zuhause&amp;quot;):&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Befehl&lt;br /&gt;
!Effekt&lt;br /&gt;
|-&lt;br /&gt;
|/fav 1&lt;br /&gt;
|Fehler weil nicht authentifiziert&lt;br /&gt;
|-&lt;br /&gt;
|/fav 3&lt;br /&gt;
|&amp;quot;set talk&amp;quot; Befehl wird ausgeführt, da &amp;quot;-&amp;quot; Befehle ohne Authentifizierung funktionieren&lt;br /&gt;
|-&lt;br /&gt;
|/fav hi&lt;br /&gt;
|&amp;quot;set talk&amp;quot; Befehl wird ausgeführt&lt;br /&gt;
|-&lt;br /&gt;
|/123456&lt;br /&gt;
|GoogleAuth Token setzen um remote Befehle freizuschalten&lt;br /&gt;
|-&lt;br /&gt;
|/fav 1&lt;br /&gt;
|&amp;quot;set lamp on&amp;quot; wird ausgeführt&lt;br /&gt;
|-&lt;br /&gt;
|/fav off&lt;br /&gt;
|&amp;quot;set lamp off&amp;quot; wird ausgeführt&lt;br /&gt;
|-&lt;br /&gt;
|/fav&lt;br /&gt;
|Liste all Favoriten mit IDs wird ausgegeben&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Readings im Detail ===&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|account&lt;br /&gt;
|Aktuell verwendete Telefonnummer (nur verfügbar wenn signal-cli 0.9.0 ohne -u Parameter gestartet wurde)&lt;br /&gt;
|-&lt;br /&gt;
|joinedGroups&lt;br /&gt;
|Liste der beigetretenen Gruppen getrennt mit Leerzeichen&lt;br /&gt;
|-&lt;br /&gt;
|lastError&lt;br /&gt;
|Text der letzten Fehlermeldung. Bitte unbedingt den Timestamp beachten. Das Reading wird bei erfolgreichen Aktionen nicht zurückgesetzt und enthält ggf. sehr alte Fehlermeldungen.&lt;br /&gt;
|-&lt;br /&gt;
|msgAttachment&lt;br /&gt;
|Attachments (Dateinamen im signal-cli repository) der zuletzt empfangenen Attachments&lt;br /&gt;
|-&lt;br /&gt;
|msgGroupName&lt;br /&gt;
|Gruppenname aus der zuletzt eine Nachricht empfangen wurde - leer wenn es eine persönlich Nachricht war&lt;br /&gt;
|-&lt;br /&gt;
|msgSender&lt;br /&gt;
|Absender der letzten Nachricht als Nummer oder wenn bekannt als Name&lt;br /&gt;
|-&lt;br /&gt;
|msgText&lt;br /&gt;
|Empfangenen Nachricht&lt;br /&gt;
|-&lt;br /&gt;
|msgTimestamp&lt;br /&gt;
|Zeitstempel der Nachricht&lt;br /&gt;
|-&lt;br /&gt;
|msgAuth&lt;br /&gt;
|Ist auf 1 gesetzt wenn der Absender der aktuellen Nachricht (also zum Zeitpunkt zu dem z.B. ein Notify/DOIF die Nachricht auswertet) per GoogleAuth authentifiziert war.&lt;br /&gt;
|-&lt;br /&gt;
|prevMsgAttachment&lt;br /&gt;
| rowspan=&amp;quot;5&amp;quot; |Wie oben, nur enthalten diese Readings die Daten der zuvor empfangenen Nachricht (n-1)&lt;br /&gt;
|-&lt;br /&gt;
|prevMsgGroupName&lt;br /&gt;
|-&lt;br /&gt;
|prevMsgSender&lt;br /&gt;
|-&lt;br /&gt;
|prevMsgText&lt;br /&gt;
|-&lt;br /&gt;
|prevMsgTimestamp&lt;br /&gt;
|-&lt;br /&gt;
|sentMsg&lt;br /&gt;
|Zuletzt gesendete Nachricht&lt;br /&gt;
|-&lt;br /&gt;
|sentMsgRecipient&lt;br /&gt;
|Empfänger der zuletzt gesendeten Nachricht. Enthält zumeist den Namen aus der Empfangsbestätigung und somit bei vielen Empfängern den zuletzt bestätigten Empfang.&lt;br /&gt;
&lt;br /&gt;
Dies muss nicht zwingend auf die zuletzt gesendete Nachricht (sendMsg) passen, wenn mehrere Nachrichten versendet wurden.&lt;br /&gt;
|-&lt;br /&gt;
|sentMsgTimestamp&lt;br /&gt;
|Zeitstempel des Empfangs oder &amp;quot;pending&amp;quot; wenn noch keine Bestätigung vorliegt&lt;br /&gt;
|-&lt;br /&gt;
|VERSION&lt;br /&gt;
|Internal Reading die die aktuelle Version von Signalbot, signal-cli und Dbus angibt - vor Support Anfragen bitte erst im Forum prüfen ob die aktuellste Version verwendet wird und ggf. updaten.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Installation ==&lt;br /&gt;
Zur Installation steht das Script &amp;quot;signal_install.sh&amp;quot; zur Verfügung, welches aber nicht zwangsweise in jeder Umgebung funktioniert. Daher erst einmal ein paar Referenzen zur manuellen Installation von signal-cli:&lt;br /&gt;
* Quickstart (englisch) für [https://github.com/AsamK/signal-cli/wiki/Quickstart signal-cli]&lt;br /&gt;
* Anleitung zum [https://github.com/AsamK/signal-cli/wiki/Provide-native-lib-for-libsignal#libsignal-client Übersetzen und Installieren der Libraries] für armv7 (Raspberry) da die Distribution nur x86 libraries enthält&lt;br /&gt;
* CPAN Seite des Perl Moduls zur [https://metacpan.org/pod/Protocol::DBus DBus Kommunikation]&lt;br /&gt;
Vorbereitung:&lt;br /&gt;
&lt;br /&gt;
Das Script &amp;quot;signal_install.sh&amp;quot; aus der Detailseite des Moduls oder vom [https://svn.fhem.de/fhem/trunk/fhem/contrib/signal/ FHEM SVN] runterladen und ins Verzeichnis eines beliebigen &amp;quot;sudo&amp;quot;-fähigen Users kopieren.&lt;br /&gt;
&lt;br /&gt;
Das Script hat mehrere Optionen um Teilfunktionen direkt auszuführen, diese sind:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Argument&lt;br /&gt;
!Bedeutung&lt;br /&gt;
|-&lt;br /&gt;
|system&lt;br /&gt;
|System für die signal-cli Installation vorbereiten. Es werden per &amp;quot;apt install&amp;quot; fehlende Pakete installiert und Verzeichnisse erstellt. &lt;br /&gt;
Muss mindestens einmal erfolgreich gelaufen sein, damit die restliche Installation funktioniert&lt;br /&gt;
|-&lt;br /&gt;
|install&lt;br /&gt;
|Installiert signal-cli als System Service. Automatischer Download, Installation und Konfiguration (dbus, systemd)&lt;br /&gt;
|-&lt;br /&gt;
|test&lt;br /&gt;
|Versendet eine Testnachricht auf zwei Arten - direkt mit dem Client (klappt das, ist die Grundregistrierung schon mal erfolgreich) und über Dbus (dann ist auch der System Service korrekt eingerichtet)&lt;br /&gt;
|-&lt;br /&gt;
|remove&lt;br /&gt;
|Löscht alle durch &amp;quot;install&amp;quot; installierten Verzeichnisse und Dateien (aber nicht die Pakete die durch &amp;quot;system&amp;quot; installiert wurden)&lt;br /&gt;
|-&lt;br /&gt;
|start&lt;br /&gt;
|Starten des singal service über systemd bzw. im Container des Dbus daemon and signal-cli Daemon&lt;br /&gt;
|-&lt;br /&gt;
|backup&lt;br /&gt;
|Erstellt ein Archiv aller relevanten Scripts und Einstellungen (z.B. für einen System Umzug) in der Datei signal-backup.tar.gz&lt;br /&gt;
|-&lt;br /&gt;
|restore&lt;br /&gt;
|Schreibt die Archive Datei signal-backup.tar.gz ins System zurück&lt;br /&gt;
|}&lt;br /&gt;
Im Normalfall kann das script einfach unter root Rechten, also mit&lt;br /&gt;
 sudo -E ./signal_install.sh&lt;br /&gt;
aufgerufen werden (wenn das Script per Download geholt wurde, muss es vorher noch mit &amp;quot;chmod a+x signal_install.sh&amp;quot; ausführbar gemacht werden). Wenn kein Argument übergeben wird, dann wird automatisch der Ablauf &#039;&#039;system -&amp;gt; install -&amp;gt; test&#039;&#039; durchlaufen.&lt;br /&gt;
&lt;br /&gt;
Wenn Betriebssystem oder CPU Architektur nicht unterstützt werden, gibt es eine Warnung bzw. das Script bricht ab.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Es prüft außerdem ab, ob es im Container läuft. Dieser Modus ist nur dafür gedacht, wenn mein FHEM/Signal Container Script verwendet wurde. In anderen Container Umgebungen wird es üblicherweise nicht funktionieren. Details dazu weiter unten.&lt;br /&gt;
&lt;br /&gt;
Dann Modul per &#039;&#039;&#039;&amp;quot;define &amp;lt;name&amp;gt; Signalbot&amp;quot;&#039;&#039;&#039; definieren.&lt;br /&gt;
&lt;br /&gt;
=== Registrierung ===&lt;br /&gt;
Die Registrierung wird ab Version 3.0 nicht mehr im Script sondern in FHEM selbst geführt durchgeführt.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Eine Nummer kann immer nur &#039;&#039;&#039;einmal&#039;&#039;&#039; registriert sein. Eine bereits bestehende Registrierung (Smartphone) wird dabei &#039;&#039;&#039;aufgehoben&#039;&#039;&#039;. Daher entweder eine Festnetznummer verwenden mit der Option &amp;quot;link&amp;quot; FHEM als Zweitbenutzer zu einer bestehenden Nummer hinzugefügen. Dies ist zum Testen ok, aber produktiv ist davon abzuraten, da FHEM dann alle Mitteilungen bekommt die man am Handy auch kriegt, was zu unerwarteten Nebeneffekten führen kann.&lt;br /&gt;
&lt;br /&gt;
Die Registrierung erfolgt mit &amp;quot;set register &amp;lt;nummer&amp;gt;&amp;quot; (Telefonnummer in internationaler Schreibweise mit +49....).&lt;br /&gt;
&lt;br /&gt;
Nach erfolgter Registrierung bekommt man je nach Wert des Attributs &amp;quot;registerMethod&amp;quot; eine SMS oder einen Sprachanruf mit einer Verifikationsnummer.&lt;br /&gt;
&lt;br /&gt;
Signal versucht sich gegen unberechtigte Nutzung des Service (man könnte ja damit quasi SMS/Telefonterror betreiben) zu schützen. Nach gewissen Kriterien (soweit bekannt z.B. Registrierung aus einer VM oder über VPN) wird daher ein Captcha verlangt.&lt;br /&gt;
&lt;br /&gt;
FHEM führt hierbei durch den Prozess mit Hilfestellungen&lt;br /&gt;
&lt;br /&gt;
Ablauf:&lt;br /&gt;
# [https://signalcaptchas.org/registration/generate.html Captcha Seite] von Signal aufrufen. Link ist auch direkt in FHEM verfügbar&lt;br /&gt;
# Nach erfolgreichem Lösen des Captchas erscheint ein Link &amp;quot;Signal öffnen&amp;quot; bzw. unter Windows besteht eine Automatisierungsoption (siehe unten)&lt;br /&gt;
# Üblicherweiser (Browserspezifisch) kann hier mit Rechtsklick und &amp;quot;Adresse des Links kopieren&amp;quot; das &amp;quot;signalcaptcha&amp;quot; kopiert werden&lt;br /&gt;
# Diesen String dann im &amp;quot;set captcha&amp;quot; Befehl eintragen und dann sollte die Registrierung weitergehen (SMS/Anruf)&lt;br /&gt;
#* SMS: Hier sollte relativ zeitnah eine SMS mit einem 6-stelligen Code übermittelt werden&lt;br /&gt;
#* Voice: Die Registrierung per Sprachanruf ist mit einigen Hürden versehen. Man muss erst mit SMS registrieren, 1 Minute warten, dann mit Voice. Ab Signalbot V3.19 wird dieser Vorgang automatisiert. Dauert aber durch die zwingende Wartezeit von 1 Minute ein wenig.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Captcha &amp;quot;Automatisierung&amp;quot;:&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
Am einfachsten ist die Registrierung wenn sich von Windows aus mit FHEM verbindet. Hier stellt Signalbot ein Windows Registry File (signalcaptcha.reg) zum Download zur Verfügung. Dieses einfach runterladen und per Doppelklick in die Registry eintragen.&lt;br /&gt;
&lt;br /&gt;
Wenn jetzt die Signal Captcha Seite besucht wird, wird nach Bestätigung ein Powershell Script welches einfach wieder FHEM mit der entsprechenden &amp;quot;set captcha&amp;quot; Befehl automatisch ausführt.&lt;br /&gt;
&lt;br /&gt;
Für Linux habe ich aktuell nur eine Lösung für Firefox. Hier die signalcaptcha.desktop runterladen und nach &#039;&#039;~/.local/share/applications/signalcaptcha.desktop&#039;&#039; kopieren und mit &#039;&#039;xdg-mime default signalcaptcha.desktop x-scheme-handler/signalcaptcha&#039;&#039; (alles mit dem Desktop User) aktivieren. Dann sollte ebenfalls automatisch FHEM aufgerufen werden.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Wichtig:&#039;&#039;&#039; Wenn csrf-Tokens nicht abgeschaltet sind, werden diese bei jedem FHEM Neustart neu erzeugt, womit man auch neue .reg/.desktop Dateien benötigt (set reinit, neuer Download)&lt;br /&gt;
&lt;br /&gt;
==== Verifizierung ====&lt;br /&gt;
Zuletzt wird mit &amp;quot;set verify&amp;quot; der Verifizierungscode eingetragen und die Registrierung ist damit abgeschlossen.&lt;br /&gt;
&lt;br /&gt;
=== Bestehende Nummer verlinken ===&lt;br /&gt;
Alternativ kann man auch eine bestehende Nummer verlinken. Dazu &amp;quot;set link&amp;quot; aufrufen. Es wird jetzt ein QR-Code auf dem Bildschirm angezeigt. In der Signal App dann auf Settings-&amp;gt;Linked Devices gehen und mit &amp;quot;+&amp;quot; den QR-Code abfotografieren.&lt;br /&gt;
&lt;br /&gt;
Bitte beachten, dass bei verlinkten Devices immer alle Devices (also auch das Smartphone) Nachrichten bekommen. Bei reinem Sendebetrieb dürfte das weniger stören, soll aber auch auf Befehle reagiert werden, dann ist das eventuell verwirrend.&lt;br /&gt;
&lt;br /&gt;
== Einrichtung des Moduls ==&lt;br /&gt;
Siehe Forenthema {{Link2Forum|Topic=118370|LinkText=Neues Modul: Signalbot}}.&lt;br /&gt;
&lt;br /&gt;
Nachdem alles sauber eingerichtet ist und das Modul im FHEM Directory abgelegt wurde, entweder ein &amp;quot;reload 50_Signalbot&amp;quot; oder besser ein &amp;quot;shutdown restart&amp;quot; von FHEM machen.&lt;br /&gt;
&lt;br /&gt;
Das Modul dann einfach mit&lt;br /&gt;
 define &amp;lt;name&amp;gt; Signalbot&lt;br /&gt;
definiert.&lt;br /&gt;
&lt;br /&gt;
== Umstieg von SiSi ==&lt;br /&gt;
Da SiSi eine inzwischen sehr alte &#039;&#039;&#039;signal-cli&#039;&#039;&#039; Version verwendet, die sehr wahrscheinlich nicht mehr voll abwärtskompatibel ist, wird von einer einfachen Migration abgeraten.&lt;br /&gt;
&lt;br /&gt;
Die Installation und Neuregistrierung der Nummer ist inzwischen soweit vereinfacht worden, dass diese Vorgehensweise weniger aufwändig ist.&lt;br /&gt;
&lt;br /&gt;
Ohne Garantie, dass dies mit der aktuellen signal-cli/Signalbot Version noch funktioniert hier trotzdem die potentielle Migration:&lt;br /&gt;
&lt;br /&gt;
Signalbot allerdings eine andere Dbus Implementierung (Protocol::DBus), diese muss erst installiert werden:&lt;br /&gt;
:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;cpan install -f Protocol::DBus&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Sofern nach dem SiSi Wiki vorgegangen wurde, dann sind folgende Anpassungen im Script notwendig:&lt;br /&gt;
 SIGNALPATH=/opt/fhem&lt;br /&gt;
 SIGNALUSER=fhem&lt;br /&gt;
 SIGNALVAR=/opt/fhem/.local/share&lt;br /&gt;
Das Verzeichnis /opt/fhem/signal-cli kann gelöscht werden.&lt;br /&gt;
&lt;br /&gt;
Wenn mein Installationsschema übernommen werden soll, dann&lt;br /&gt;
 sudo mv /opt/fhem/.local/share/signal-cli /var/lib&lt;br /&gt;
&lt;br /&gt;
Jetzt kann das Script einfach wie oben beschrieben gestartet werden.&lt;br /&gt;
&lt;br /&gt;
=== Umzug auf ein neues System ===&lt;br /&gt;
Dazu einfach das Script mit dem Argument &amp;quot;backup&amp;quot; starten. Die alte Konfiguration wird dabei im Home Verzeichnis des aktuellen Benutzers als &#039;&#039;~/signal-backup.tar.gz&#039;&#039; gesichert.&lt;br /&gt;
&lt;br /&gt;
auf dem neuen System dann diese Datei wieder ins Home und entsprechend das Script mit &amp;quot;restore&amp;quot; laufen lassen.&lt;br /&gt;
== Eigene native Library übersetzen ==&lt;br /&gt;
Signal-cli ist zwar überwiegend in Java geschrieben, hat aber leider eine binäre Library die zwingend benötigt wird. Ohne diese startet der Service nicht.&lt;br /&gt;
&lt;br /&gt;
Der Installler lädt automatisch die korrekte Library für unterstützte Architekturen und ersetzt die am64/glibc-2.31 die von signal-cli standardmäßig mitgeliefert wird. Unterstützt werden aktuell:&lt;br /&gt;
* Raspberry (armv7l) für Buster (glibc2.28) und Bullseye (glibc2.31)&lt;br /&gt;
* Raspberry 64-bit (aarch64) für glibc2.28 (ungetestet, sollte für Buster und Bullseye funktionieren)&lt;br /&gt;
* AMD/Intel 64-bit (amd64) für glibc2.28 und glibc2.31 (Ubuntu 18,20,22, Debian 10,11 u.a.)&lt;br /&gt;
Es gibt mehrere github Projekte um signal-cli die auch fertig übersetzte libsignal_jni.so im Angebot haben (einfach mal suchen). Man kann sich die Library aber auch selbst übersetzen.&lt;br /&gt;
&lt;br /&gt;
Ich gehe dabei davon aus, dass eine (wenn auch inkompatible) Installation von signal-cli bereits erfolgt ist und z.B. alle Java libraries an Ort und Stelle sind.&lt;br /&gt;
&lt;br /&gt;
Es werden eine Reihe von Programmen benötigt. Diese Liste ist möglicherweise nicht vollständig, je nachdem wie eurer System konfiguriert ist:&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt-install git build-essential clang cmake openjdk-17-jdk-headless&lt;br /&gt;
sudo curl https://sh.rustup.rs -sSf | sh&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Es ist hier wichtig, dass die libsignal-client in der Version passt, daher in der signal-cli Installation checken&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
ls /opt/signal/lib/libsignal-client*&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Und die Versionsnummer notieren (für signal-cli 0.11.3 ist das 0.20.0)&lt;br /&gt;
&lt;br /&gt;
Jetzt entsprechend auschecken&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
git clone git@github.com:signalapp/libsignal-client.git&lt;br /&gt;
cd libsignal-client&lt;br /&gt;
git checkout v0.20.0&lt;br /&gt;
cd java&lt;br /&gt;
./build_jni.sh desktop&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&#039;&#039;libsignal_jni.so&#039;&#039; aus &#039;&#039;target/release/&#039;&#039; nach &#039;&#039;/opt/signal/lib&#039;&#039; kopieren&lt;br /&gt;
&lt;br /&gt;
Libraries in den Java .jar Files durch die selbst compilierten ersetzen:&amp;lt;syntaxhighlight lang=&amp;quot;shell&amp;quot;&amp;gt;&lt;br /&gt;
cd /opt/signal/lib&lt;br /&gt;
sudo -u signal-cli zip -u signal-client-java-*.jar libsignal_jni.so&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Dann Service neu starten&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;sudo service signal start&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn alles richtig funktioniert hat, sollte der Service jetzt laufen (syslog prüfen, oder &#039;&#039;ps -ef | grep signal-cli )&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Installation im Docker Container  ==&lt;br /&gt;
Um signal-cli in einem Docker Container zu installieren stellt sich die Schwierigkeit, dass man dort nicht so einfach Dienste per systemd starten kann und die Kommunikation zum System Dbus schwierig ist. Dies wird in durch die spezielle Docker Installation umgangen, indem der dbus-daemon dort eigens gestartet wird und signal-cli per script in den Hintergrund gestartet wird.&lt;br /&gt;
&lt;br /&gt;
Unter Verwendung [https://svn.fhem.de/fhem/trunk/fhem/contrib/signal/fhem_signal_docker_install.sh dieses Scripts] wird eine komplette FHEM Basisinstallation per Docker erstellt und dort signal-cli eingerichtet.&lt;br /&gt;
&lt;br /&gt;
==== Funktionsweise: ====&lt;br /&gt;
Das Script erstellt alle notwendigen Dateien in einem User Verzeichnis (default: $HOME/fhem) und installiert dort auch in &amp;quot;fhem-&amp;lt;version&amp;gt;&amp;quot; die aktuelle FHEM Version sowie ein Verzeichnis &amp;quot;signal&amp;quot; für die Registrierungsdaten. Diese sind somit persistent außerhalb des Containers und können auch von außen überschrieben werden.&lt;br /&gt;
&lt;br /&gt;
Wer bereits eine Signal Registrierung einer normalen Installation hat, kann diese von /var/lib/signal-cli in dieses &amp;quot;signal&amp;quot; Verzeichnis kopieren, so das sie verwendet wird.&lt;br /&gt;
&lt;br /&gt;
Das Script muss mit &amp;quot;sudo&amp;quot; ausgeführt werden und hat noch die Option &amp;quot;remove&amp;quot; alle Dockerdateien die es erzeugt auch wieder zu entfernen. FHEM bleibt dabei unangetastet.&lt;br /&gt;
&lt;br /&gt;
Bei einer erneuten Erstellung des Containers (z.B. um package updates oder eine neue signal-cli Version einzuspielen) kann man wählen FHEM nicht neu zu installieren womit es danach genauso konfiguriert wieder gestartet wird.&lt;br /&gt;
&lt;br /&gt;
Der Container wird basierend auf einem aktuellen Ubuntu Image erzeugt (aktuelle Ubuntu 20.04). Falls in FHEM Module verwendet werden, müssen oft weiteren Pakete (über apt, cpan oder npm) installiert werden. Im Installscript finden sich hier auskommentiert ein paar Hinweise wie für einige gängige Module (bzw. eben welche die ich verwende) die entsprechenden Abhängigkeiten mit eingebunden werden können.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Achtung:&#039;&#039;&#039; Das Ganze ist experimentell und für eine einmalige Installation/Start gebaut. Wenn fhem, signal-cli oder der dbus-daemon im Docker beendet werden, dann muss man diese evtl. selbst wieder nachstarten. Das kann man sicher noch einiges verbessern. Sinnvollerweise nimmt man die erzeugten Config Dateien und Scripte eher als Anregung für eine eigene Konfiguration. Verbesserungsvorschläge gerne auch im Forum.&lt;br /&gt;
&lt;br /&gt;
== Versenden von Nachrichten ohne FHEM ==&lt;br /&gt;
Falls jemand auch aus Shell Scripten heraus Signal Nachrichten versenden möchte, kann die FHEM signal-cli Installation am einfachsten über den &amp;quot;dbus-send&amp;quot; Befehl mitverwendet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;dbus-send --system --type=method_call --print-reply --dest=org.asamk.Signal /org/asamk/Signal/_xxxxxx org.asamk.Signal.sendMessage string:Hallo array:string: string:+49yyyy&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;/org/asamk/Signal/_xxxxxx&#039;&#039; entspricht hier der registrierten Nummer und steht in FHEM Signalbot im Status (&amp;quot;connected to ...&amp;quot;). Dabei wird das &amp;quot;+&amp;quot; in der Nummer durch &amp;quot;_&amp;quot; ersetzt.&lt;br /&gt;
&lt;br /&gt;
Wichtig ist bei Dbus Nachrichten nicht nur der Name der Methode (sendMessage) sondern auch Typ und Reihenfolge der Parameter. Für &#039;&#039;sendMessage&#039;&#039; heisst das:&lt;br /&gt;
# Die eigentliche Nachricht als String&lt;br /&gt;
# Ein Array von Strings die Attachments enthalten (da man dies von der Kommandozeile eher nicht machen wird, erzeugt &#039;&#039;array:string&#039;&#039; hier einen leeren Parameter)&lt;br /&gt;
# Die Telefonnummer der Empfängers als String&lt;br /&gt;
Grundsätzlich kann man so alle Dbus Methoden von signal-cli ansteuern, welche unter https://github.com/AsamK/signal-cli/blob/master/man/signal-cli-dbus.5.adoc dokumentiert sind.&lt;br /&gt;
&lt;br /&gt;
Einige Dinge sind aber nicht so komfortabel, z.B. kann man Gruppen nicht per Namen, sondern nur über einen langen base64-kodierten String ansteuern - hier übernimmst SignalBot eine benutzerfreundliche Übersetzung.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Alternative ist dann einfach einen FHEM Befehl abzusetzen - z.B. per &#039;&#039;telnet&#039;&#039; Kommando.&lt;br /&gt;
&lt;br /&gt;
Alternativ geht es auch direkt über den signal-cli client. Dafür muss aber vorher der service beendet sein (Konflikt):&lt;br /&gt;
 sudo service signal stop &lt;br /&gt;
 sudo -E -u signal-cli /opt/signal/bin/signal-cli -c /var/lib/signal-cli -u +49&amp;lt;registrierte Nummer&amp;gt; send -m &amp;quot;testmessage&amp;quot; +49&amp;lt;Empfänger&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Fernsteuerung und Authentifizierung ==&lt;br /&gt;
Signalbot ermöglicht es FHEM über Signal fernzusteuern und dies auch abzusichern.&lt;br /&gt;
&lt;br /&gt;
Um die Fernsteuerung zu aktivieren muss zuerst über das Attribut &amp;quot;cmdKeyword&amp;quot; festgelegt werden, woran Signalbot erkennen soll, dass es sich um einen Befehl handelt. In dieser Dokumentation gehe ich jetzt davon aus das &amp;quot;/&amp;quot; als Keyword gesetzt ist. Das Keyword kann auch mehrere Zeichen lang sein.&lt;br /&gt;
&lt;br /&gt;
Sendet man jetzt &amp;quot;/set lamp on&amp;quot; an Signalbot, so führt dieser das entsprechende set Kommando direkt aus.&lt;br /&gt;
&lt;br /&gt;
Dies ist natürlich sicherheitstechnisch ein offenes Scheunentor und es gibt mehrere Methoden der Absicherung&lt;br /&gt;
&lt;br /&gt;
==== Attribut allowedPeer ====&lt;br /&gt;
Dieses Attribut enthält eine Komma-getrennte Liste von Nummer, Kontakt- oder Gruppennamen welche als gültige Absender akzeptiert werden. Ist es nicht gesetzt kann jeder mit Signalbot kommunizieren und Kommandos senden oder Events triggern&lt;br /&gt;
&lt;br /&gt;
==== GoogleAuth ====&lt;br /&gt;
Vorrausetzung ist, dass man in FHEM ein GoogleAuth Device angelegt hat und entsprechend auch die App auf dem Telefon. Näheres in der Commandref.&lt;br /&gt;
&lt;br /&gt;
Über das Attribut &amp;quot;authDev&amp;quot; kann die GoogleAuth Device zugewiesen werden. Üblicherweise ist dies nicht erforderlich, da SignalBot dieses in System sucht und das Attribut automatisch setzt.&lt;br /&gt;
&lt;br /&gt;
Um die Prüfung per GoogleAuth zu aktivieren wird das Attribut &amp;quot;authTimeout&amp;quot; (in Sekunden) gesetzt, welches definiert wie lange eine erfolgreiche Authentifierung gültig bleibt.&lt;br /&gt;
&lt;br /&gt;
Wenn jetzt Befehle an FHEM gesendet werden, quittiert Signalbot diese mit &amp;quot;You are not authorized to execute commands&amp;quot;. Zur Authentifizierung wird einfach die 6-stellige Nummer aus dem Google Authenticator mit vorangestelltem Keyword an FHEM gesendet, also z.B. &amp;quot;/123456&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Man erhält die Meldung, dass man nur für gewisse Zeit (authTimeout) authentifiziert ist und kann Kommandos senden.&lt;br /&gt;
&lt;br /&gt;
==== Trust ====&lt;br /&gt;
Signal hat eine eigene Funktionalität um Kommunikationspartner zu überprüfen und Ihnen das Vertrauen auszusprechend. Siehe dazu &amp;quot;set trust&amp;quot; und &amp;quot;set trustVerified&amp;quot;. Da die Authentifizierung per GoogleAuth auf Dauer lästig sein kann, besteht die Möglichkeit diese für verifizierte vertraute Nutzer zu umgehen. Dazu wird das Attribut &amp;quot;authTrusted&amp;quot; auf &amp;quot;yes&amp;quot; gesetzt. Nutzer denen nicht voll vertraut wird, müssen sich weiter authentifzieren.&lt;br /&gt;
&lt;br /&gt;
====== Favoriten ======&lt;br /&gt;
Der Vollständigkeit halber sei hier noch erwähnt, dass man Befehlskürzel per Favoriten definieren kann. Details dazu in der Beschreibung der set Befehle und Attribute.&lt;br /&gt;
&lt;br /&gt;
Per Attribut &amp;quot;cmdFavorite&amp;quot; wird festgelegt welches Keyword die Favoritenauswahl triggert. Das könnte z.B. auch &amp;quot;/&amp;quot; sein, so dass &amp;quot;// 1&amp;quot; den ersten Favoriten triggert. Dass Attribute &amp;quot;favorites&amp;quot; enhält dann die eigentliche Definition der Favoritenliste.&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting / FAQ ==&lt;br /&gt;
Anmerkung: Ich gehe hier davon aus, dass die Installation mit den im Script voreingestellten Pfaden/Users durchgeführt wurde. Änderungen auf eigene Gefahr.&lt;br /&gt;
&lt;br /&gt;
Bevor ich hier ein paar typische Probleme und Lösungen aus dem Foren Thread aufliste, bitte folgende Punkte sicherstellen:&lt;br /&gt;
# Ich verwende eine unterstütztes Betriebssystem (Raspbian oder Ubuntu) und CPU Architektur (armv7l oder x86)&lt;br /&gt;
# Ich habe das neuste Install Script aus https://svn.fhem.de/fhem/trunk/fhem/contrib/signal/ verwendet&lt;br /&gt;
# Ich habe vor der Installation nach besten Wissen und Gewissen Reste einer vorherigen Installation (z.B. auch für SiSi) entfernt (das Repository kann weggesichert werden um eine erneute Registrierung zu vermeiden und dann statt dem Registrierungsschritt in /var/lib/signal-cli kopiert werden&lt;br /&gt;
# Ich habe das Install Script gemäß Anleitung vollständig durchlaufen lassen und auf Fehlermeldungen geachtet&lt;br /&gt;
&lt;br /&gt;
==== Wo finde ich Fehlermeldungen/Logfiles? ====&lt;br /&gt;
* Beim Install Script direkt in der Console - achte auf die Bildschirmausgabe&lt;br /&gt;
* Beim Install Script auch in &#039;&#039;/tmp/signal_install.log&#039;&#039; - ggf. wegsichern da es bei jedem Durchlauf wieder überschrieben wird.&lt;br /&gt;
* Fehler beim Starten und Betrieb des signal-cli service (normale Installation) in /var/log/syslog&lt;br /&gt;
* Fehler beim Betrieb in FHEM im normalen FHEM log (ggf. Signalbot mit verbose=5 definieren)&lt;br /&gt;
* Im Container, sofern die Daemons mit dem Install Script gestartet wurden, schreiben ihr log in /var/log/dbus.log bzw. signal.log und die Fehlerausgabe in /var/log/dbus.err bzw. signal.err&lt;br /&gt;
&lt;br /&gt;
==== Probleme bei normaler Installation ====&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
!Fehler&lt;br /&gt;
!Lösungsansatz&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;In FHEM:&#039;&#039;&#039;&lt;br /&gt;
Error sending message:org.asamk.Signal.Error.Failure: org.whispersystems.signalservice.api.push.exceptions.NotFoundException: Not found&lt;br /&gt;
|signal-cli läuft nicht.&lt;br /&gt;
Prüfe ggf. &#039;&#039;&#039;/var/log/syslog&#039;&#039;&#039; für weitere Fehlermeldungen.&lt;br /&gt;
&lt;br /&gt;
Führe &#039;&#039;&#039;sudo service signal start&#039;&#039;&#039; aus.&lt;br /&gt;
|-&lt;br /&gt;
|signal-cli läuft nach reboot oder restart nicht, aber ein manueller Start ist erfolgreich. &lt;br /&gt;
&amp;lt;code&amp;gt;sudo systemctl status dbus-org.asamk.Signal.service&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
meldet einen timeout&lt;br /&gt;
|Möglicherweise dauert das Starten von signal-cli länger als der standard 90sec Timeout des systemd (langsames System, langsame SD-Karte bei Raspberry, viele gleichzeitiger Startprozesse bei Reboot).&lt;br /&gt;
&lt;br /&gt;
Hier kann man in &#039;&#039;/etc/systemd/system/signal.service&#039;&#039; den Timeout erhöhen indem in der Sektion &#039;&#039;[Service]&#039;&#039; die Zeile&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;TimeoutSec=200&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
eingefügt wird.&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Bei Starten von signal-cli:&#039;&#039;&#039;&lt;br /&gt;
OpenJDK Server VM warning: You have loaded library /tmp/resource17792002454964883349.so which might have disabled stack guard. The VM will try to fix the stack guard now.&lt;br /&gt;
&lt;br /&gt;
It&#039;s highly recommended that you fix the library with &#039;execstack -c &amp;lt;libfile&amp;gt;&#039;, or link it with &#039;-z noexecstack&#039;.&lt;br /&gt;
&lt;br /&gt;
oder&lt;br /&gt;
&lt;br /&gt;
ERROR App - Missing required native library dependency: libsignal-client&lt;br /&gt;
|Passiert üblicherweise auf dem &#039;&#039;&#039;Raspberry pi.&#039;&#039;&#039; Die Standard Distribution von signal-cli enthält eine x86 library libsignal_jni.so, die mit armv7l nicht kompatibel ist, welche im jar libsignal-client-*.jar enthalten sind. Das Install Script entfernt diese und ersetzt sie durch armv7l libraries die vom Signalbot Maintainer auf svn.fhem.de zur Verfügung gestellt werden.&lt;br /&gt;
Irgendwo auf dem System vorhandene alte Versionen können aber versehentlich erwischt werden und diese Fehler produzieren. Als ersten Schritt mit&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;sudo rm -rf /opt/signal&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
die alte Installation komplett löschen (enthält keine Konfigurationen) und vom Install Script neu erstellen lassen (einfach wie oben beschrieben starten).&lt;br /&gt;
&lt;br /&gt;
Weitere Tests wenn der Fehler nicht behoben ist:&lt;br /&gt;
# Welche Library wird vom System verwendet: &#039;&#039;sudo ldconfig -v | grep libsignal_jni.so&#039;&#039; . Da die libraries in .jar files eingebettet sind, darf hier keine gefunden werden.&lt;br /&gt;
# Check gibt es noch irgendwo ein anderes jar  &amp;lt;code&amp;gt;sudo find / -name libsignal-client-*.jar 2&amp;gt;/dev/null&amp;lt;/code&amp;gt;  Wenn ja, sicherstellen, dass diese nicht genommen wird (löschen, umbenennen)&lt;br /&gt;
|-&lt;br /&gt;
|Beim Start von signal-cli:&lt;br /&gt;
Fehler: Beim Laden der Klasse org.asamk.signal.Main ist ein LinkageError aufgetreten&lt;br /&gt;
&lt;br /&gt;
java.lang.UnsupportedClassVersionError: org/asamk/signal/Main has been compiled by a more recent version of the Java Runtime (class file version 65.0), this version of the Java Runtime only recognizes class file versions up to xx.0&lt;br /&gt;
|Signal-cli benötigt seit der Version 0.13+ eine vorhandene Java 21 Installation. Ältere Systeme haben von Haus aus aber nur Java 11 oder 17.&lt;br /&gt;
Das Install Script kann hier helfen und eine Binärdistribution von OpenJDK 21 installieren und setzt JAVA_HOME im Startup des Service üblicherweise auch entsprechend.&lt;br /&gt;
&lt;br /&gt;
Wenn signal-cli allerdings in der Kommandozeile ausgeführt wird, ist darauf zu achten das JAVA_HOME=/opt/java gesetzt ist (bzw. auch die von euch gewählte Java 21 Distribution). &lt;br /&gt;
&lt;br /&gt;
Ein häufiger Fehler ist auch beim sudo das &amp;quot;-E&amp;quot; zu vergessen, denn nur so wird JAVA_HOME beim sudo &amp;quot;durchgereicht&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
|Fehler beim Setzen des Captcha: &amp;quot;Incorrect captcha - e.g. needs to start with signalcaptcha://&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
# Sicherstellen, dass das Captcha tatsächlich korrekt ist - am Besten die Automatisierung über die Windows Registry verwenden&lt;br /&gt;
# Alternativ kann die Registrierung auch in der Kommandozeile vorgenommen werden&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo service signal stop &lt;br /&gt;
&lt;br /&gt;
cd /opt/signal/bin/ &lt;br /&gt;
&lt;br /&gt;
sudo -E -u signal-cli ./signal-cli --config /var/lib/signal-cli -u +4912456 register --voice --captcha signalcaptcha://03AG.... &lt;br /&gt;
&lt;br /&gt;
sudo -E -u signal-cli ./signal-cli --config /var/lib/signal-cli -u +4912456 verify 12345&lt;br /&gt;
&lt;br /&gt;
sudo service signal start&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Fehler: &#039;&#039;Untrusted Identity for &amp;quot;+49xxxxxxx&amp;quot;&#039;&#039; beim Versenden von Nachrichten.&lt;br /&gt;
&lt;br /&gt;
Dieses Fehlerbild ist zu erwarten, wenn ein bereits bestehender Kontakt sich erneut bei Signal angemeldet hat (z.B. Handywechsel) und sich der Sicherheitscode dadurch geändert hat.&lt;br /&gt;
|Mit &amp;quot;set trust &amp;lt;Nummer&amp;gt;&amp;quot; das Vertrauen (unverified) zum Kontakt wieder herstellen.&lt;br /&gt;
Sollte das nicht reichen (Nachrichten kommen nicht an / werden nicht empfangen) siehe weiter unten &amp;quot;Ich kann Nachrichten ohne Fehler senden.....&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|Senden von Nachrichten schlägt fehl oder Nachrichten werden nicht versendet&lt;br /&gt;
|Zur Prüfung ob der Fehler in FHEM, der DBUS Konfiguration oder bei signal-cli liegt, sind im Kapitel &amp;quot;Versenden von Nachrichten ohne FHEM&amp;quot; Methoden beschrieben direkt mit Dbus oder von der Kommandozeile Nachrichten zu senden.&lt;br /&gt;
Sicherstellen, dass mit &amp;quot;updateProfile&amp;quot; ein Name für das aktuelle Profil angelegt ist, sonst werden Nachrichten möglicherweise nicht verschickt.&lt;br /&gt;
|-&lt;br /&gt;
|Signal-cli started nach &amp;quot;apt update/upgrade&amp;quot; unter Raspberry Bullseye oder Buster nicht mehr.&lt;br /&gt;
Fehlermeldungen z.B. wrong ELF class: ELFCLASS64 (Possible cause: can&#039;t load AARCH64 .so on a ARM platform)&lt;br /&gt;
&lt;br /&gt;
oder&lt;br /&gt;
&lt;br /&gt;
Fehler wenn signal-cli als service läuft im syslog:&lt;br /&gt;
&lt;br /&gt;
Caused by: org.sqlite.NativeLibraryNotFoundException: No native library found for os.name=Linux, os.arch=aarch64, paths=[/org/sqlite/native/Linux/aarch64:/usr/java/packages/lib:/lib:/usr/lib]&lt;br /&gt;
|Seit März 2023 stellt Raspian anscheinend den Kernel auf 64bit um, sofern es sich um einen neueren 64-bit fähigen Raspberry handelt. Mit dem Befehl &amp;quot;arch&amp;quot; wird dann &amp;quot;aarch64&amp;quot; statt &amp;quot;armv7l&amp;quot; ausgegeben.&lt;br /&gt;
Aktuell hilft hier nur wieder auf den 32-bit Kernel umzustellen.&lt;br /&gt;
&lt;br /&gt;
Dazu am Ende der /boot/config.txt die Zeile&lt;br /&gt;
:&amp;lt;code&amp;gt;arm_64bit=0&amp;lt;/code&amp;gt;&lt;br /&gt;
einfügen. Das Mischmasch aus 64Bit Kernel und 32Bit libraries bringt den Java loader für native libraries durcheinander. Aktuell ist dazu keine andere Lösung bekannt.&lt;br /&gt;
|-&lt;br /&gt;
|Die Registrierung schlägt fehl , z.B. mit der Fehlermeldung &amp;quot;Rate limit exceeded&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
# Ein paar Stunden warten und es dann nochmal probieren (bei Rate limit exceeded)&lt;br /&gt;
# Anderen Browser probieren - es gibt Berichte, dass Firefox nicht funktioniert - Chrome scheint hier die bessere Wahl zu sein&lt;br /&gt;
|-&lt;br /&gt;
|Ich kann Nachrichten ohne Fehler senden, diese kommen aber beim Empfänger nicht an.&lt;br /&gt;
Ich empfange keine Nachrichten, obwohl diese vom Sender korrekt abgeschickt wurden.&lt;br /&gt;
|&#039;&#039;&#039;Möglicherweise liegt es daran, dass dem Kontakt nicht vertraut wird.&#039;&#039;&#039; &lt;br /&gt;
Am Handy in die Details des FHEM Kontakts gehen, Sicherheitsnummer anzeigen und als verifiziert markieren.&lt;br /&gt;
In FHEM &amp;quot;set trustVerified&amp;quot; mit der Telefonnummer des Kontakts und dessen Sicherheitsnummer ausführen.&lt;br /&gt;
Damit man die Sicherheitsnummer nicht abtippen muss, kann man diese auch mit &amp;quot;get identityDetails&amp;quot; anzeigen lassen,  grob vergleichen und per copy&amp;amp;paste in den set Befehl übernehmen.&lt;br /&gt;
Anschliessend (möglicherweise mit etwas Verzögerung) sollte der Kontakt bei &amp;quot;get identityDetails&amp;quot; als &amp;quot;TRUSTED_VERIFIED&amp;quot; angezeigt werden.&lt;br /&gt;
|-&lt;br /&gt;
|Signal findet &amp;quot;Protocol::DBus&amp;quot; nicht mehr. &amp;quot;sudo cpan install Protocol::DBus&amp;quot; bricht mit einer Fehlermeldung ab.&lt;br /&gt;
|Passiert z.B. nach einem Upgrade des Betriebssystemes auf Debian Trixie.&amp;lt;br&amp;gt;Die Lösung ist, Protocol::DBus mit cpanminus zu installieren:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt install cpanminus&lt;br /&gt;
sudo cpanm --notest Protocol::DBus&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Links ====&lt;br /&gt;
* Thread {{Link2Forum|Topic=118370|LinkText=Neues Modul: Signalbot}}&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Signal]]&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Ble2mqtt&amp;diff=39199</id>
		<title>Ble2mqtt</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Ble2mqtt&amp;diff=39199"/>
		<updated>2024-03-24T09:11:16Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: Infobox auf Contrib geändert und Download-Link hinzugefügt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{SEITENTITEL:ble2mqtt}} &lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=Anwesenheitserkennung von Bluetooth-Geräten&lt;br /&gt;
|ModType=contrib&lt;br /&gt;
|ModFTopic=127173&lt;br /&gt;
|ModForumArea=Unterstützende Dienste&lt;br /&gt;
|ModTechName=ble2mqtt&lt;br /&gt;
|ModOwner=PatrickR&lt;br /&gt;
}}&lt;br /&gt;
[[ble2mqtt]] ist ein Script, das den Anwesenheitsstatus eines oder mehrerer Bluetooth Low Energy Geräte überprüfen und das Ergebnis an einen MQTT Broker schicken kann.&lt;br /&gt;
&lt;br /&gt;
Es verwendet dazu die Linux Tools &#039;&#039;bluetoothctl&#039;&#039; und &#039;&#039;gatttool&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
ble2mqtt ist in Perl geschrieben und wurde von {{Link2FU|5068|PatrickR}} erstellt. Weitere Informationen finden sich in diesem {{Link2Forum|Topic=127173|LinkText=Forums-Thema}}. Fragen dazu bitte in den Bereich {{Link2Forum|Area=Unterstützende Dienste}}.&lt;br /&gt;
&lt;br /&gt;
==Voraussetzungen==&lt;br /&gt;
* Debian od. Raspberry Pi OS&lt;br /&gt;
* Bluetooth Empfänger&lt;br /&gt;
&lt;br /&gt;
==Parameter==&lt;br /&gt;
Beim Start von ble2mqtt können folgende Parameter angegeben werden:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Parameter!!Beschreibung!!Standardwert!!Beispiel!!Optional&lt;br /&gt;
|-&lt;br /&gt;
| --mqttserver&lt;br /&gt;
|Die Adresse des MQTT Brokers inklusive Port&lt;br /&gt;
|&lt;br /&gt;
| --mqttserver mqtt.example.org:1883&lt;br /&gt;
|nein&lt;br /&gt;
|-&lt;br /&gt;
| --mqttfingerprint&lt;br /&gt;
|Der Fingerprint des für die TLS-verschlüsselte Kommunikation mit dem MQTT Broker verwendeten Zertifikates&lt;br /&gt;
|&lt;br /&gt;
| --mqttfingerprint bfe5d244a821194230f1479fe2f8f7bbcd2a8cb8&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --mqtttopic&lt;br /&gt;
| An welches MQTT-Topic das Tool die Informationen schicken soll.&lt;br /&gt;
|ble2mqtt&lt;br /&gt;
| --mqtttopic ble2mqtt/Wohnzimmer&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --mqttuser&lt;br /&gt;
|Der Benutzernamen, unter dem die Verbindung zum Broker hergestellt werden soll&lt;br /&gt;
|&lt;br /&gt;
| --mqttuser ble2mqtt&lt;br /&gt;
|ja bzw. abhängig vom Broker&lt;br /&gt;
|-&lt;br /&gt;
| --mqttpass&lt;br /&gt;
|Das zum Benutzernamen gehörende Passwort&lt;br /&gt;
|&lt;br /&gt;
| --mqttpass verysecret3&lt;br /&gt;
|ja bzw. abhängig vom Broker&lt;br /&gt;
|-&lt;br /&gt;
| --retain&lt;br /&gt;
|Versendet die Nachrichten present und lastseen als retained.&lt;br /&gt;
|0&lt;br /&gt;
| --retain&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --daemonize&lt;br /&gt;
|Wenn ble2mqtt im Hintergrund (als Daemon) ausgeführt werden soll&lt;br /&gt;
|0&lt;br /&gt;
| --daemonize&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --loglevel&lt;br /&gt;
|Wie und was genau protokolliert werden soll. Mögliche Loglevel sind LOG_CRIT, LOG_ERR, LOG_WARNING, LOG_NOTICE, LOG_INFO, LOG_DEBUG.&lt;br /&gt;
|LOG_INFO&lt;br /&gt;
| --loglevel LOG_ERR&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --logtarget&lt;br /&gt;
|Wohin gelogged werden soll. Mögliche Optionen sind &#039;&#039;syslog&#039;&#039; und &#039;&#039;stdout&#039;&#039;.&lt;br /&gt;
|syslog&lt;br /&gt;
| --logtarget stdout&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --absentinterval&lt;br /&gt;
|Anzahl an Sekunden, nach denen das Gerät als abwesend bezeichnet werden soll. Mindestwert ist 30.&lt;br /&gt;
|60&lt;br /&gt;
| --absentinterval 120&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --rssithreshold&lt;br /&gt;
|Ab welcher Abweichung des RSSI Wertes ein Update getriggert werden soll. Mindestwert ist 5.&lt;br /&gt;
|10&lt;br /&gt;
| --rssithreshold 8&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --watchdogthreshold&lt;br /&gt;
|Ab welchem Zeitraum in Sekunden nach Empfangen des letzten BT-Signals ble2mqtt neu gestartet werden soll. Mindestwert ist 30. Der Wert 0 bedeutet deaktiviert, also nie.&lt;br /&gt;
|0&lt;br /&gt;
| --watchdogthreshold 30&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --debug&lt;br /&gt;
|Kann nur gemeinsam mit --daemonize verwendet werden, um Logeinträge auf stdout auszugeben. Je höher die Nummer, desto mehr Output.&lt;br /&gt;
|0&lt;br /&gt;
| --daemonize --debug 4&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --mac&lt;br /&gt;
|Filtert mittels Regex nach MAC-Adressen der von ble2mqtt zu beachtenden BLE-Geräte. Alle anderen Geräte werden ignoriert.&lt;br /&gt;
|&lt;br /&gt;
| --mac &#039;(11:22:33:44:55:66|77:88:99:00:AA:BB)&#039;&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --batterymaxage&lt;br /&gt;
|Zeit in Stunden, nach denen ein Batterie-Wert als veraltet angesehen und aktualisiert wird. Der Wert 0 deaktiviert den Batterie-Check.&lt;br /&gt;
|48&lt;br /&gt;
| --batterymaxage 6&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --forcebattery&lt;br /&gt;
|Nur in Kombination mit --mac. Erzwingt einen Batterie-Check, auch wenn das battery-service am Gerät nicht erkannt wird.&lt;br /&gt;
|0&lt;br /&gt;
| --forcebattery&lt;br /&gt;
|ja&lt;br /&gt;
|}&lt;br /&gt;
===Beispiele===&lt;br /&gt;
* Broker verlangt Username/Passwort; es sollen keine Batterie-Werte ausgelesen werden&lt;br /&gt;
 ble2mqtt --mqttserver mqtt.example.org:1883 --mqttuser ble2mqtt --mqttpass verysecret3 --batterymaxage 0&lt;br /&gt;
&lt;br /&gt;
* Broker verlangt keine Authentifizierung; es soll nach zwei G-Tags gesucht werden; definiertes MQTT-Topic; Batteriewerte benötigt&lt;br /&gt;
 ble2mqtt --mqttserver mqtt.example.org:1883 --mqtttopic ble2mqtt/Wohnzimmer --mac &#039;(11:22:33:44:55:66|77:88:99:00:AA:BB)&#039;&lt;br /&gt;
&lt;br /&gt;
* Broker verlangt keine Authentifizierung; Geräte sollen nach 45s ohne Kontakt als abwesend angezeigt werden; MQTT Nachrichten sollen gespeichert bleiben&lt;br /&gt;
 ble2mqtt --mqttserver mqtt.example.org:1883 --absentinterval 45 --retain&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
Zur Installation muss das ble2mqtt-Script auf den Server kopiert werden und es müssen diverse Linux- und Perl-Pakete installiert werden. Das Script findet ihr im [https://svn.fhem.de/trac/browser/trunk/fhem/contrib/ble2mqttd Contrib-Verzeichnis] von FHEM.&lt;br /&gt;
&lt;br /&gt;
Zuerst das Script nach /usr/local/bin kopieren, um beim Aufruf in der Bash nicht immer den ganzen Pfad voranstellen zu müssen.&lt;br /&gt;
:&amp;lt;code&amp;gt;sudo cp -a ble2mqttd /usr/local/bin/&amp;lt;/code&amp;gt;&lt;br /&gt;
Danach das Script noch als ausführbar markieren&lt;br /&gt;
:&amp;lt;code&amp;gt;sudo chmod +x /usr/local/bin/ble2mqttd&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Benötigte Linux Pakete===&lt;br /&gt;
Die benötigten Pakete können ganz einfach mit &#039;&#039;apt&#039;&#039; installiert werden. Dabei werden auch mögliche Abhängigkeiten automatisch installiert.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt install -y libssl-dev libio-socket-ssl-perl libreadonly-perl libtest-expect-perl libnet-ssleay-perl libnet-server-perl&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Benötigte Perl-Module===&lt;br /&gt;
Es wird das Modul &#039;&#039;Net::MQTT::Simple&#039;&#039; (&#039;&#039;libnet-mqtt-simple-perl&#039;&#039;) benötigt. Das ist - Stand 08.11.2023 - noch nicht in den Stable-Repositories von Debian verfügbar und muss daher mittels &#039;&#039;cpan&#039;&#039; installiert werden. Voraussetzung dafür ist das Modul &#039;&#039;CPAN::DistnameInfo&#039;&#039;, welches zuerst installiert werden muss.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
 sudo cpan CPAN::DistnameInfo&lt;br /&gt;
 sudo cpan Net::MQTT::Simple&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Sobald &#039;&#039;libnet-mqtt-simple-perl&#039;&#039; verfügbar ist, kann dieses statt der Perl-Module wie ein normales Linux-Paket installiert werden.&lt;br /&gt;
&lt;br /&gt;
===Erster Test===&lt;br /&gt;
Mit einem einfachen Aufruf von &#039;&#039;&#039;ble2mqtt&#039;&#039;&#039; kann getestet werden, ob alle benötigten Module und Pakete vorhanden sind.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Bash&amp;quot;&amp;gt;&lt;br /&gt;
 sudo /usr/local/bin/ble2mqttd&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Erstellen einens Systemd-Daemons===&lt;br /&gt;
Damit &#039;&#039;&#039;ble2mqtt&#039;&#039;&#039; bei jedem Systemstart automatisch gestartet wird, muss ein Systemd-Daemon erstellt werden. Das wird gemacht, in dem eine neue Textdatei mit folgendem Inhalt angelegt und der Daemon dann aktiviert wird.&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|&#039;&#039;&#039;Wichtig:&#039;&#039;&#039; Das Kommando, mit welchen Parametern ble2mqtt gestartet wird, muss natürlich individuell angepasst werden!}}&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo nano /etc/systemd/system/ble2mqttd.service&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=ble2mqttd&lt;br /&gt;
After=bluetooth.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
Restart=always&lt;br /&gt;
ExecStart=/usr/local/bin/ble2mqttd --mqttserver mqtt.example.com:1883 --mqtttopic ble2mqtt/wohnzimmer --mac &#039;(11:22:33:44:55:66|77:88:99:00:AA:BB)&#039; --absentinterval 30 --mqttuser &amp;lt;username&amp;gt; --mqttpass &amp;lt;password&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 sudo systemctl daemon-reload&lt;br /&gt;
 sudo systemctl enable ble2mqttd.service&lt;br /&gt;
 sudo systemctl start ble2mqttd.service&lt;br /&gt;
&lt;br /&gt;
==Einbindung in FHEM==&lt;br /&gt;
Da ble2mqtt alle Informationen an einen [[MQTT]]-Broker sendet, können diese Informationen ganz einfach als [[MQTT2_DEVICE]] in FHEM eingebunden werden. Wie dabei vorgegangen werden kann, unterscheidet sich je nach Anwendungsbereich und den eigenen Vorlieben.&lt;br /&gt;
&lt;br /&gt;
Als Beispiel sie hier die Anwesenheitserkennung mittels BT-Tags angeführt.&lt;br /&gt;
&lt;br /&gt;
===Anwesenheitserkennung mittels BT-Tags===&lt;br /&gt;
[[File:ble2mqtt.png|thumb|Readings eines Devices, dass mit diesem Code erstellt wurde]]&lt;br /&gt;
Der folgende Code geht davon aus, dass es mehrere ble2mqtt-Instanzen gibt und ein BT-Tag mit der MAC-Adresse AA:BB:CC:DD:EE:FF erkannt werden soll.&lt;br /&gt;
&lt;br /&gt;
Die verschiedenen ble2mqtt-Instanzen schicken ihre Nachrichten in unterschiedliche Topics.&lt;br /&gt;
Für jede Instanz ein eigenes Topic:&lt;br /&gt;
*ble2mqtt/wohnzimmer&lt;br /&gt;
*ble2mqtt/schlafzimmer&lt;br /&gt;
*ble2mqtt/kueche&lt;br /&gt;
Im Attribut &#039;&#039;devicetopic&#039;&#039; werden diese Topics dann gemeinsam ausgewertet. Das funktioniert, in dem der Name des Subtopics einfach durch den Regex-Ausdruck &#039;&#039;.*&#039;&#039; ersetzt wird.&lt;br /&gt;
&lt;br /&gt;
Bedeutet aber auch, dass die Informationen - wenn gewünscht - wieder in unterschiedliche Readings zerlegt werden müssen. Um z.B. schnell zu erkennen, in welchem Raum der BT-Tag gerade liegt. Das passiert hier z.B. bei den Nachrichten für &#039;&#039;rssi&#039;&#039; und &#039;&#039;presence&#039;&#039;. Daraus resultieren dann eigene Readings für jedes MQTT-Subtopic.&lt;br /&gt;
&lt;br /&gt;
Das &amp;quot;raumübergreifende&amp;quot; Reading &#039;&#039;presence&#039;&#039; wird anhand der des Alters in Sekunden der letzten lastseen-Nachricht gesteuert. Die lastseen-Nachricht wird immer gesendet, wenn der Scanvorgang von ble2mqtt das gewünschte Gerät findet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
define ble2mqttGTag MQTT2_DEVICE FHEM&lt;br /&gt;
attr ble2mqttGTag devicetopic ble2mqtt/.*/AA_BB_CC_DD_EE_FF&lt;br /&gt;
attr ble2mqttGTag event-on-change-reading .*&lt;br /&gt;
attr ble2mqttGTag readingList ble2mqtt/.*/heartbeat:.* heartbeat&lt;br /&gt;
$DEVICETOPIC/rssi:.* {my $room=(split m{[/]}x,$TOPIC)[1]; my $roomMax=$room; my $rssiMax=$EVENT; my @readings = grep { $_ =~ m{\Arssi_(?!$room).*}x } keys %{$defs{&amp;quot;$NAME&amp;quot;}-&amp;gt;{READINGS}}; for (@readings) {my $rssiTmp=ReadingsVal($NAME,$_,&#039;-100&#039;); my $roomTmp=(split m{[_]}x,$_)[1]; if(($rssiMax gt $rssiTmp)&amp;amp;&amp;amp;(ReadingsVal($NAME,&amp;quot;presence_&amp;quot;.$roomTmp,&#039;absent&#039;) eq &#039;present&#039;)) {$rssiMax=$rssiTmp; $roomMax=$roomTmp}}; {rssi=&amp;gt;$rssiMax,room=&amp;gt;$roomMax,&amp;quot;rssi_$room&amp;quot;=&amp;gt;$EVENT}}&lt;br /&gt;
$DEVICETOPIC/lastseen:.* {lastseen=&amp;gt;strftime &amp;quot;%Y-%m-%d %H:%M:%S&amp;quot;, localtime($EVENT)}&lt;br /&gt;
$DEVICETOPIC/present:.* {my $roomAct=(split m{[/]}x,$TOPIC)[1]; my $rssi=ReadingsVal($NAME,&amp;quot;rssi_&amp;quot;.$roomAct,&#039;-100&#039;); my $presenceAct=$EVENT?&#039;present&#039;:&#039;absent&#039;; my $room=$EVENT ? $roomAct:&#039;&#039;; my @readings = grep { $_ =~ m{\Apresence_(?!$roomAct).*}x } keys %{$defs{$NAME}-&amp;gt;{READINGS}}; for (@readings) {if(ReadingsVal($NAME,$_,&#039;absent&#039;) eq &#039;present&#039;) {my $roomTmp=(split m{[_]}x,$_)[1]; my $rssiTmp=ReadingsVal($NAME,&amp;quot;rssi_&amp;quot;.$roomTmp,&#039;-100&#039;); if($rssi gt $rssiTmp){$room=$roomTmp; $rssi=$rssiTmp}}}; {&amp;quot;presence_$roomAct&amp;quot;=&amp;gt;$presenceAct, room=&amp;gt;$room}}&lt;br /&gt;
ble2mqtt/.*/state:.* state&lt;br /&gt;
$DEVICETOPIC/battery:.* batteryLevel&lt;br /&gt;
attr ble2mqttGTag userReadings presence {if (ReadingsAge($NAME,&amp;quot;lastseen&amp;quot;,0)&amp;gt;60) {return &amp;quot;absent&amp;quot;;}else{return &amp;quot;present&amp;quot;;}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Ergebnis ist unter anderem ein Reading &#039;&#039;presence&#039;&#039; mit den Zuständen &#039;&#039;absent&#039;&#039; und &#039;&#039;present&#039;&#039;. Es kann somit ganz einfach als &amp;quot;presenceDevice&amp;quot; in einem [[ROOMMATE]]-Device verwendet werden:&lt;br /&gt;
 attr rr_Franz rr_presenceDevices ble2mqttGTag&lt;br /&gt;
&lt;br /&gt;
[[Category:MQTT]][[Category:Anwesenheitserkennung]][[Category:FHEM Utilities]]&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Ble2mqtt&amp;diff=39195</id>
		<title>Ble2mqtt</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Ble2mqtt&amp;diff=39195"/>
		<updated>2024-03-21T12:42:00Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: Link zum Script-Download hinzugefügt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=Anwesenheitserkennung von Bluetooth-Geräten&lt;br /&gt;
|ModType=u&lt;br /&gt;
|ModFTopic=127173&lt;br /&gt;
|ModForumArea=Unterstützende Dienste&lt;br /&gt;
|ModTechName=ble2mqtt&lt;br /&gt;
|ModOwner=PatrickR&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;ble2mqtt&#039;&#039;&#039; ist ein Script, dass den Anwesenheitsstatus eines oder mehrerer Bluetooth Low Energy Geräte überprüfen und das Ergebnis an einen MQTT Broker schicken kann.&lt;br /&gt;
&lt;br /&gt;
Es verwendet dazu die Linux Tools &#039;&#039;bluetoothctl&#039;&#039; und &#039;&#039;gatttool&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
ble2mqtt ist in Perl geschrieben und wurde von {{Link2FU|5068|PatrickR}} erstellt. Weitere Informationen finden sich in diesem {{Link2Forum|Topic=127173|LinkText=Forums-Topic }}. Fragen dazu bitte in den Bereich [https://forum.fhem.de/index.php?board=44.0 Unterstützende Dienste].&lt;br /&gt;
&amp;lt;!--diesen {{Link2Forum|Area=44|LinkText=Bereich }}.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Voraussetzungen==&lt;br /&gt;
* Debian od. Raspberry Pi OS&lt;br /&gt;
* Bluetooth Empfänger&lt;br /&gt;
&lt;br /&gt;
==Parameter==&lt;br /&gt;
Beim Start von ble2mqtt können folgende Parameter angegeben werden:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Parameter!!Beschreibung!!Standardwert!!Beispiel!!Optional&lt;br /&gt;
|-&lt;br /&gt;
| --mqttserver&lt;br /&gt;
|Die Adresse des MQTT Brokers inklusive Port&lt;br /&gt;
|&lt;br /&gt;
| --mqttserver mqtt.example.org:1883&lt;br /&gt;
|nein&lt;br /&gt;
|-&lt;br /&gt;
| --mqttfingerprint&lt;br /&gt;
|Der Fingerprint des für die TLS-verschlüsselte Kommunikation mit dem MQTT Broker verwendeten Zertifikates&lt;br /&gt;
|&lt;br /&gt;
| --mqttfingerprint bfe5d244a821194230f1479fe2f8f7bbcd2a8cb8&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --mqtttopic&lt;br /&gt;
| An welches MQTT-Topic das Tool die Informationen schicken soll.&lt;br /&gt;
|ble2mqtt&lt;br /&gt;
| --mqtttopic ble2mqtt/Wohnzimmer&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --mqttuser&lt;br /&gt;
|Der Benutzernamen, unter dem die Verbindung zum Broker hergestellt werden soll&lt;br /&gt;
|&lt;br /&gt;
| --mqttuser ble2mqtt&lt;br /&gt;
|ja bzw. abhängig vom Broker&lt;br /&gt;
|-&lt;br /&gt;
| --mqttpass&lt;br /&gt;
|Das zum Benutzernamen gehörende Passwort&lt;br /&gt;
|&lt;br /&gt;
| --mqttpass verysecret3&lt;br /&gt;
|ja bzw. abhängig vom Broker&lt;br /&gt;
|-&lt;br /&gt;
| --retain&lt;br /&gt;
|Versendet die Nachrichten present und lastseen als retained.&lt;br /&gt;
|0&lt;br /&gt;
| --retain&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --daemonize&lt;br /&gt;
|Wenn ble2mqtt im Hintergrund (als Daemon) ausgeführt werden soll&lt;br /&gt;
|0&lt;br /&gt;
| --daemonize&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --loglevel&lt;br /&gt;
|Wie und was genau protokolliert werden soll. Mögliche Loglevel sind LOG_CRIT, LOG_ERR, LOG_WARNING, LOG_NOTICE, LOG_INFO, LOG_DEBUG.&lt;br /&gt;
|LOG_INFO&lt;br /&gt;
| --loglevel LOG_ERR&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --logtarget&lt;br /&gt;
|Wohin gelogged werden soll. Mögliche Optionen sind &#039;&#039;syslog&#039;&#039; und &#039;&#039;stdout&#039;&#039;.&lt;br /&gt;
|syslog&lt;br /&gt;
| --logtarget stdout&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --absentinterval&lt;br /&gt;
|Anzahl an Sekunden, nach denen das Gerät als abwesend bezeichnet werden soll. Mindestwert ist 30.&lt;br /&gt;
|60&lt;br /&gt;
| --absentinterval 120&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --rssithreshold&lt;br /&gt;
|Ab welcher Abweichung des RSSI Wertes ein Update getriggert werden soll. Mindestwert ist 5.&lt;br /&gt;
|10&lt;br /&gt;
| --rssithreshold 8&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --watchdogthreshold&lt;br /&gt;
|Ab welchem Zeitraum in Sekunden nach Empfangen des letzten BT-Signals ble2mqtt neu gestartet werden soll. Mindestwert ist 30. Der Wert 0 bedeutet deaktiviert, also nie.&lt;br /&gt;
|0&lt;br /&gt;
| --watchdogthreshold 30&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --debug&lt;br /&gt;
|Kann nur gemeinsam mit --daemonize verwendet werden, um Logeinträge auf stdout auszugeben. Je höher die Nummer, desto mehr Output.&lt;br /&gt;
|0&lt;br /&gt;
| --daemonize --debug 4&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --mac&lt;br /&gt;
|Filtert mittels Regex nach MAC-Adressen der von ble2mqtt zu beachtenden BLE-Geräte. Alle anderen Geräte werden ignoriert.&lt;br /&gt;
|&lt;br /&gt;
| --mac &#039;(11:22:33:44:55:66|77:88:99:00:AA:BB)&#039;&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --batterymaxage&lt;br /&gt;
|Zeit in Stunden, nach denen ein Batterie-Wert als veraltet angesehen und aktualisiert wird. Der Wert 0 deaktiviert den Batterie-Check.&lt;br /&gt;
|48&lt;br /&gt;
| --batterymaxage 6&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --forcebattery&lt;br /&gt;
|Nur in Kombination mit --mac. Erzwingt einen Batterie-Check, auch wenn das battery-service am Gerät nicht erkannt wird.&lt;br /&gt;
|0&lt;br /&gt;
| --forcebattery&lt;br /&gt;
|ja&lt;br /&gt;
|}&lt;br /&gt;
===Beispiele===&lt;br /&gt;
* Broker verlangt Username/Passwort; es sollen keine Batterie-Werte ausgelesen werden&lt;br /&gt;
 ble2mqtt --mqttserver mqtt.example.org:1883 --mqttuser ble2mqtt --mqttpass verysecret3 --batterymaxage 0&lt;br /&gt;
&lt;br /&gt;
* Broker verlangt keine Authentifizierung; es soll nach zwei G-Tags gesucht werden; definiertes MQTT-Topic; Batteriewerte benötigt&lt;br /&gt;
 ble2mqtt --mqttserver mqtt.example.org:1883 --mqtttopic ble2mqtt/Wohnzimmer --mac &#039;(11:22:33:44:55:66|77:88:99:00:AA:BB)&#039;&lt;br /&gt;
&lt;br /&gt;
* Broker verlangt keine Authentifizierung; Geräte sollen nach 45s ohne Kontakt als abwesend angezeigt werden; MQTT Nachrichten sollen gespeichert bleiben&lt;br /&gt;
 ble2mqtt --mqttserver mqtt.example.org:1883 --absentinterval 45 --retain&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
Zur Installation muss das ble2mqtt-Script auf den Server kopiert werden und es müssen diverse Linux- und Perl-Pakete installiert werden. Das Script findet ihr in {{Link2Forum|Topic=127173|Message=1286068|LinkText=diesem Forumsbeitrag}} zum Download.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zuerst das Script nach /usr/local/bin kopieren, um beim Aufruf in der Bash nicht immer den ganzen Pfad voranstellen zu müssen.&lt;br /&gt;
 sudo cp -a ble2mqttd /usr/local/bin/&lt;br /&gt;
Danach das Script noch als ausführbar markieren&lt;br /&gt;
 sudo chmod +x /usr/local/bin/ble2mqttd&lt;br /&gt;
&lt;br /&gt;
===Benötigte Linux Pakete===&lt;br /&gt;
Die benötigten Pakete können ganz einfach mit &#039;&#039;apt&#039;&#039; installiert werden. Dabei werden auch mögliche Abhängigkeiten automatisch installiert.&lt;br /&gt;
&lt;br /&gt;
 sudo apt install -y libssl-dev libio-socket-ssl-perl libreadonly-perl libtest-expect-perl libnet-ssleay-perl libnet-server-perl&lt;br /&gt;
&lt;br /&gt;
===Benötigte Perl-Module===&lt;br /&gt;
Es wird das Modul &#039;&#039;Net::MQTT::Simple&#039;&#039; (&#039;&#039;libnet-mqtt-simple-perl&#039;&#039;) benötigt. Das ist - Stand 08.11.2023 - noch nicht in den Stable-Repositories von Debian verfügbar und muss daher mittels &#039;&#039;cpan&#039;&#039; installiert werden. Voraussetzung dafür ist das Modul &#039;&#039;CPAN::DistnameInfo&#039;&#039;, welches zuerst installiert werden muss.&lt;br /&gt;
&lt;br /&gt;
 sudo cpan CPAN::DistnameInfo&lt;br /&gt;
 sudo cpan Net::MQTT::Simple&lt;br /&gt;
&lt;br /&gt;
Sobald &#039;&#039;libnet-mqtt-simple-perl&#039;&#039; verfügbar ist, kann dieses statt der Perl-Module wie ein normales Linux-Paket installiert werden.&lt;br /&gt;
&lt;br /&gt;
===Erster Test===&lt;br /&gt;
Mit einem einfachen Aufruf von &#039;&#039;&#039;ble2mqtt&#039;&#039;&#039; kann getestet werden, ob alle benötigten Module und Pakete vorhanden sind.&lt;br /&gt;
&lt;br /&gt;
 sudo /usr/local/bin/ble2mqttd&lt;br /&gt;
&lt;br /&gt;
===Erstellen einens Systemd-Daemons===&lt;br /&gt;
Damit &#039;&#039;&#039;ble2mqtt&#039;&#039;&#039; bei jedem Systemstart automatisch gestartet wird, muss ein Systemd-Daemon erstellt werden. Das wird gemacht, in dem eine neue Textdatei mit folgendem Inhalt angelegt und der Daemon dann aktiviert wird.&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|&#039;&#039;&#039;Wichtig:&#039;&#039;&#039; Das Kommando, mit welchen Parametern ble2mqtt gestartet wird, muss natürlich individuell angepasst werden!}}&lt;br /&gt;
&lt;br /&gt;
 sudo nano /etc/systemd/system/ble2mqttd.service&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=ble2mqttd&lt;br /&gt;
After=bluetooth.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
Restart=always&lt;br /&gt;
ExecStart=/usr/local/bin/ble2mqttd --mqttserver mqtt.example.com:1883 --mqtttopic ble2mqtt/wohnzimmer --mac &#039;(11:22:33:44:55:66|77:88:99:00:AA:BB)&#039; --absentinterval 30 --mqttuser &amp;lt;username&amp;gt; --mqttpass &amp;lt;password&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 sudo systemctl daemon-reload&lt;br /&gt;
 sudo systemctl enable ble2mqttd.service&lt;br /&gt;
 sudo systemctl start ble2mqttd.service&lt;br /&gt;
&lt;br /&gt;
==Einbindung in FHEM==&lt;br /&gt;
Da ble2mqtt alle Informationen an einen [[MQTT]]-Broker sendet, können diese Informationen ganz einfach als [[MQTT2_DEVICE]] in FHEM eingebunden werden. Wie dabei vorgegangen werden kann, unterscheidet sich je nach Anwendungsbereich und den eigenen Vorlieben.&lt;br /&gt;
&lt;br /&gt;
Als Beispiel sie hier die Anwesenheitserkennung mittels BT-Tags angeführt.&lt;br /&gt;
&lt;br /&gt;
===Anwesenheitserkennung mittels BT-Tags===&lt;br /&gt;
[[File:ble2mqtt.png|thumb|Readings eines Devices, dass mit diesem Code erstellt wurde]]&lt;br /&gt;
Der folgende Code geht davon aus, dass es mehrere ble2mqtt-Instanzen gibt und ein BT-Tag mit der MAC-Adresse AA:BB:CC:DD:EE:FF erkannt werden soll.&lt;br /&gt;
&lt;br /&gt;
Die verschiedenen ble2mqtt-Instanzen schicken ihre Nachrichten in unterschiedliche Topics.&lt;br /&gt;
Für jede Instanz ein eigenes Topic:&lt;br /&gt;
*ble2mqtt/wohnzimmer&lt;br /&gt;
*ble2mqtt/schlafzimmer&lt;br /&gt;
*ble2mqtt/kueche&lt;br /&gt;
Im Attribut &#039;&#039;devicetopic&#039;&#039; werden diese Topics dann gemeinsam ausgewertet. Das funktioniert, in dem der Name des Subtopics einfach durch den Regex-Ausdruck &#039;&#039;.*&#039;&#039; ersetzt wird.&lt;br /&gt;
&lt;br /&gt;
Bedeutet aber auch, dass die Informationen - wenn gewünscht - wieder in unterschiedliche Readings zerlegt werden müssen. Um z.B. schnell zu erkennen, in welchem Raum der BT-Tag gerade liegt. Das passiert hier z.B. bei den Nachrichten für &#039;&#039;rssi&#039;&#039; und &#039;&#039;presence&#039;&#039;. Daraus resultieren dann eigene Readings für jedes MQTT-Subtopic.&lt;br /&gt;
&lt;br /&gt;
Das &amp;quot;raumübergreifende&amp;quot; Reading &#039;&#039;presence&#039;&#039; wird anhand der des Alters in Sekunden der letzten lastseen-Nachricht gesteuert. Die lastseen-Nachricht wird immer gesendet, wenn der Scanvorgang von ble2mqtt das gewünschte Gerät findet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
define ble2mqttGTag MQTT2_DEVICE FHEM&lt;br /&gt;
attr ble2mqttGTag devicetopic ble2mqtt/.*/AA_BB_CC_DD_EE_FF&lt;br /&gt;
attr ble2mqttGTag event-on-change-reading .*&lt;br /&gt;
attr ble2mqttGTag readingList ble2mqtt/.*/heartbeat:.* heartbeat&lt;br /&gt;
$DEVICETOPIC/rssi:.* {my $room=(split m{[/]}x,$TOPIC)[1]; my $roomMax=$room; my $rssiMax=$EVENT; my @readings = grep { $_ =~ m{\Arssi_(?!$room).*}x } keys %{$defs{&amp;quot;$NAME&amp;quot;}-&amp;gt;{READINGS}}; for (@readings) {my $rssiTmp=ReadingsVal($NAME,$_,&#039;-100&#039;); my $roomTmp=(split m{[_]}x,$_)[1]; if(($rssiMax gt $rssiTmp)&amp;amp;&amp;amp;(ReadingsVal($NAME,&amp;quot;presence_&amp;quot;.$roomTmp,&#039;absent&#039;) eq &#039;present&#039;)) {$rssiMax=$rssiTmp; $roomMax=$roomTmp}}; {rssi=&amp;gt;$rssiMax,room=&amp;gt;$roomMax,&amp;quot;rssi_$room&amp;quot;=&amp;gt;$EVENT}}&lt;br /&gt;
$DEVICETOPIC/lastseen:.* {lastseen=&amp;gt;strftime &amp;quot;%Y-%m-%d %H:%M:%S&amp;quot;, localtime($EVENT)}&lt;br /&gt;
$DEVICETOPIC/present:.* {my $roomAct=(split m{[/]}x,$TOPIC)[1]; my $rssi=ReadingsVal($NAME,&amp;quot;rssi_&amp;quot;.$roomAct,&#039;-100&#039;); my $presenceAct=$EVENT?&#039;present&#039;:&#039;absent&#039;; my $room=$EVENT ? $roomAct:&#039;&#039;; my @readings = grep { $_ =~ m{\Apresence_(?!$roomAct).*}x } keys %{$defs{$NAME}-&amp;gt;{READINGS}}; for (@readings) {if(ReadingsVal($NAME,$_,&#039;absent&#039;) eq &#039;present&#039;) {my $roomTmp=(split m{[_]}x,$_)[1]; my $rssiTmp=ReadingsVal($NAME,&amp;quot;rssi_&amp;quot;.$roomTmp,&#039;-100&#039;); if($rssi gt $rssiTmp){$room=$roomTmp; $rssi=$rssiTmp}}}; {&amp;quot;presence_$roomAct&amp;quot;=&amp;gt;$presenceAct, room=&amp;gt;$room}}&lt;br /&gt;
ble2mqtt/.*/state:.* state&lt;br /&gt;
$DEVICETOPIC/battery:.* batteryLevel&lt;br /&gt;
attr ble2mqttGTag userReadings presence {if (ReadingsAge($NAME,&amp;quot;lastseen&amp;quot;,0)&amp;gt;60) {return &amp;quot;absent&amp;quot;;}else{return &amp;quot;present&amp;quot;;}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Ergebnis ist unter anderem ein Reading &#039;&#039;presence&#039;&#039; mit den Zuständen &#039;&#039;absent&#039;&#039; und &#039;&#039;present&#039;&#039;. Es kann somit ganz einfach als &amp;quot;presenceDevice&amp;quot; in einem [[ROOMMATE]]-Device verwendet werden:&lt;br /&gt;
 attr rr_Franz rr_presenceDevices ble2mqttGTag&lt;br /&gt;
&lt;br /&gt;
[[Category:MQTT]][[Category:Anwesenheitserkennung]][[Category:FHEM Utilities]]&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FHEMWEB_mit_Let%27s_Encrypt_Zertifikaten&amp;diff=38930</id>
		<title>FHEMWEB mit Let&#039;s Encrypt Zertifikaten</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FHEMWEB_mit_Let%27s_Encrypt_Zertifikaten&amp;diff=38930"/>
		<updated>2024-01-15T13:18:56Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: Beispiel mit mehreren Domains ergänzt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[https://certbot.eff.org Certbot] ist ein freies Open-Source-Tool der [https://www.eff.org/ Electronic Frontier Foundation (EFF)] mit dem automatisiert Zertifikate der [https://letsencrypt.org/ Let&#039;s Encrypt CA] erstellt werden können.&lt;br /&gt;
&lt;br /&gt;
Diese Zertifikate können auch in FHEM verwendet werden, um mittels HTTPS auf [[FHEMWEB]] zuzugreifen.&lt;br /&gt;
&lt;br /&gt;
In dieser Anleitung wird beschrieben wie [[#Certbot installieren|Certbot]] installiert, [[#Zertifikate erstellen|Zertifikate damit erstellt]] und diese dann [[#Einbindung in FHEM|FHEM zur Verfügung gestellt]] werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Let&#039;s Encrypt Zertifikate sind in der Regel 90 Tage gültig. Beim Beantragen eines Zertifikates wird von Certbot automatisch ein systemd Timer erstellt, der kurz vor Ablauf des Zertifikat einen Prozess zur Erneuerung desselben startet. Dabei müssen die selben Voraussetzungen gegeben sein, die auch bei der Erst-Erstellung des Zertifikates nötig sind.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Certbot installieren==&lt;br /&gt;
;Voraussetzungen:&lt;br /&gt;
* Debian/Ubuntu/Raspberry Pi OS auf dem FHEM-Server&lt;br /&gt;
* SSH-Zugang zum FHEM-Server&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die empfohlene Installationsweise ist über die [https://snapcraft.io Snap Paketverwaltung]. Diese Anleitung geht von dieser Empfehlung aus. Wer Snap nicht verwenden möchte, findet [https://eff-certbot.readthedocs.io/en/latest/install.html hier] weitere Informationen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es werden zuerst die Paket-Quellen aktualisiert. Danach erfolgt die Installation der Snap Paketverwaltung und einer Laufzeitumgebung dafür:&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt install -y snapd&lt;br /&gt;
 sudo snap install core&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im nächsten Schritt kann dann der Cerbot installiert werden:&lt;br /&gt;
 sudo snap install --classic certbot&lt;br /&gt;
&lt;br /&gt;
Damit Certbot ohne Angabe seines Pfades ausgeführt werden kann, wird noch ein symbolischer Link erstellt:&lt;br /&gt;
 sudo ln -s /snap/bin/certbot /usr/bin/certbot&lt;br /&gt;
&lt;br /&gt;
==Zertifikate erstellen==&lt;br /&gt;
Certbot bietet mehrere Möglichkeiten, Let&#039;s Encrypt Zertifikate zu erstellen. Diese hängen von den jeweiligen technischen Voraussetzungen ab.&lt;br /&gt;
&lt;br /&gt;
Damit ein Zertifikat ausgestellt werden kann, muss der Server bzw. der Serveradministrator bestimmte Aufgaben erfüllen um zu beweisen, dass er auch Besitzer der Domain ist, für die ein Zertifikat erstellt werden soll. Beispiele für solche Aufgaben sind z.B. einen bestimmten Record im DNS-Eintrag der Domain zu erstellen oder eine definierte Datei auf einem Webserver abzulegen. Für jede dieser Aufgaben gibt es ein Certbot Plug-In. Genauere Details finden sich auf der Webseite von [https://letsencrypt.org/de/how-it-works/ Let&#039;s Encrpyt].&lt;br /&gt;
&lt;br /&gt;
Welche der Möglichkeiten bzw. welches Plug-In genutzt wird, entscheidet der Serveradministrator.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im Folgenden sind zwei verschiedene Plug-Ins erklärt. Weitere Informationen oder alternative Möglichkeiten bietet die [https://eff-certbot.readthedocs.io/en/latest/using.html#getting-certificates-and-choosing-plugins Certbot-Dokumentation].&lt;br /&gt;
&lt;br /&gt;
===Standalone-Plugin===&lt;br /&gt;
Die &amp;quot;standalone&amp;quot; Variante bietet sich an, wenn auf dem System kein Web-Server installiert ist oder mit diesem nicht interagiert werden soll/kann.&lt;br /&gt;
&lt;br /&gt;
Um die Let&#039;s Encrypt Aufgabe erfüllen zu können, wird automatisch ein in Certbot eingebauter Webserver gestartet. Dieser liefert eine Datei aus, die von Let&#039;s Encrypt dann überprüft wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Voraussetzungen:&lt;br /&gt;
* Einen DNS Eintrag vom Typ A (IPv4) oder AAAA (IPv6) für eure Domain mit eurer externen IP Adresse&lt;br /&gt;
* Port 80 ist auf der Firewall geöffnet und wird zum FHEM-Server weitergeleitet&lt;br /&gt;
* Port 80 wird auf dem FHEM-Server von keinem anderen Service (Web-Server z.B.) verwendet&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind alle Voraussetzungen erfüllt, kann ein Zertifikat mit folgendem Befehl beantragt werden:&lt;br /&gt;
 sudo certbot certonly --standalone -d www.example.com -d example.com&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;&#039;&#039;--standalone&#039;&#039;&#039;&#039;&#039; bestimmt hier das zu verwendende Plug-In &amp;quot;standalone&amp;quot;&lt;br /&gt;
*&#039;&#039;&#039;&#039;&#039;-d&#039;&#039;&#039;&#039;&#039; die Domain, für die das Zertifikat ausgestellt werden soll. Es können - kommagetrennt - mehrere Domains angegeben werden. Oder der Parameter -d wird einfach öfter verwendet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weiteres Beispiel für das Beantragen eines Zertifikates mit mehreren Domains:&lt;br /&gt;
 sudo certbot certonly --standalone -d www.example.com -d example.com -d www.example.org -d example.org&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wer den ganzen Ablauf zuerst testen möchte, kann einen &amp;quot;dry-run&amp;quot; durchführen. Dabei wird die Ausstellung durch einen Test-Server von Let&#039;s Encrypt durchgeführt, es werden aber keine Zertifikate am FHEM-Server gespeichert: &lt;br /&gt;
 sudo certbot certonly --standalone --dry-run -d www.example.com&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit, einen ausführlicheren Testlauf durchzuführen ist, den Let&#039;s Encrypt Staging-Server (Test-Server) zu verwenden. Dabei werden Zertifikate im System abgelegt, die zwar ungültig sind, aber zu Testzwecken verwendet werden können:&lt;br /&gt;
 sudo certbot certonly --standalone --staging -d www.example.com&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--;Erneuern&lt;br /&gt;
sudo certbot certonly --standalone --force-renewal --staging -d www.example.com--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===DNS Plugins===&lt;br /&gt;
Eine ganz einfache Möglichkeit zur Erstellen von Zertifikaten bieten die DNS Plug-Ins.&lt;br /&gt;
&lt;br /&gt;
Dabei muss kein lokaler Server aus dem Internet erreichbar sein, sondern es wird ein bestimmter DNS-Eintrag der Domain automatisch geändert und überprüft um zu beweisen, dass der Antragsteller Inhaber der Domain ist.&lt;br /&gt;
&lt;br /&gt;
;Voraussetzungen&lt;br /&gt;
*Verwendung eines [https://eff-certbot.readthedocs.io/en/latest/using.html#dns-plugins unterstützten DNS-Providers] zur Verwaltung der eigenen Domain&lt;br /&gt;
*API-Key mit dem Recht, DNS-Einträge zu ändern&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für alle DNS Plug-Ins gilt, dass sie unter dem root-User laufen. Um das zu erlauben, ist folgender Befehl nötig:&lt;br /&gt;
 sudo snap set certbot trust-plugin-with-root=ok&lt;br /&gt;
&lt;br /&gt;
Anschließend muss das korrekte Plug-In installiert werden.&lt;br /&gt;
&lt;br /&gt;
In dieser Anleitung wird die Verwendung des [https://certbot-dns-cloudflare.readthedocs.io/en/stable/ Cloudflare Plug-Ins] erklärt. Die Funktionsweise ist bei anderen ähnlich und auf der jeweiligen [https://eff-certbot.readthedocs.io/en/latest/using.html#dns-plugins Dokumentationsseite] des Plug-Ins ersichtlich.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zuerst wird das Plug-In installiert:&lt;br /&gt;
 sudo snap install certbot-dns-cloudflare&lt;br /&gt;
&lt;br /&gt;
Danach wird eine Datei erstellt, die den API-Key mit der Berechtigung zum Ändern von DNS-Einträgen bei Cloudflare beinhaltet:&lt;br /&gt;
 sudo mkdir /root/.secrets/&lt;br /&gt;
 sudo nano /root/.secrets/cloudflare.ini&lt;br /&gt;
&lt;br /&gt;
;/root/.secrets/cloudflare.ini&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
# Cloudflare API token used by Certbot&lt;br /&gt;
dns_cloudflare_api_token = 0123456789abcdef0123456789abcdef01234567&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Datei muss dann noch vor unbefugtem Zugriff geschützt werden:&lt;br /&gt;
 sudo chmod 0700 /root/.secrets/&lt;br /&gt;
 sudo chmod 0400 /root/.secrets/cloudflare.ini&lt;br /&gt;
&lt;br /&gt;
Sind diese Schritte erledigt, kann ein Zertifikat beantragt werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo certbot certonly \&lt;br /&gt;
  --dns-cloudflare \&lt;br /&gt;
  --dns-cloudflare-credentials /root/.secrets/cloudflare.ini \&lt;br /&gt;
  --dns-cloudflare-propagation-seconds 20 \&lt;br /&gt;
  -d www.example.com -d example.com&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Einbindung in FHEM==&lt;br /&gt;
Um die Zertifikate nun in FHEM nutzen zu können, müssen zuerst die Berechtigungen auf diese geändert und dann symbolische Links zu Pfaden erstellt werden, wie sie FHEM erwartet.&lt;br /&gt;
&lt;br /&gt;
Das Ändern der Berechtigungen ist wichtig, weil der User &#039;&#039;fhem&#039;&#039; sonst keinen Lesezugriff auf diese hätte. Das Erstellen der symbolischen Link, weil FHEM die Zertifikate im Ordner &#039;&#039;/opt/fhem/certs&#039;&#039; erwartet.&lt;br /&gt;
&lt;br /&gt;
Grundsätzlich legt Certbot alle Zertifikate unter &#039;&#039;/etc/letsencrypt/archive&#039;&#039; ab. Und zwar unterschiedliche Versionen der Zertifikate. Damit Anwendungen die jeweils aktuellen Zertifikate ohne Änderung verwenden können, werden aber gleichzeitig auch symbolische Links nach &#039;&#039;/etc/letsencrypt/live&#039;&#039; gesetzt.&lt;br /&gt;
&lt;br /&gt;
Kurz gesagt, für Anwendungen sind nur die jeweiligen Dateien unter &#039;&#039;/etc/letsencrypt/live&#039;&#039; relevant. Dabei vor allem:&lt;br /&gt;
* &#039;&#039;&#039;/etc/letsencrypt/live/www.example.com/privkey.pem&#039;&#039;&#039; (Der private Key)&lt;br /&gt;
* &#039;&#039;&#039;/etc/letsencrypt/live/www.example.com/fullchain.pem&#039;&#039;&#039; (Das erstellte Zertifikat mit der ganzen Signaturkette)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nichts desto trotz müssen aber auf beiden Verzeichnisse (&#039;&#039;archive&#039;&#039; und &#039;&#039;live&#039;&#039;) die Zugriffsrechte geändert werden, damit der User &#039;&#039;fhem&#039;&#039; in späterer Folge daraus lesen kann. Für die Sicherheit der Zertifikate hat das keinen Einfluss, die sind durch eigene Dateisystemrechte geschützt.&lt;br /&gt;
 sudo chmod 0755 /etc/letsencrypt/{live,archive}&lt;br /&gt;
&lt;br /&gt;
Damit FHEM den Private Key lesen kann, ändern wir den Gruppenbesitz der Datei auf die Gruppe &#039;&#039;dialout&#039;&#039;:&lt;br /&gt;
 sudo chgrp dialout /etc/letsencrypt/archive/www.example.com/privkey1.pem&lt;br /&gt;
&lt;br /&gt;
Und vergeben anschließend noch eine Leseberechtigung für diese Gruppe:&lt;br /&gt;
 sudo chmod 0640 /etc/letsencrypt/archive/www.example.com/privkey1.pem&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind alle Berechtigungen vergeben (die sich beim Erneuern der Zertifikate nicht ändern), müssen noch symbolische Links in das Verzeichnis &#039;&#039;/opt/fhem/certs&#039;&#039; erstellt werden, da FHEM die Zertifikats-Dateien genau dort erwartet. Alle folgenden Befehle werden unter dem Benutzerkontext des Users &#039;&#039;fhem&#039;&#039; ausgeführt, damit danach keine Berechtigungen mehr verändert werden müssen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zuerst wird das Verzeichnis selbst erstellt:&lt;br /&gt;
 sudo -u fhem mkdir /opt/fhem/certs&lt;br /&gt;
&lt;br /&gt;
Anschließend ein symbolischer Link für den PrivateKey eingerichtet:&lt;br /&gt;
 sudo -u fhem ln -s /etc/letsencrypt/live/www.example.com/privkey.pem /opt/fhem/certs/server-key.pem&lt;br /&gt;
&lt;br /&gt;
Und danach einer für das Zertifikat:&lt;br /&gt;
 sudo -u fhem ln -s /etc/letsencrypt/live/www.example.com/fullchain.pem /opt/fhem/certs/server-cert.pem&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Änderung in FHEM selbst beschränken sich auf eine einzige Änderung am FHEMWEB-Device (&#039;&#039;WEB&#039;&#039;):&lt;br /&gt;
 attr WEB HTTPS 1&lt;br /&gt;
&lt;br /&gt;
Danach die Konfiguration speichern und FHEM ist ab sofort unter https://www.example.com:8083/ zu erreichen.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HOWTOS]][[Kategorie:Sicherheit]][[Kategorie:Systemadministration]][[Kategorie:FHEM Frontends]]&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FHEM_Tablet_UI&amp;diff=38704</id>
		<title>FHEM Tablet UI</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FHEM_Tablet_UI&amp;diff=38704"/>
		<updated>2023-11-09T11:31:39Z</updated>

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

		<summary type="html">&lt;p&gt;Drhirn: Weiterleitung auf Kategorie:Vorlage entfernt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Löschkandidat|Da ist wohl mal was bei der Erstellung einer Seite schief gelaufen. Der Doppelpunkt in dieser Kategorie ist zu viel.}}&lt;br /&gt;
#WEITERLEITUNG [[:Kategorie:Vorlage]]&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FHEMWiki:Sandbox&amp;diff=38702</id>
		<title>FHEMWiki:Sandbox</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FHEMWiki:Sandbox&amp;diff=38702"/>
		<updated>2023-11-09T10:58:06Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: veraltete &amp;quot;source&amp;quot;-Angaben in &amp;quot;syntaxhighlight&amp;quot; geändert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/perl&lt;br /&gt;
use strict;&lt;br /&gt;
use warnings;&lt;br /&gt;
&lt;br /&gt;
use Path::Class;&lt;br /&gt;
use autodie; # die if problem reading or writing a file&lt;br /&gt;
&lt;br /&gt;
my $dir = dir(&amp;quot;/tmp&amp;quot;); # /tmp&lt;br /&gt;
&lt;br /&gt;
my $file = $dir-&amp;gt;file(&amp;quot;file.txt&amp;quot;); # /tmp/file.txt&lt;br /&gt;
&lt;br /&gt;
# Get a file_handle (IO::File object) you can write to&lt;br /&gt;
my $file_handle = $file-&amp;gt;openw();&lt;br /&gt;
&lt;br /&gt;
my @list = (&#039;a&#039;, &#039;list&#039;, &#039;of&#039;, &#039;lines&#039;);&lt;br /&gt;
&lt;br /&gt;
foreach my $line ( @list ) {&lt;br /&gt;
    # Add the line to the file&lt;br /&gt;
    $file_handle-&amp;gt;print($line . &amp;quot;\n&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Test Tracking categories:&lt;br /&gt;
[[Datei:Brokenfile.pdf]]&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;Seiten mit dem veralteten source-Tag&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
 &amp;lt;syntaxhighlight ohne lang=&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=DWD_OpenData&amp;diff=38701</id>
		<title>DWD OpenData</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=DWD_OpenData&amp;diff=38701"/>
		<updated>2023-11-09T10:57:25Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: veraltete &amp;quot;source&amp;quot;-Angaben in &amp;quot;syntaxhighlight&amp;quot; geändert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Versionsänderung: Die Vorhersagedaten wurden Mitte September 2018 von CSV auf KML umgestellt. Diese Umstellung ist inkompatibel: das DWD_OpenData-Modul muss aktualisiert werden, einige Reading-Namen haben sich geändert und der Weblink muss deinstalliert und neu installiert werden (siehe diesen {{Link2Forum|Topic=83097|Message=840270|Linktext=Beitrag im Forum}}).}}&lt;br /&gt;
&lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=Daten vom DWD OpenData Server abrufen&lt;br /&gt;
|ModType=d&lt;br /&gt;
|ModCmdRef=DWD_OpenData&lt;br /&gt;
|ModForumArea=Unterstützende Dienste/Wettermodule&lt;br /&gt;
|ModTechName=55_DWD_OpenData.pm&lt;br /&gt;
|ModOwner=JensB ({{Link2FU|14024|Forum}}/[[Benutzer Diskussion:JensB|Wiki]])&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Der Deutsche Wetterdienst (DWD) stellt Wetterdaten über den [https://www.dwd.de/DE/leistungen/opendata/opendata.html Open Data Server] zur Verfügung. Die Verwendung dieses Dienstes und der vom DWD zur Verfügung gestellten Daten unterliegt den auf der OpenData Webseite beschriebenen Bedingungen. Einen Überblick über die verfügbaren Daten findet man in der Tabelle [https://www.dwd.de/DE/leistungen/opendata/help/inhalt_allgemein/opendata_content_de_en_xls.xls OpenData_weather_content.xls] oder hier: https://opendata.dwd.de/weather/lib/MetElementDefinition.xml.&lt;br /&gt;
&lt;br /&gt;
== Anwendung ==&lt;br /&gt;
Aufgrund der unterschiedlichen vom DWD bereitgestellten Datenformate benötigt das Modul zur Dekodierung je nach gewünschtem Funktionsumfang zusätzliche Perl-Module, die nicht standardmäßig vorinstalliert sind und je nach Systemkonfiguration nachinstalliert werden müssen. Außerdem unterstützt das Modul Zeitzonen, um z.B. die Wettervorhersage internationaler Stationen in Ortszeit darstellen zu können. Hierfür sind je nach Systemkonfiguration weitere Einstellungen erforderlich. Auch die Sprache der Wochentage für die Wettervorhersage ist frei wählbar. Je nach Systemkonfiguration ist aber die Standardsprache u.U. auf Englisch eingestellt, was weitere Anpassungen der Systemkonfiguration erforderlich macht.&lt;br /&gt;
&lt;br /&gt;
=== Vorbereitung ===&lt;br /&gt;
Im folgenden wird z.T. von einem System mit Rasbian oder Debian mit System-V Startsystem ausgegangen. Auf anderen Betriebssystemen und auf Systemen mit System-D müssen die Installationsschritte ggf. angepasst werden.&lt;br /&gt;
&lt;br /&gt;
1. Für die Wettervorhersage und die Wetterwarnungen:&lt;br /&gt;
Installation des Perl-Moduls &#039;&#039;XML::LibXML&#039;&#039; über die System-Kommandozeile mit&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt-get install libxml-libxml-perl&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; &lt;br /&gt;
oder mit CPAN.&lt;br /&gt;
&lt;br /&gt;
2. Weiterhin ist das Perl-Modul &#039;&#039; DateTime&#039;&#039; erforderlich. Dieses lässt sich mit &amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;sudo apt-get install libdatetime-perl&amp;lt;/syntaxhighlight&amp;gt; installieren.&lt;br /&gt;
&lt;br /&gt;
3. Falls man einen eigenen Internet-Proxy nutzt:&lt;br /&gt;
Die Konfiguration des Proxies für FHEM erfolgt z.B. durch Eintrag von&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr global proxy &amp;lt;myProxyHost&amp;gt;:&amp;lt;myProxyPort&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
in die [[Konfiguration]], wobei &#039;&#039;myProxyHost&#039;&#039; durch den Namen oder die IP-Adresse des Proxy-Servers ersetzt werden muss und für &#039;&#039;myProxyPort&#039;&#039; der Port des Proxy-Servers eingetragen werden muss (oft 3128).&lt;br /&gt;
&lt;br /&gt;
3. FHEM Uhrzeit und Zeitzone:&lt;br /&gt;
Durch Eingabe von &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 {localtime()}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
in die FHEM-Kommandozeile überprüfen, ob die FHEM-Uhrzeit plausibel ist. Ist dies nicht der Fall sollten die Uhrzeit auf Systemebene überprüft werden und ggf. die Systemeinstellungen angepasst werden.&lt;br /&gt;
Ermitteln der Bezeichnung der eigenen Zeitzone über die System-Kommandozeile mit&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  tzselect&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
und diese Bezeichnung in die Datei &#039;&#039;/etc/timezone&#039;&#039; eintragen und &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 export TZ=`cat /etc/timezone`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
der Datei &#039;&#039;/etc/profile&#039;&#039; hinzufügen und dann das System neu starten. Nun muss die Zeitanzeige in FHEM korrekt sein.&lt;br /&gt;
&lt;br /&gt;
4. FHEM Sprache:&lt;br /&gt;
Durch Eingabe von &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 {$ENV{LANG}}&lt;br /&gt;
&amp;lt;/pre&amp;gt; in die FHEM-Kommandozeile überprüfen, in welcher Sprache der Wochentag angezeigt wird. Stimmt die Sprache nicht, dann auf der System-Kommandozeile&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 dpkg-reconfigure locales&lt;br /&gt;
&amp;lt;/pre&amp;gt; eingeben und aus der Liste z.B. &#039;&#039;de_DE.UTF-8&#039;&#039; zusätzlich auswählen. Dieser Befehl gilt für Debian-basierte Betriebssysteme - für andere Betriebssysteme ist eine analoge Funktion zu verwenden. Mit Eingabe von &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 locale -a&lt;br /&gt;
&amp;lt;/pre&amp;gt; auf der System-Kommandozeile überprüfen, ob die ausgewählte Sprache nun zur Verfügung steht. Sollte FHEM nach einem Neustart noch immer nicht die gewünschte Sprache verwenden, kann man auf einem System V Linux durch Hinzufügen von z.B.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 export LANG=de_DE.UTF-8&lt;br /&gt;
&amp;lt;/pre&amp;gt; in die Datei &#039;&#039;/etc/init.d/fhem&#039;&#039; (irgendwo zwischen &#039;&#039;start&#039;&#039; und &#039;&#039;perl&#039;&#039;) und erneutem Neustart von FHEM die Sprache für FHEM erzwingen. Bei einem Systemd Linux kann man die Einstellungen mit &#039;&#039;systemctl edit --full fhem.service&#039;&#039; bearbeiten. Spätestes jetzt muss die Wochentagsanzeige in FHEM korrekt sein.&lt;br /&gt;
&lt;br /&gt;
5. Nur für den Weblink erforderlich:&lt;br /&gt;
Installation des Perl-Moduls &#039;&#039;DateTime&#039;&#039; über die System-Kommandozeile mit&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 sudo apt-get install libdatetime-perl&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
oder mit CPAN.&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
Siehe {{Link2CmdRef|Anker=DWD_OpenDatadefine|Label=Commandref}}.&lt;br /&gt;
&lt;br /&gt;
=== Attributes ===&lt;br /&gt;
Siehe {{Link2CmdRef|Anker=DWD_OpenDataattr|Label=Commandref}}.&lt;br /&gt;
&lt;br /&gt;
== Anwendungsbeispiele ==&lt;br /&gt;
=== Beispiel zur Modul-Einrichtung ===&lt;br /&gt;
&lt;br /&gt;
* Wettervorhersage&lt;br /&gt;
Für die Wettervorhersage muss der Stationscode ermittelt werden. Dazu den [https://www.dwd.de/DE/leistungen/met_verfahren_mosmix/mosmix_stationskatalog.pdf MOSMIX Stationskatalog] herunterladen, öffnen und die gewünschte Station heraussuchen (Spalte &#039;&#039;id&#039;&#039;). Einen Teil der deutschen Stationen kann man auch der [https://www.dwd.de/DE/derdwd/messnetz/bodenbeobachtung/messnetzkarte_boden.pdf Bodenmessnetzkarte] entnehmen. Den ermittelten Stationscode kann man dann entweder für eine Einzelabfrage als Parameter für das Kommando &#039;&#039;get forecast&#039;&#039; verwenden oder für die automatische Aktualisierung als Attribut &#039;&#039;forecastStation&#039;&#039; hinterlegen. Insgesamt werden vom DWD mehr als 70 Merkmale zur Verfügung gestellt. Eine Auflistung findet sich im Dokument [https://opendata.dwd.de/weather/lib/MetElementDefinition.xml MetElementDefinition]. Nur ein kleiner Teil der Merkmale wird in der Standardeinstellung des Moduls als Reading zur Verfügung gestellt. Wer andere Merkmale benötigt muss sie mit Komma getrennt dem Attribut &#039;&#039;forecastProperties&#039;&#039; zuweisen. Es empfiehlt sich zur Performance-Optimierung sowohl das Attribut &#039;&#039;forecastDays&#039;&#039; als auch das Attribut &#039;&#039;forecastProperties&#039;&#039; auf den tatsächlichen Bedarf einzustellen.&lt;br /&gt;
&lt;br /&gt;
* Wetterwarnungen&lt;br /&gt;
Für die Wetterwarnungen muss die Warnzelle ermittelt werden. Dazu [https://www.dwd.de/DE/leistungen/opendata/help/warnungen/cap_warncellids_csv.csv Warnzellen-ID Katalog] herunterladen, öffnen und die gewünschte Warnzelle heraussuchen. Unterstützt werden Gemeinden (beginnen mit 8), Landkreise (beginnen mit 1 oder 9) oder Küste (beginnen mit 5). Die Warnzellen-ID kann man dann entweder für eine Einzelabfrage als Parameter für das Kommando &#039;&#039;get alerts&#039;&#039; verwenden oder für die automatische Aktualisierung als Attribut &#039;&#039;alertArea&#039;&#039; hinterlegen. Die Warnzellen-ID ist ab der 2. Stelle identisch mit den ersten Ziffern des amtlichen Gemeindeschlüssels. Man kann z.B. den Namen von Gemeinde oder Landkreis bei den [https://www.statistik-bw.de/Statistik-Portal/gemeindeverz.asp Statistischen Ämtern des Bundes und der Länder] eingeben, den amtlichen Gemeindeschlüssel ermitteln und dann mit vorangestellter 1, 8 oder 9 im Warnzellen-ID Katalog des DWD nach einem Eintrag mit exakter oder weitgehender Übereinstimmung suchen. Wem das zu kompliziert vorkommt, der kann bei mehrdeutigen Gemeinde- bzw. Landkreisbezeichnungen auch versuchen auszuprobieren, welche die richtige Warnzellen-ID ist.&lt;br /&gt;
&lt;br /&gt;
Um das Modul mit automatisch Aktualisierung von Vorhersage und Wetterwarnungen zu nutzen, kann z.B. folgendes in die [[Konfiguration]] eingetragen werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 define DWD DWD_OpenData&lt;br /&gt;
 attr DWD alertArea 111000000&lt;br /&gt;
 attr DWD forecastStation 99810&lt;br /&gt;
 attr DWD forecastDays 3&lt;br /&gt;
 attr DWD forecastWW2Text 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Performance&lt;br /&gt;
Das DWD_OpenData-Modul ist ein Datenmodul mit relativ vielen Readings. In der Standardkonfiguration wird, wie bei jedem anderen FHEM Modul, bei jeder Änderung jedes Readings ein FHEM internes Ereignis erzeugt, damit andere FHEM Devices auf diese Änderungen reagieren können. Diese Ereignisse sorgen auch dafür, dass man Änderungen in der Weboberfläche sofort angezeigt bekommt, ohne die Webseite neu aufzurufen. Interessiert sich aber kein FHEM Device für die Änderungsbenachrichtigung bestimmter Readings, entsteht unnötiger Verarbeitungs-Overhead, der je nach FHEM Konfiguration und verfügbarer CPU-Leistung auch mehrere Sekunden benötigen kann und in dieser Zeit andere Abläufe blockiert. Um die Performance zu optimieren, empfiehlt es sich,  mit [[event-on-update-reading]] für eine angepasste und dadurch effizientere Verarbeitung zu sorgen, indem man nur für jene Readings Ereignisse zulässt, welche man für die Weiterverarbeitung braucht. Der DWD_OpenData_Weblink braucht z.B. gar keine Ereignisse, um zu funktionieren. Hier eine minimalistische Beispielkonfiguration:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr DWD event-on-update-reading state,fc_state,a_state&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Weitere Details zur Installation und Konfiguration des Moduls finden sich in der&lt;br /&gt;
{{Link2CmdRef|Anker=DWD_OpenData|Label=Commandref}}.&lt;br /&gt;
&lt;br /&gt;
=== Beispiel für die Einrichtung eines Meteogramms ===&lt;br /&gt;
Um den vorhergesagten Wetterverlauf als Meteogramm in Kurvenform mit [[SVG]] darzustellen, kann man wie folgt vorgehen:&lt;br /&gt;
&lt;br /&gt;
1. 99_myUtils.pm&lt;br /&gt;
&lt;br /&gt;
Für die Bestimmung der Werte für den SVG-Plot wird eine Perl-Funktion benötigt, die in die Datei 99_myUtils.pm vor dem Ende eingefügt wird. Wer diese FHEM-Datei noch nicht nutzt, legt sie einfach an (siehe [[99_myUtils_anlegen]]).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
package main;&lt;br /&gt;
&lt;br /&gt;
use strict;&lt;br /&gt;
use warnings;&lt;br /&gt;
 &lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# (c) mumpitzstuff 19.12.2018&lt;br /&gt;
#&lt;br /&gt;
# see https://forum.fhem.de/index.php/topic,83097.msg874150.html#msg874150&lt;br /&gt;
#&lt;br /&gt;
sub logProxy_dwd2Plot($$$$;$$$)&lt;br /&gt;
{&lt;br /&gt;
  my ($device, $fcValue, $from, $to, $fcHour, $expMode, $shiftTime) = @_;&lt;br /&gt;
  my $regex;&lt;br /&gt;
  my @rl;&lt;br /&gt;
&lt;br /&gt;
  return undef if(!$device);&lt;br /&gt;
&lt;br /&gt;
  if ($fcValue =~ s/_$//)&lt;br /&gt;
  {&lt;br /&gt;
    $regex = &amp;quot;^fc[\\d]+_[\\d]+_&amp;quot;.$fcValue.&amp;quot;\$&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    $regex = &amp;quot;^fc[\\d]+_&amp;quot;.$fcValue.&amp;quot;\$&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  $fcHour = 12 if(!defined($fcHour));&lt;br /&gt;
  $expMode = &amp;quot;point&amp;quot; if(!defined($expMode));&lt;br /&gt;
  #Log3 undef,2, &amp;quot;Regex: &amp;quot;.$regex;&lt;br /&gt;
&lt;br /&gt;
  # ermitteln aller relevanten Readings&lt;br /&gt;
  if ( defined($defs{$device}) )&lt;br /&gt;
  {&lt;br /&gt;
    if ( $defs{$device}{TYPE} eq &amp;quot;DWD_OpenData&amp;quot; )&lt;br /&gt;
    {&lt;br /&gt;
      @rl = sort&lt;br /&gt;
      {&lt;br /&gt;
        my ($an) = ($a =~ m/fc(\d+)_.*/);&lt;br /&gt;
        my ($bn) = ($b =~ m/fc(\d+)_.*/);&lt;br /&gt;
        my ($ao) = ($a =~ m/fc\d+_(\d+).*/);&lt;br /&gt;
        my ($bo) = ($b =~ m/fc\d+_(\d+).*/);&lt;br /&gt;
        $an &amp;lt;=&amp;gt; $bn or $ao &amp;lt;=&amp;gt; $bo or $a cmp $b;&lt;br /&gt;
      } ( grep /${regex}/,keys %{$defs{$device}{READINGS}} );&lt;br /&gt;
      return undef if ( !@rl );&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
      Log3 undef, 2, &amp;quot;logProxy_dwd2Plot: $device is not a DWD_OpenData device&amp;quot;;&lt;br /&gt;
      return undef;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  my $fromsec = SVG_time_to_sec($from);&lt;br /&gt;
  my $tosec   = SVG_time_to_sec($to);&lt;br /&gt;
  my $sec = $fromsec;&lt;br /&gt;
  my ($h, $hp, $fcDay, $mday, $mon, $year);&lt;br /&gt;
  my $timestamp;&lt;br /&gt;
&lt;br /&gt;
  my $reading;&lt;br /&gt;
  my $value;&lt;br /&gt;
  my $prev_value;&lt;br /&gt;
  my $min = 999999;&lt;br /&gt;
  my $max = -999999;&lt;br /&gt;
  my $ret = &amp;quot;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  # while not end of plot range reached&lt;br /&gt;
  while (($sec &amp;lt; $tosec) &amp;amp;&amp;amp; @rl)&lt;br /&gt;
  {&lt;br /&gt;
    #remember previous value for start of plot range&lt;br /&gt;
    $prev_value = $value;&lt;br /&gt;
&lt;br /&gt;
    $reading = shift @rl;&lt;br /&gt;
    ($fcDay) = $reading =~ m/^fc(\d+).*/;&lt;br /&gt;
    ($hp) = $reading =~ m/^fc\d+_(\d+).*/;&lt;br /&gt;
    #Log 1, &amp;quot;hp: &amp;quot;.$hp;&lt;br /&gt;
&lt;br /&gt;
    if ($hp)&lt;br /&gt;
    {&lt;br /&gt;
      $h = ReadingsVal($device, &amp;quot;fc&amp;quot;.$fcDay.&amp;quot;_&amp;quot;.$hp.&amp;quot;_time&amp;quot;, $fcHour);&lt;br /&gt;
      if ($h =~ m/^(\d+):\d+/)&lt;br /&gt;
      {&lt;br /&gt;
        $h = $1;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
      $h = $fcHour;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    $value = ReadingsVal($device, $reading, undef);&lt;br /&gt;
&lt;br /&gt;
    # calculate minutes of sunshine per hour&lt;br /&gt;
    if ($fcValue =~ /^SunD(\d+)/)&lt;br /&gt;
    {&lt;br /&gt;
      if (defined($1))&lt;br /&gt;
      {&lt;br /&gt;
        $value = $value / ($1 * 36);&lt;br /&gt;
      }&lt;br /&gt;
      else&lt;br /&gt;
      {&lt;br /&gt;
        $value = $value / (12 * 36);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    # calculate amount of rain per hour&lt;br /&gt;
    if ($fcValue =~ /^RR(\d+)c$/)&lt;br /&gt;
    {&lt;br /&gt;
      if (defined($1))&lt;br /&gt;
      {&lt;br /&gt;
        $value /= $1;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    ($year, $mon, $mday) = split(&#039;\-&#039;,ReadingsVal($device, &amp;quot;fc&amp;quot;.$fcDay.&amp;quot;_date&amp;quot;,undef));&lt;br /&gt;
    $timestamp = sprintf(&amp;quot;%04d-%02d-%02d_%02d:%02d:%02d&amp;quot;, $year, $mon, $mday, $h, 0, 0);&lt;br /&gt;
    $sec = SVG_time_to_sec($timestamp);&lt;br /&gt;
    if (defined($shiftTime))&lt;br /&gt;
    {&lt;br /&gt;
      $sec += $shiftTime;&lt;br /&gt;
      $timestamp = logProxy_shiftTime($timestamp, $shiftTime);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    # skip all values before start of plot range&lt;br /&gt;
    next if ( $sec &amp;lt; $fromsec );&lt;br /&gt;
&lt;br /&gt;
    # add first value at start of plot range&lt;br /&gt;
    if ( !$ret &amp;amp;&amp;amp; $prev_value )&lt;br /&gt;
    {&lt;br /&gt;
      $min = $prev_value if ( $prev_value &amp;lt; $min );&lt;br /&gt;
      $max = $prev_value if ( $prev_value &amp;gt; $max );&lt;br /&gt;
      $ret .= &amp;quot;$from $prev_value\n&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    # done if after end of plot range&lt;br /&gt;
    last if ($sec &amp;gt; $tosec);&lt;br /&gt;
&lt;br /&gt;
    $min = $value if ( $value &amp;lt; $min );&lt;br /&gt;
    $max = $value if ( $value &amp;gt; $max );&lt;br /&gt;
&lt;br /&gt;
    # add actual control point&lt;br /&gt;
    $ret .= &amp;quot;$timestamp $value\n&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if (($sec &amp;lt; $tosec) &amp;amp;&amp;amp; !@rl &amp;amp;&amp;amp; ($expMode eq &amp;quot;day&amp;quot;))&lt;br /&gt;
  {&lt;br /&gt;
    $timestamp = sprintf(&amp;quot;%04d-%02d-%02d_%02d:%02d:%02d&amp;quot;, $year, $mon, $mday, 23, 59, 59);&lt;br /&gt;
    $_ = SVG_time_to_sec($timestamp);&lt;br /&gt;
    if (defined($shiftTime))&lt;br /&gt;
    {&lt;br /&gt;
      $_ += $shiftTime;&lt;br /&gt;
      $timestamp = logProxy_shiftTime($timestamp, $shiftTime);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($_ &amp;lt; $tosec)&lt;br /&gt;
    {&lt;br /&gt;
      $ret .= &amp;quot;$timestamp $value\n&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
      $ret .= &amp;quot;$to $value\n&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  elsif (($sec &amp;gt; $tosec) &amp;amp;&amp;amp; ($expMode eq &amp;quot;day&amp;quot;))&lt;br /&gt;
  {&lt;br /&gt;
    $value = $prev_value + ($value - $prev_value) * (86400 + ($tosec - $sec)) / 86400;&lt;br /&gt;
    $ret .= &amp;quot;$to $value\n&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return ($ret, $min, $max, $prev_value);&lt;br /&gt;
} &lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. LogProxy&lt;br /&gt;
&lt;br /&gt;
Wer bereits ein [[logProxy]]-Device hat, muss den Namen seines logProxy-Devices in die weiter unter aufgeführte GPlot-Konfiguration eintragen. Ansonsten wird es wie folgt neu erstellt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define LogProxy logProxy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3. FileLog&lt;br /&gt;
&lt;br /&gt;
Das Meteogramm kennt anders als andere FHEM-Plots keine Vergangenheit außer heute. Trotzdem wird aus formalen Gründen ein [[FileLog]]-Device benötigt. Dazu kann ein beliebiges vorhandenes FileLog-Device verwendet werden. Wer will, kann hierfür aber auch ein neues FileLog Device für das DWD_OpenData-Device anlegen (Achtung: wird schnell umfangreich):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define FileLog_DWD FileLog ./log/DWD-%Y-%m.log DWD&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im folgenden wird für das FileLog-Device der Platzhalter &#039;&#039;FileLog_Dummy&#039;&#039; verwendet, der mit dem Namen des gewählten FileLog-Devices zu ersetzen ist.&lt;br /&gt;
&lt;br /&gt;
4. SVG Plot&lt;br /&gt;
&lt;br /&gt;
Das eigentliche Meteogramm ist ein SVG-Device. Will man mehrere Tage darstellen bietet sich die folgende Definition an:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define SVG_DWD SVG FileLog_Dummy:SVG_DWD:CURRENT&lt;br /&gt;
attr SVG_DWD fixedoffset 6&lt;br /&gt;
attr SVG_DWD fixedrange 7days&lt;br /&gt;
attr SVG_DWD nrAxis 1,2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dabei muss das SVG-Attribut &#039;&#039;fixedoffset&#039;&#039; entweder gleich oder kleiner als die Einstellung des DWD_OpenData-Attributs &#039;&#039;forecastDays&#039;&#039; (Standardwert: 6 Tage) gewählt werden und das SVG-Attribut &#039;&#039;fixedrange&#039;&#039; um eins größer als &#039;&#039;fixedoffset&#039;&#039; eingestellt werden.&lt;br /&gt;
&lt;br /&gt;
Will man stattdessen nur die nächsten 24 Stunden anzeigen, nimmt man folgende Einstellungen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define SVG_DWD SVG FileLog_Dummy:SVG_DWD:CURRENT&lt;br /&gt;
attr SVG_DWD endPlotNow 1&lt;br /&gt;
attr SVG_DWD fixedoffset 1&lt;br /&gt;
attr SVG_FileLog_WETTER_DWD_3 label &amp;quot;Tmin: $data{max1} °C, Tmax: $data{min1} °C&amp;quot;&lt;br /&gt;
attr SVG_DWD nrAxis 1,2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Um die DWD_OpenData-Readings mit dem Plot zu verknüpfen, muss man nun die GPlot-Konfigurationsdatei des SVG-Plots manuell bearbeiten. Dazu auf den Link klicken, der im SVG_DWD-Device am Internal &#039;&#039;GPLOTFILE&#039;&#039; steht. Die y-Wertebereiche für die Regenmenge und die Temperaturen sind im Beispiel auskommentiert (Autorange). Das kann man so lassen oder man stellt sie nach den eigenen Wetter-Gegebenheiten ein. Je nach Konfiguration des DWD_OpenData-Attributs &#039;&#039;forecastResolution&#039;&#039; sind aber noch einige weitere Einstellungen anzupassen. Das folgende Beispiel ist für die 3h-Auflösung:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set terminal png transparent size &amp;lt;SIZE&amp;gt; crop&lt;br /&gt;
set output &#039;&amp;lt;OUT&amp;gt;.png&#039;&lt;br /&gt;
set xdata time&lt;br /&gt;
set timefmt &amp;quot;%Y-%m-%d_%H:%M:%S&amp;quot;&lt;br /&gt;
set xlabel &amp;quot; &amp;quot;&lt;br /&gt;
set title &#039;Wettervorhersage&#039;&lt;br /&gt;
set ytics &lt;br /&gt;
set y2tics &lt;br /&gt;
set grid ytics&lt;br /&gt;
set ylabel &amp;quot;Regen [mm]&amp;quot;&lt;br /&gt;
#set yrange [0:4]&lt;br /&gt;
set y2label &amp;quot;Temperatur [°C]&amp;quot;&lt;br /&gt;
#set y2range [-5:35]&lt;br /&gt;
set y3label &amp;quot;Wolken/Regen/Sonne [%]&amp;quot;&lt;br /&gt;
set y3range [0:100]&lt;br /&gt;
&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;TTT_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;Tx&amp;quot;,$from,$to,18,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;Tn&amp;quot;,$from,$to,6,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;SunD3_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-3*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;RR3c_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-3*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;FX1_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;R600_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-3*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;Neff_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy ConstX:TimeNow(),0,100&lt;br /&gt;
#LogProxy ConstY:0&lt;br /&gt;
&lt;br /&gt;
plot &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;T&#039; ls l0 lw 2 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;Tmax&#039; ls l0dot lw 2 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;Tmin&#039; ls l0dot lw 2 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Sonne&#039; ls l4fill lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y1 title &#039;Regenmenge&#039; ls l2fill lw 1 with steps,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Wind&#039; ls l1 lw 1 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Regen&#039; ls l5fill lw 1 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Wolken&#039; ls l6fill lw 1 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 notitle ls l5 lw 4 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 notitle ls l5 lw 1 with lines&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verwendet man dagegen eine Auflösung von 1 Stunde, sind folgende LogProxy-Einträge erforderlich:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;TTT_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;Tx&amp;quot;,$from,$to,18,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;Tn&amp;quot;,$from,$to,6,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;SunD1_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-1*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;RR1c_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-1*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;FX1_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;R101_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-0.5*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;Neff_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy ConstX:TimeNow(),0,100&lt;br /&gt;
#LogProxy ConstY:0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für die Darstellung der nächsten 24 Stunden mit einer Auflösung von 1 Stunde nimmt man folgende GPlot-Konfiguration:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set terminal png transparent size &amp;lt;SIZE&amp;gt; crop&lt;br /&gt;
set output &#039;&amp;lt;OUT&amp;gt;.png&#039;&lt;br /&gt;
set xdata time&lt;br /&gt;
set timefmt &amp;quot;%Y-%m-%d_%H:%M:%S&amp;quot;&lt;br /&gt;
set xlabel &amp;quot; &amp;quot;&lt;br /&gt;
set title &#039;&amp;lt;L1&amp;gt;&#039;&lt;br /&gt;
set ytics&lt;br /&gt;
set y2tics&lt;br /&gt;
set y3tics&lt;br /&gt;
set grid xtics y2tics&lt;br /&gt;
set ylabel &amp;quot;Regen [mm]&amp;quot;&lt;br /&gt;
set y2label &amp;quot;Temperatur [°C]&amp;quot;&lt;br /&gt;
set y3label &amp;quot;Wolken/Regen/Sonne [%]&amp;quot;&lt;br /&gt;
set y3range [0:100]&lt;br /&gt;
&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;TTT_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;SunD1_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-1*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;RR1c_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-1*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;FX1_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;R101_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-0.5*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;Neff_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy ConstY:0&lt;br /&gt;
&lt;br /&gt;
plot &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;T&#039; ls l0 lw 2 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Sonne&#039; ls l4fill lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y1 title &#039;Regenmenge&#039; ls l2fill lw 1 with steps,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Wind&#039; ls l1 lw 1 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Regen&#039; ls l5fill lw 1 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Wolken&#039; ls l6fill lw 1 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 notitle ls l2 lw 2 with lines&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Je nachdem, welche Auflösung man verwendet, werden unterschiedliche Readings des DWD_OpenData-Devices benötigt. Diese sind in den LogProxy-Zeilen in der GPlot-Konfigurationsdatei zu finden und müssen auf jeden Fall dem Attribut &#039;&#039;forecastProperties&#039;&#039; des DWD_OpenData-Device hinzugefügt werden.&lt;br /&gt;
&lt;br /&gt;
Viele Detaileinstellungen des Meteogramms lassen sich individualisieren. Man kann z.B. mehr oder weniger Daten anzeigen und zumindest für &#039;&#039;heute&#039;&#039; auch aktuelle Messwerte hinzufügen.&lt;br /&gt;
&lt;br /&gt;
Hier ein Beispiel für ein Meteogramm über 4 Tage mit 3 Stunden Auflösung:&lt;br /&gt;
&lt;br /&gt;
[[File:DWDODmeteogram4d3h.png|500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Beispiel für die Einrichtung eines Weblinks ===&lt;br /&gt;
Zur graphischen Darstellung der Vorhersage und der Wetterwarnungen mit [[FHEMWEB]] steht das Modul [https://raw.githubusercontent.com/jnsbyr/fhem/master/FHEM/99_DWD_OpenData_Weblink.pm 99_DWD_OpenData_Weblink.pm] zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
Zunächst die Moduldatei herunterladen und in das Modulverzeichnis &#039;&#039;fhem/FHEM&#039;&#039; kopieren. Entweder die Datei direkt auf den FHEM-Server herunterladen (z.B. mit &#039;&#039;wget&#039;&#039;) oder beim indirekten Herunterladen darauf achten, dass dabei das Encoding nicht verändert wird (also z.B. bei WinSCP den Binär-Modus und nicht den Text-Modus verwenden). Ansonsten werden später z.B. Sonderzeichen wie &#039;&#039;°C&#039;&#039; falsch angezeigt. &lt;br /&gt;
&lt;br /&gt;
Anschließend kann in die [[Konfiguration]] z.B. folgendes eingetragen werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 define DWD_Weblink_Generator DWD_OpenData_Weblink&lt;br /&gt;
 attr DWD_Weblink_Generator IODev DWD&lt;br /&gt;
 attr DWD_Weblink_Generator forecastDays 4&lt;br /&gt;
 # refreshRate nur dann setzten, wenn der Browser Java-Script beherrscht:&lt;br /&gt;
 attr DWD_Weblink_Generator refreshRate 900&lt;br /&gt;
 &lt;br /&gt;
 define DWD_Weblink weblink htmlCode { DWD_OpenData_Weblink::AsHtmlH(&amp;quot;DWD_Weblink_Generator&amp;quot;) } &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Damit legt man das Weblink-Generator-Device an und verknüpft es mit dem DWD_OpenData-Device. Außerdem wird der [[weblink ]] selbst angelegt, der seinerseits mit dem Weblink-Generator-Device verknüpft wird. Der Weblink benötigt für seine Funktion eine bestimmte Auswahl der Vorhersage-Merkmale. Wer das Attribut &#039;&#039;forecastProperties&#039;&#039; des DWD_OpenData-Moduls anpassen will, muss diese Merkmale auf jeden Fall mit berücksichtigen. &lt;br /&gt;
&lt;br /&gt;
Wenn vom Weblink nichts im Browser zu sehen ist, kann das daran liegen, dass der Browser kein aktuelles JavaScript verwendet oder JavaScript deaktiviert ist. Dann sollte das Attribut &#039;&#039;refreshRate&#039;&#039; auf 0 Sekunden eingestellt oder gelöscht werden. Mit aktiviertem Refresh werden die Daten auch ohne Seitenneuaufbau regelmäßig und bei Tab-Wechsel aktualisiert.&lt;br /&gt;
&lt;br /&gt;
Die Liste der erforderlichen Vorhersage-Merkmale finden sich zusammen mit allen weiteren Details zur Installation und Konfiguration in der Modulhilfe von &#039;&#039;99_DWD_OpenData_Weblink.pm&#039;&#039;, die man z.B. nach dem Anlegen des Weblink-Generator-Devices über die Weboberfläche abrufen kann.&lt;br /&gt;
&lt;br /&gt;
Hier ein Ausschnitt aus der Darstellung des Weblinks mit [[FHEMWEB]]:&lt;br /&gt;
&lt;br /&gt;
[[File:DWDODweblink.png|500px]]&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Vbus&amp;diff=38700</id>
		<title>Vbus</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Vbus&amp;diff=38700"/>
		<updated>2023-11-09T10:56:56Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: veraltete &amp;quot;source&amp;quot;-Angaben in &amp;quot;syntaxhighlight&amp;quot; geändert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div style=&amp;quot;float:right&amp;quot;&amp;gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=VBUS LAN Adapter Device&lt;br /&gt;
|ModType=x&lt;br /&gt;
|ModCmdRef=VBUSIF&lt;br /&gt;
|ModForumArea=Sonstige Systeme &lt;br /&gt;
|ModFTopic=10303&lt;br /&gt;
|ModTechName=19_VBUSIF.pm&lt;br /&gt;
|ModOwner={{Link2FU|1754|Jörg (pejonp}})&lt;br /&gt;
}}&lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=VBUS Client Device&lt;br /&gt;
|ModType=x&lt;br /&gt;
|ModCmdRef=VBUSDEV&lt;br /&gt;
|ModForumArea=Sonstige Systeme&lt;br /&gt;
|ModFTopic=10303&lt;br /&gt;
|ModTechName=21_VBUSDEV.pm&lt;br /&gt;
|ModOwner={{Link2FU|1754|Jörg (pejonp}})&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Kurzbeschreibung ==&lt;br /&gt;
Das Vbus-Modul verbindet einen Vbus LAN-Adapter mit FHEM.&lt;br /&gt;
&lt;br /&gt;
== Voraussetzung ==&lt;br /&gt;
Voraussetzung zur Anbindung eines VBus Device an FHEM ist eine bestehende Netzwerkverbindung und die Verwendung der zur Verfügung stehenden Module: &lt;br /&gt;
* 19_VBUSIF.pm&lt;br /&gt;
* 21_VBUSDEV.pm&lt;br /&gt;
&lt;br /&gt;
Diese Module werden aktuell extern gehostet (es findet sich aber auch noch eine veraltete Version im FHEM repository). Um diese in die FHEM Installtion einzubinden muss folgender Befehl abgesetzt werden&lt;br /&gt;
:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;update all https://raw.githubusercontent.com/pejonp/vbus/master/controls_vbus.txt&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Damit werden auch bei einer FHEM Aktualisierung ([[update]]) diese Module berücksichtigt&lt;br /&gt;
&lt;br /&gt;
== Installation RESOL VBUS LAN Gateway ==&lt;br /&gt;
# Vorerst keine Einstellungen am VBUS/Lan Gateway (Passwort/Port etc.) vornehmen&lt;br /&gt;
# Die IP Adresse herausfinden (z.B. am Router) und prüfen, ob man per Browser darauf zugreifen kann&lt;br /&gt;
# Optional: Testen, ob Daten ankommen mit der ServiceCenter Software von Resol&lt;br /&gt;
# dann nur das VBUSIF als &#039;&#039;define&#039;&#039; eintragen&lt;br /&gt;
&lt;br /&gt;
== Definition ==&lt;br /&gt;
:&amp;lt;code&amp;gt;define &amp;lt;name&amp;gt; VBUSIF  &amp;lt;IP des VBus-Lan&amp;gt; &amp;lt;Port muss 7053 bleiben&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  define vbus VBUSIF 192.168.1.25:7053&lt;br /&gt;
  attr vbus event-min-interval .*:120&lt;br /&gt;
  attr vbus verbose 5&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Features / Funktionen ==&lt;br /&gt;
Es wurden die Module &lt;br /&gt;
*DL 2			0050&lt;br /&gt;
*DL 3			0053&lt;br /&gt;
*Vitosolic200_SD4	1060&lt;br /&gt;
*DeltaSol_SL		2251&lt;br /&gt;
*WMZ			4010&lt;br /&gt;
*SKSC1/2		4211&lt;br /&gt;
*DeltaSolC		4212&lt;br /&gt;
*Sonnenkraft_SKSC2HE	4214&lt;br /&gt;
*DeltaSol_BS4		4278&lt;br /&gt;
*DeltaSol_BS_2009	427b&lt;br /&gt;
*DeltaTherm_FK		5611&lt;br /&gt;
*MSR65_1		6521&lt;br /&gt;
*MSR65_2		6522&lt;br /&gt;
*SKS3HE			7160&lt;br /&gt;
*SKSC3HE_[HK1]		7161&lt;br /&gt;
*SKSC3HE_[HK2]		7162&lt;br /&gt;
*DeltaSol_M		7311&lt;br /&gt;
*DeltaSol_M_HKM		7312&lt;br /&gt;
*DeltaSol_M_Volumen	7315&lt;br /&gt;
*DeltaSol_M_WMZ1	7316&lt;br /&gt;
*DeltaSol_M_WMZ2	7317&lt;br /&gt;
*Vitosolic200		7321&lt;br /&gt;
*Vitosolic200_WMZ1	7326&lt;br /&gt;
*Vitosolic200_WMZ2	7327&lt;br /&gt;
*SLR 			7331&lt;br /&gt;
*CitrinSLR_XT		7341&lt;br /&gt;
*DeltaSol_ES 		7411&lt;br /&gt;
*DeltaSol_BX		7421&lt;br /&gt;
*DeltaSolE_Regler	7721&lt;br /&gt;
*DeltaSolE_WMZ		7722&lt;br /&gt;
*DiemasolC		7751&lt;br /&gt;
*Cosmo_Multi_Regler	7821&lt;br /&gt;
*Cosmo_Multi_WMZ	7822&lt;br /&gt;
*DeltaSol_MX_Regler	7E11&lt;br /&gt;
*DeltaSol_MX_Module	7E12&lt;br /&gt;
*DeltaSol_MX_HK		7E21&lt;br /&gt;
*DeltaSol_MX_WMZ	7E31&lt;br /&gt;
&lt;br /&gt;
== Bekannte Probleme ==&lt;br /&gt;
Aktuell ist es nicht möglich, die Konfiguration der Steuerungen zu ändern; es ist nur ein Abfragen der Werte implementiert.&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
* Resol Protokollbeschreibung [https://danielwippermann.github.io/resol-vbus/vbus-packets.html]&lt;br /&gt;
* VBus GitHub [https://github.com/pejonp/vbus]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Heizungssteuerung]]&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Unifi&amp;diff=38699</id>
		<title>Unifi</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Unifi&amp;diff=38699"/>
		<updated>2023-11-09T10:56:30Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: veraltete &amp;quot;source&amp;quot;-Angaben in &amp;quot;syntaxhighlight&amp;quot; geändert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=Steuerung des Unifi-Controllers über FHEM &lt;br /&gt;
|ModType=d&lt;br /&gt;
|ModForumArea=Automatisierung&lt;br /&gt;
|ModTechName=74_Unifi.pm&lt;br /&gt;
|ModOwner=Wuehler ({{Link2FU|18141|Forum}} / [[Benutzer Diskussion:Wuehler|Wiki]])}}&lt;br /&gt;
Das Modul [[Unifi]] ermöglicht die Steuerung eines Unifi-Controllers durch FHEM. Wenn durch den Unifi-Controller auch ein [[UnifiSwitch]] verwaltet wird, so legt das Modul bei aktiviertem [[autocreate]] UnifiSwitch-Devices an.&lt;br /&gt;
Ausserdem gibt es das Unterstützungsmodul [[UnifiClient]], welches alle vorhandenen Informationen zu Clients als Reading bereitstellt und clientspezifische Funktionen zur Verfügung stellt.&lt;br /&gt;
&lt;br /&gt;
== Voraussetzungen ==&lt;br /&gt;
=== Unifi-Controller ===&lt;br /&gt;
Es wird eine dauerhaft laufende Unifi-Controller-Software benötigt. Diese kann z.B. auf dem Unifi-Cloud-Key oder selbst installiert z.B. auf einem RaspberryPi laufen.&lt;br /&gt;
&lt;br /&gt;
=== Definition ===&lt;br /&gt;
Die Definition erfolgt mittels &amp;lt;code&amp;gt;define &amp;lt;name&amp;gt; Unifi &amp;lt;ip&amp;gt; &amp;lt;port&amp;gt; &amp;lt;username&amp;gt; &amp;lt;password&amp;gt; [&amp;lt;interval&amp;gt; [&amp;lt;siteID&amp;gt;]] &amp;lt;/code&amp;gt;.&lt;br /&gt;
Dabei ist folgendes zu beachten:&lt;br /&gt;
* ip: Der Unifi-Controller muss eine feste IP-Adresse haben&lt;br /&gt;
* port: Port der Adminkonsole des Unifi-Controllers. In der Regel 8443 oder 443.&lt;br /&gt;
* username/password: Username und Passwort eines Unifi-Controller-Users (siehe [[Unifi#Unifi-User|Unifi-User]])&lt;br /&gt;
* interval: Gibt die Zeit in Sekunden an, nach der das Modul erneut die Daten beim Unifi-Controller abfragt. Default: 30 Sekunden. Es ist darauf zu achten, dass das Intervall groß genug ist, so dass auch unter Last nicht vor Ende eines Update-Zyklus ein neuer Update-Zyklus gestartet wird. Dies kann zum Beispiel passieren, wenn FHEM und der Unifi-Controller auf demselben RaspberryPi laufen (interval dann zB auf 90 setzen).&lt;br /&gt;
* siteID: Üblicherweise und als Default &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Damit ist die Installation abgeschlossen. Nach kurzer Zeit sollten die ersten Readings angezeigt werden.&lt;br /&gt;
&lt;br /&gt;
=== Unifi-User ===&lt;br /&gt;
Bei der Definition des Moduls werden username und passwort mit angegeben. Entweder wird der standardmäßig angelegte Admin des Unifi-Controllers, oder besser ein im Unifi-Controller angelegter eigener User (unter &amp;lt;code&amp;gt;settings-&amp;gt; admins -&amp;gt; add new admin&amp;lt;/code&amp;gt;) genutzt. Wenn ein neuer User angelegt wird kann dieser z.B. auch ausschließlich read-only-Berechtigungen bekommen. Dies reicht für die Grundfunktion des Unifi-Moduls )Informationen auslesen und in Readings darstellen) aus. Alle set-Funktionen (Ausnahmen: clear, update und updateClient) sowie das Attribut voucherCache benötigen schreibende Rechte im Unifi-Controller .&lt;br /&gt;
&lt;br /&gt;
== Anwendung ==&lt;br /&gt;
=== Readings ===&lt;br /&gt;
Details siehe Siehe  {{Link2CmdRef|Lang=en|Anker=Unifi}}&lt;br /&gt;
&lt;br /&gt;
==== Attribut customClientReadings ====&lt;br /&gt;
Mit dem Attribut &amp;lt;code&amp;gt;customClientReadings&amp;lt;/code&amp;gt; können die Readings für Clients individualisiert werden. Eine Liste der möglichen Readings erhält man mittels &amp;lt;code&amp;gt;get &amp;lt;unifi&amp;gt; clientData all&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Der state eines clients kann nicht entfernt werden. D.h. für jeden client wird es ein Reading &amp;lt;clientName&amp;gt; geben, das entweder den Wert &amp;lt;code&amp;gt;connected&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;disconnected&amp;lt;/code&amp;gt; hat.&lt;br /&gt;
* Es werden die Daten, die der Unifi-Controller zu den Clients vorhält 1:1 als Readings zur Verfügung gestellt.&lt;br /&gt;
* Zusätzlich stehen mit dem Präfix _f_ versehen formatierte Werte als Reading zur Verfügung.&lt;br /&gt;
* Wenn der Unifi-Controller einen Wert nicht liefert, so wird auch kein Reading angelegt, selbst wenn dies im Attribut customClientReadings explizit angegeben wird.&lt;br /&gt;
&lt;br /&gt;
Bei der Verwendung des Attributes gibt es teilweise Abweichungen vom Standardverhalten, die bei einer nachträglichen Verwendung des Attributes ggf. berücksichtigt werden müssen:&lt;br /&gt;
* Das Reading &amp;lt;clientName&amp;gt;_last_seen wird nicht als Datum formatiert dargestellt, sondern wie vom Unifi-Controller zurückgegeben als Unix-Timestamp.&lt;br /&gt;
* Das Reading &amp;lt;clientName&amp;gt;_hostname kann ggf. auch fehlen. Ohne das Attribut customClientReadings wird bei fehlendem hostname die ip oder &amp;quot;unknown&amp;quot; angezeigt.&lt;br /&gt;
* Das Reading &amp;lt;clientName&amp;gt;_snr entfällt und lautet &amp;lt;clientName&amp;gt;_rssi.&lt;br /&gt;
&lt;br /&gt;
Beispiele:&lt;br /&gt;
* &amp;lt;code&amp;gt;.:^mac$&amp;lt;/code&amp;gt; : Stellt für alle Clients zusätzlich ein Reading mit der mac-Adresse zur Verfügung&lt;br /&gt;
* &amp;lt;code&amp;gt;.:^mac$|^uptime$&amp;lt;/code&amp;gt; : Stellt für alle Clients zusätzlich ein Reading mit der mac-Adresse und ein Reading mit der uptime (Unix-Timestamp) zur Verfügung&lt;br /&gt;
* &amp;lt;code&amp;gt;^meinTelefon$:^mac$&amp;lt;/code&amp;gt; : Stellt nur für den Client mit dem Namen &amp;quot;meinTelefon&amp;quot; ein zusätzliches Reading mit der mac-Adresse zur Verfügung&lt;br /&gt;
* &amp;lt;code&amp;gt;^meinTelefon$:^mac$ ^seinTelefon$:^mac$&amp;lt;/code&amp;gt; : Stellt nur für die Clients mit dem Namen &amp;quot;meinTelefon&amp;quot; oder &amp;quot;seinTelefon&amp;quot; ein zusätzliches Reading mit der mac-Adresse zur Verfügung&lt;br /&gt;
* &amp;lt;code&amp;gt;einTelefon$:^mac$&amp;lt;/code&amp;gt; : Stellt für alle Clients, die auf &amp;quot;einTelefon&amp;quot; enden im Client-Namen haben die mac-Adresse zusätzlich zur Verfügung&lt;br /&gt;
* &amp;lt;code&amp;gt;.:uptime&amp;lt;/code&amp;gt; : Stellt für alle Clients zusätzlich einige Readings zur Verfügung, die &amp;quot;uptime&amp;quot; im Namen enthalten. Darunter sind auch formatierte uptimes.&lt;br /&gt;
&lt;br /&gt;
=== Anwesenheitserkennung ===&lt;br /&gt;
Üblicherweise: siehe [[PRESENCE#Beispiel_Anwesenheitserkennung_mittels_UniFi_Controller|PRESENCE]]&lt;br /&gt;
&lt;br /&gt;
Oder falls man einen [[UnifiClient]] definiert hat:&lt;br /&gt;
&amp;lt;code&amp;gt;define &amp;lt;NAME&amp;gt; PRESENCE event &amp;lt;UnifiClientName&amp;gt;:fhem_state:.disconnected &amp;lt;UnifiClientName&amp;gt;:fhem_state:.connected&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Voucher ===&lt;br /&gt;
Das Modul kann automatisiert immer eine ausreichende Anzahl an Voucher-Nummern für den Zugang in ein per GuestPortal mit Voucherzugang konfiguriertes WLAN bereithalten.&lt;br /&gt;
Dazu wird das Attribut &amp;lt;code&amp;gt;voucherCache&amp;lt;/code&amp;gt; genutzt. Mit Komma separiert können mehrere Vouchercaches angegeben werden. Je Vouchercache werden vier Attribute mit Leerzeichen getrennt mitgegeben:&lt;br /&gt;
* expire: Ablaufzeit des Vouchers in Minuten&lt;br /&gt;
* quota: Anzahl der Voucher, die mindestens vorgehalten werden (sinnvoller Wert ist &amp;gt;=2)&lt;br /&gt;
* n: Gibt an, wie oft ein einzelner Voucher genutzt werden kann (sinnvoll ist in der Regel der Wert 1)&lt;br /&gt;
* note: der Name des Vouchers. Er darf keine Leerzeichen enthalten und kann z.B. bei einer Auswahl in ftui angezeigt werden.&lt;br /&gt;
Je Vouchercache wird ein Reading -VC_&amp;lt;note&amp;gt; mit dem nächsten noch nicht bzw. am längsten nicht angeforderten Voucher zur Verfügung gestellt. Wenn weniger als &amp;quot;quota&amp;quot;-Voucher zur Verfügung stehen werden &amp;quot;quota&amp;quot; neue Voucher erstellt. Die Maximalanzahl an vorgehaltenen Vouchern beträgt als 2*quota-1.&lt;br /&gt;
&lt;br /&gt;
==== Voucherverwendung aufzeichnen ====&lt;br /&gt;
Dies geschieht außerhalb des Moduls mit einem dummy und wird in den weiteren Beispielen mit verwendet:&lt;br /&gt;
&amp;lt;pre&amp;gt;defmod voucherComment dummy&lt;br /&gt;
attr voucherComment event-on-change-reading comment&lt;br /&gt;
attr voucherComment readingList comment&lt;br /&gt;
attr voucherComment setList comment&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Über eine ReadingsHistory kann dies festgehalten werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;defmod voucherCacheRH readingsHistory voucherComment:comment&lt;br /&gt;
attr voucherCacheRH nolinks 1&lt;br /&gt;
attr voucherCacheRH rows 10&lt;br /&gt;
attr voucherCacheRH timestampFormat %Y.%m.%d_%H:%M:%S&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Und/oder in einem Log speichern:&lt;br /&gt;
&amp;lt;pre&amp;gt;defmod voucherCommentLog FileLog ./log/voucher.log voucherComment:.*&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Voucher bereitstellen ====&lt;br /&gt;
Die Beispiele gehen davon aus, dass auch die Verwendung aufgezeichnet werden soll.&lt;br /&gt;
&lt;br /&gt;
===== über Telegram =====&lt;br /&gt;
Voraussetzung in diesem Beispiel ist, dass das Modul msgDialog eingerichtet ist und ein VoucherCache mit der note &amp;quot;2h&amp;quot; konfiguriert wurde:&lt;br /&gt;
&amp;lt;pre&amp;gt;defmod voucher_Dialog msgDialog {\&lt;br /&gt;
  &amp;quot;Voucher&amp;quot;: {\&lt;br /&gt;
    &amp;quot;commands&amp;quot;: [\&lt;br /&gt;
      &amp;quot;{fhem(&#039;set voucherComment comment &#039;.ReadingsVal(&#039;Unifi&#039;,&#039;-VC_2h&#039;,&#039;&#039;).&#039; (2h): $recipient&#039;)}&amp;quot;\&lt;br /&gt;
    ],\&lt;br /&gt;
    &amp;quot;message&amp;quot;: &amp;quot;{return(&#039;Code: &#039;.fhem(&#039;get Unifi voucher 2h&#039;))}&amp;quot;\&lt;br /&gt;
  }\&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== in FTUI =====&lt;br /&gt;
Im head der Seite wird folgender code benötigt:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt; &lt;br /&gt;
&amp;lt;script&amp;gt;&lt;br /&gt;
  var oldcode=0;&lt;br /&gt;
  function setComment(){&lt;br /&gt;
    var code =document.getElementById(&#039;voucherCode&#039;).children[0].value;&lt;br /&gt;
    if(oldcode!=code){&lt;br /&gt;
      oldcode=code;&lt;br /&gt;
      ftui.sendFhemCommand(&#039;get Unifi voucher &#039; + document.getElementById(&#039;voucherCacheNote&#039;).children[0].children[0].options.item(document.getElementById(&#039;voucherCacheNote&#039;).children[0].children[0].selectedIndex).text);     &lt;br /&gt;
      ftui.sendFhemCommand(&#039;set voucherComment comment &#039; + code +&#039; (&#039;+document.getElementById(&#039;voucherCacheNote&#039;).children[0].children[0].options.item(document.getElementById(&#039;voucherCacheNote&#039;).children[0].children[0].selectedIndex).text+&#039;): &#039;+document.getElementById(&#039;comment&#039;).children[0].value);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im body der Seite kann der folgende code verwendet werden. Es wird vorausgesetzt, dass es Vouchercaches mit der note 2h und 3h gibt. &lt;br /&gt;
&lt;br /&gt;
[[Datei:ftui_vouchercache.png|thumb|FTUI-Darstellung]]&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt; &lt;br /&gt;
&amp;lt;li data-row=&amp;quot;18&amp;quot; data-col=&amp;quot;1&amp;quot; data-sizex=&amp;quot;2&amp;quot; data-sizey=&amp;quot;3&amp;quot; class=&amp;quot;semitransparent&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;header&amp;gt;Voucher&amp;lt;/header&amp;gt;&lt;br /&gt;
  Typ:&lt;br /&gt;
  &amp;lt;div data-type=&amp;quot;select&amp;quot; data-items=&#039;[&amp;quot;-VC_2h&amp;quot;,&amp;quot;-VC_3h&amp;quot;]&#039; data-alias=&#039;[&amp;quot;2h&amp;quot;,&amp;quot;3h&amp;quot;]&#039; id=&amp;quot;voucherCacheNote&amp;quot; class=&amp;quot;notransmit w3x&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
  Kommentar:&lt;br /&gt;
  &amp;lt;div data-type=&amp;quot;input&amp;quot;&lt;br /&gt;
    id=&amp;quot;comment&amp;quot;&lt;br /&gt;
    class=&amp;quot;notransmit&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
  Code: &lt;br /&gt;
  &amp;lt;div data-type=&amp;quot;input&amp;quot;&lt;br /&gt;
    data-device=&amp;quot;Unifi&amp;quot;  &lt;br /&gt;
    data-get=&amp;quot;#voucherCacheNote&amp;quot;&lt;br /&gt;
    id=&amp;quot;voucherCode&amp;quot;&lt;br /&gt;
    class=&amp;quot;notransmit w3x&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;div data-type=&amp;quot;link&amp;quot;&lt;br /&gt;
    class=&amp;quot;round notransmit&amp;quot;&lt;br /&gt;
    onclick=&amp;quot;setComment()&amp;quot;&amp;gt;&lt;br /&gt;
   Save&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt; &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Erkennung neuer clients ===&lt;br /&gt;
Kleines DOIF mit [[TelegramBot|Telegram]]-Benachrichtigung:&lt;br /&gt;
&amp;lt;pre&amp;gt;defmod di_newClients DOIF ([Unifi:-UC_newClients] ne &amp;quot;&amp;quot; ) (set Telegram message unbekannter WLAN Zugriff:[Unifi:-UC_newClients])&amp;lt;/pre&amp;gt;Mit zusätzlichen Infos zu SSID und AP:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defmod UniFi_new_Client DOIF ([UniFi:-UC_newClients] ne &amp;quot;&amp;quot; )\&lt;br /&gt;
{my $host        = ReadingsVal(&amp;quot;UniFi&amp;quot;,&amp;quot;-UC_newClients&amp;quot;,&amp;quot;--&amp;quot;);; ## einlesen Hostname neuer WLAN Client\&lt;br /&gt;
 my $readingSSID = ReadingsVal(&amp;quot;UniFi&amp;quot;,$host.&amp;quot;_essid&amp;quot;,&amp;quot;--&amp;quot;);; ## bauen Reading SSID\&lt;br /&gt;
 my $readingAP   = ReadingsVal(&amp;quot;UniFi&amp;quot;,$host.&amp;quot;_accesspoint&amp;quot;,&amp;quot;--&amp;quot;);; ## bauen Reading AP\&lt;br /&gt;
 my $text = &amp;quot;Neuer WLAN Zugriff von &amp;quot;.$host.&amp;quot; über &amp;quot;.$readingAP.&amp;quot; an &amp;quot;.$readingSSID;; ## vorbereiten Text\&lt;br /&gt;
 fhem(&amp;quot;set TelegramBot msg $text&amp;quot;)} ## Telegram senden&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Funkscan mit startRFScan ===&lt;br /&gt;
Die Accesspoints von Unifi erlauben eine automatische Kanalwahl. &lt;br /&gt;
&lt;br /&gt;
Besonders dann, wenn der Funkraum mit vielen verschiedenen WLAN-Geräten belegt ist, ist die Auswahl des richtigen Kanals für einen stabilen Funkempfang wichtig. Um den richtigen Kanal zu wählen, sollte aber der vorhandene Funkraum vorher analysiert werden. Unifi erlaubt dies durch den so genannten RFScan, der für jeden einzelnen Accesspoint aufgerufen werden kann (und der dann für die Zeit des Scan von ca 5 Minuten offline ist).&lt;br /&gt;
&lt;br /&gt;
Im Modul wird der Funkscann durch den Befehl&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;UnifiModulname&amp;gt; setRFScan &amp;lt;APName&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
sofort ausgelöst. Wenn beispielsweise bei zwei Accesspoints mit den Namen Arbeitszimmer und Keller jeweils Montag Nacht ein Scan ausgelöst werden soll, kann dies mit folgendem DOIF geschehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;defmod MeinScan DOIF ([02:55|Mo]) (set Unifi startRFScan Keller) DOELSEIF ([03:10|Mo]) (set Unifi startRFScan Arbeitszimmer) &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== FAQ ==&lt;br /&gt;
=== Warum enthält die DropDown-Liste einiger set-/get-Funktionen nicht alle Clients? ===&lt;br /&gt;
Vom UnifiController werden nur die Geräte mitgesendet, die connected sind / die im UnifiController auf der Seite Clients angezeigt werden. Clients, die connected waren, es aber nicht mehr sind - im UnifiController auf der Seite Insights - werden vom Modul aktuell nicht ausgelesen. &lt;br /&gt;
&lt;br /&gt;
Seit März 2019 wird versucht, auch disconnected clients nach einem Neustart aus den Readings wiederherzustellen. Damit sollten die clients in den DropDowns vollständig sein.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:IP Components]]&lt;br /&gt;
[[Kategorie:Code Snippets]]&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Summe_aller_Einschaltzeiten_eines_Ger%C3%A4tes&amp;diff=38698</id>
		<title>Summe aller Einschaltzeiten eines Gerätes</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Summe_aller_Einschaltzeiten_eines_Ger%C3%A4tes&amp;diff=38698"/>
		<updated>2023-11-09T10:56:03Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: veraltete &amp;quot;source&amp;quot;-Angaben in &amp;quot;syntaxhighlight&amp;quot; geändert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Dieses Beispiel ermittelt aus der Datenbank die Einschaltdauer eines Kühlschrankes (über einen Zwischenstecker HM-ES-PMSw1-Pl) innerhalb der letzten 24 Stunden. Wie üblich kann der Auswertungszeitraum über die Time-spezifischen Attribute abgeändert werden.&lt;br /&gt;
&lt;br /&gt;
Es wird angenommen, dass &amp;quot;Aus&amp;quot; = 0 ist und &amp;quot;Ein&amp;quot; ein von 0 abweichender Wert (1 oder eine andere Zahl).&lt;br /&gt;
&lt;br /&gt;
Es sind zwei Komponenten notwendig, ein DbRep-Device und eine Subroutine &amp;quot;switchontime&amp;quot; in der 99_myUtils. &lt;br /&gt;
Diese Auswertungsroutine kann abweichend davon auch in einer eigenen 99_xxxUtils.pm, z.B. 99_myOntimeUtils.pm, eingebaut werden. Diese Datei ist in das FHEM-Verzeichnis zu kopieren (üblicherweise /opt/fhem/FHEM).&lt;br /&gt;
&lt;br /&gt;
== DbRep-Device ==&lt;br /&gt;
&lt;br /&gt;
Das DbRep-Device wird entsprechend dieser &#039;&#039;&#039;Raw-Definition&#039;&#039;&#039; angelegt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define Rep.powerOnTime DbRep LogDB&lt;br /&gt;
attr Rep.powerOnTime aggregation no&lt;br /&gt;
attr Rep.powerOnTime comment Ermittlung der Anschaltdauer (Switch-on Time) eines Gerätes (z.B. Kühlschrank) \&lt;br /&gt;
innerhalb der letzten 24 Stunden.\&lt;br /&gt;
Es wird die Auswertungsroutine &amp;quot;switchontime&amp;quot; im Attribut &amp;quot;userExitFn&amp;quot; benötigt \&lt;br /&gt;
(in 99_myOntimeUtils.pm enthalten).\&lt;br /&gt;
\&lt;br /&gt;
Start erfolgt mit:      &amp;quot;set &amp;amp;lt;;Name&amp;amp;gt;; fetchrows history&amp;quot;&lt;br /&gt;
attr Rep.powerOnTime devStateIcon connected:10px-kreis-gelb .*disconnect:10px-kreis-rot .*done:10px-kreis-gruen&lt;br /&gt;
attr Rep.powerOnTime device eg.az.fridge_Pwr&lt;br /&gt;
attr Rep.powerOnTime event-on-update-reading state,switch_on_time_sec&lt;br /&gt;
attr Rep.powerOnTime reading power&lt;br /&gt;
attr Rep.powerOnTime room DbLog&lt;br /&gt;
attr Rep.powerOnTime timeDiffToNow 86400&lt;br /&gt;
attr Rep.powerOnTime userExitFn switchontime&lt;br /&gt;
attr Rep.powerOnTime verbose 2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Natürlich ist das angegeben DbLog-Device (LogDB) in der Definition, sowie die Attribute device und reading den eigenen Gegebenheiten anzupassen.&lt;br /&gt;
Wichtig ist die Angabe:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
attr Rep.powerOnTime userExitFn switchontime&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
was die Aktivierung der userExit-Funktion bzw. den Aufruf der Auswertungsroutine &amp;quot;switchontime&amp;quot; bewirkt.&lt;br /&gt;
&lt;br /&gt;
Die Daten in der Datenbank befinden sich im Device &amp;quot;eg.az.fridge_Pwr&amp;quot; und dem Reading &amp;quot;power&amp;quot;. Daraus resultiert dass nach einem &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set &amp;lt;Name&amp;gt; fetchrows history&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Readings mit folgenden Muster generiert werden.                              [[Datei:po_readings.PNG|right|thumb|300px|set &amp;lt;Name&amp;gt; fetchrows history]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2017-11-22_16-26-50__eg.az.fridge_Pwr__power  0  2017-11-22 18:33:50 &lt;br /&gt;
2017-11-22_16-29-54__eg.az.fridge_Pwr__power  0  2017-11-22 18:33:50 &lt;br /&gt;
2017-11-22_16-32-43__eg.az.fridge_Pwr__power  57.83  2017-11-22 18:33:50 &lt;br /&gt;
2017-11-22_16-35-18__eg.az.fridge_Pwr__power  51.09  2017-11-22 18:33:50 &lt;br /&gt;
2017-11-22_16-37-39__eg.az.fridge_Pwr__power  50.13  2017-11-22 18:33:50 &lt;br /&gt;
2017-11-22_16-39-45__eg.az.fridge_Pwr__power  50.17  2017-11-22 18:33:50 &lt;br /&gt;
2017-11-22_16-42-40__eg.az.fridge_Pwr__power  49.59  2017-11-22 18:33:50 &lt;br /&gt;
2017-11-22_16-45-22__eg.az.fridge_Pwr__power  48.57  2017-11-22 18:33:50 &lt;br /&gt;
2017-11-22_16-47-48__eg.az.fridge_Pwr__power  47.48  2017-11-22 18:33:50 &lt;br /&gt;
2017-11-22_16-50-01__eg.az.fridge_Pwr__power  46.97  2017-11-22 18:33:50 &lt;br /&gt;
2017-11-22_16-53-03__eg.az.fridge_Pwr__power  46.02  2017-11-22 18:33:50 &lt;br /&gt;
2017-11-22_16-53-05__eg.az.fridge_Pwr__power  11.09  2017-11-22 18:33:50 &lt;br /&gt;
2017-11-22_16-53-13__eg.az.fridge_Pwr__power  0  2017-11-22 18:33:50&lt;br /&gt;
2017-11-22_18-14-05__eg.az.fridge_Pwr__power  0 2017-11-22 18:33:50 &lt;br /&gt;
2017-11-22_18-16-39__eg.az.fridge_Pwr__power  0 2017-11-22 18:33:50 &lt;br /&gt;
2017-11-22_18-18-58__eg.az.fridge_Pwr__power  0 2017-11-22 18:33:50 &lt;br /&gt;
2017-11-22_18-21-03__eg.az.fridge_Pwr__power  0 2017-11-22 18:33:50 &lt;br /&gt;
2017-11-22_18-23-58__eg.az.fridge_Pwr__power  0 2017-11-22 18:33:50 &lt;br /&gt;
2017-11-22_18-26-08__eg.az.fridge_Pwr__power  56.37 2017-11-22 18:33:50 &lt;br /&gt;
2017-11-22_18-26-38__eg.az.fridge_Pwr__power  43.22 2017-11-22 18:33:50 &lt;br /&gt;
2017-11-22_18-29-04__eg.az.fridge_Pwr__power  50.92 2017-11-22 18:33:50 &lt;br /&gt;
2017-11-22_18-31-16__eg.az.fridge_Pwr__power  50.12 2017-11-22 18:33:50&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Auswertungsroutine &amp;quot;switchontime&amp;quot; ==&lt;br /&gt;
&lt;br /&gt;
Die nachfolgende Auswertungsroutine wird z.B. in der Datei 99_myOntimeUtils.pm gespeichert. Der Code ist mit Kommentaren angereichert um den Ablauf der Auswertung verständlich darzustellen und dadurch eine abgewndelte Nutzung in eigenen Projekten zu erleichtern.&lt;br /&gt;
&lt;br /&gt;
Den Code in die Datei kopieren:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
############################################################################&lt;br /&gt;
# $Id: myUtilsTemplate.pm 7570 2015-01-14 18:31:44Z rudolfkoenig $&lt;br /&gt;
# Beispiel aus https://wiki.fhem.de/wiki/Summe_aller_Einschaltzeiten_eines_Ger%C3%A4tes&lt;br /&gt;
&lt;br /&gt;
package main;&lt;br /&gt;
&lt;br /&gt;
use strict;&lt;br /&gt;
use warnings;&lt;br /&gt;
use Time::Local;&lt;br /&gt;
&lt;br /&gt;
sub&lt;br /&gt;
myOntimeUtils_Initialize($$)&lt;br /&gt;
{&lt;br /&gt;
  my ($hash) = @_;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
############################################################################################################&lt;br /&gt;
##                           Ermitteln der Einschaltzeiten eines Gerätes                               &lt;br /&gt;
############################################################################################################&lt;br /&gt;
# Im DbRep-Device ist das Attribut &amp;quot;userExitFn = switchontime&amp;quot; zu setzen.&lt;br /&gt;
# Auswertung wird im DbRep gestartet mit:&lt;br /&gt;
#&lt;br /&gt;
#      set &amp;lt;DbRep-Device&amp;gt; fetchrows history&lt;br /&gt;
#&lt;br /&gt;
# Die resultierende Switch-on Zeit wird im aufrufenden DbRep-Device in Readings dargestellt:&lt;br /&gt;
#      switch_on_time     -&amp;gt; on-Zeit als formatierte Angabe hhh:mm:ss&lt;br /&gt;
#      switch_on_time_sec -&amp;gt; on-Zeit als Sekundenwert&lt;br /&gt;
#   &lt;br /&gt;
# Die Routine ist für alle Readings geeignet die Zahlenwerte als Switch-on/off Zustand beinhalten.&lt;br /&gt;
#      Switch-off = 0&lt;br /&gt;
#      Swich-off  != 0&lt;br /&gt;
#&lt;br /&gt;
# Nach der Erstellung jedes einzelnen Readings wird die im Attribut &amp;quot;userExitFn&amp;quot; hinterlegte Funktion&lt;br /&gt;
# aufgerufen. Es wird der Devicename des aufrufenden Device, Reading und Wert des Readings übergeben.&lt;br /&gt;
# Der Aufrufablauf ist:&lt;br /&gt;
# 1. Start: state = running&lt;br /&gt;
# 2. Übermittlung jedes generierten Readings&lt;br /&gt;
# 3. Stop: state = done (bzw. nicht running)&lt;br /&gt;
#&lt;br /&gt;
###########################################################################################################&lt;br /&gt;
my $t = 0;        				# Variable für resultierende Sekunden&lt;br /&gt;
my $sekunden = 0;				# Variable für sekunden des Readings&lt;br /&gt;
my $startzeit = 0;				# Variable für Beginn des Zeitraums&lt;br /&gt;
my $endzeit = 0;				# Variable für Ende des Zeitraums&lt;br /&gt;
my $letztervalue = 0;			# Variable für Value des vorherigen Readings&lt;br /&gt;
my $letztersekunden = 0;			# Variable für Sekunde des vorherigen Readings&lt;br /&gt;
my $initvalue = 0;&lt;br /&gt;
my $pattern = &amp;quot;Ttim__state&amp;quot;;     # verwendbarer Teilstring des Switch-on/Switch-off Werte&lt;br /&gt;
                                             # enthaltenden Readings (entsprechend anpassen !)&lt;br /&gt;
my $runde;&lt;br /&gt;
&lt;br /&gt;
sub switchontime($$$)&lt;br /&gt;
{&lt;br /&gt;
	my ($name,$reading,$value) = @_;&lt;br /&gt;
	my $hash = $defs{$name};&lt;br /&gt;
	# $value = int  $value;    #schöner für Anzeigen&lt;br /&gt;
	&lt;br /&gt;
	if($reading eq &amp;quot;state&amp;quot; &amp;amp;&amp;amp; $value eq &amp;quot;running&amp;quot;)     # der Select wurde gestartet&lt;br /&gt;
	{     &lt;br /&gt;
		$letztervalue = -1;&lt;br /&gt;
		$runde = 0;&lt;br /&gt;
		my ($devn,$devread) = split(&amp;quot;__&amp;quot;,$pattern); # den aktuellen Zustand des Devices ermitteln&lt;br /&gt;
		$devread = uc ($devread);&lt;br /&gt;
		$initvalue = InternalVal(&amp;quot;$devn&amp;quot;,&amp;quot;$devread&amp;quot;,99);&lt;br /&gt;
		if ($initvalue == 99)&lt;br /&gt;
		{&lt;br /&gt;
			Log3 $name, 1, &amp;quot;$name - der Patternname scheint falsch zu sein&amp;quot;; 	&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		my $jetzt = TimeNow();   # aktuelle Zeit = Ende des Abfragezeitraums ermitteln&lt;br /&gt;
		&lt;br /&gt;
		my $lstr = (split(&amp;quot;__&amp;quot;,$jetzt))[0];&lt;br /&gt;
		my ($year, $month, $day, $hour, $min, $sec) = ($lstr =~ /(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)/);&lt;br /&gt;
		# Umwandeln in Epochesekunden&lt;br /&gt;
		&lt;br /&gt;
		$endzeit = timelocal($sec, $min, $hour, $day, $month-1, $year-1900); &lt;br /&gt;
		$startzeit = $endzeit - AttrVal(&amp;quot;Rep.powerOnTime&amp;quot;,&amp;quot;timeDiffToNow&amp;quot;,98); # Beginn des Abfragezeitraums ermitteln&lt;br /&gt;
	   &lt;br /&gt;
		Log3 $name, 3, &amp;quot;$name - UserExitFn \&amp;quot;ontime\&amp;quot; has been called.&amp;quot;;&lt;br /&gt;
		($sec,$min,$hour) = localtime($startzeit);&lt;br /&gt;
		Log3 $name, 3, &amp;quot;Start der Abfrage $startzeit $hour:$min:$sec&amp;quot;;   &lt;br /&gt;
		($sec,$min,$hour) = localtime($endzeit);		&lt;br /&gt;
		Log3 $name, 3, &amp;quot;Ende  der Abfrage $endzeit $hour:$min:$sec&amp;quot;;   &lt;br /&gt;
	&lt;br /&gt;
		$t = 0;&lt;br /&gt;
		return;&lt;br /&gt;
	}&lt;br /&gt;
	$runde = $runde +1;&lt;br /&gt;
	if($reading =~ /$pattern/)  # den Timestamp unabhängig vom Status festhalten&lt;br /&gt;
	{&lt;br /&gt;
		my $lstr = (split(&amp;quot;__&amp;quot;,$reading))[0];&lt;br /&gt;
		my ($year, $month, $day, $hour, $min, $sec) = ($lstr =~ /(\d+)-(\d+)-(\d+)_(\d+)-(\d+)-(\d+)/);&lt;br /&gt;
		# Umwandeln in Epochesekunden&lt;br /&gt;
		$sekunden = timelocal($sec, $min, $hour, $day, $month-1, $year-1900);&lt;br /&gt;
		Log3 $name, 4, &amp;quot;t:$t s:$sekunden value:$value $hour:$min:$sec &amp;quot;;&lt;br /&gt;
		&lt;br /&gt;
		if($letztervalue == -1)		# wenn jüngster Wert (erstes reading)&lt;br /&gt;
		{&lt;br /&gt;
			if($value != 0)		#  an&lt;br /&gt;
			{&lt;br /&gt;
				$t = $endzeit;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		if ($value == $letztervalue)&lt;br /&gt;
		{&lt;br /&gt;
				Log3 $name, 2, &amp;quot;$name - Ein value ist doppelt&amp;quot;; 	&lt;br /&gt;
		}&lt;br /&gt;
		if( $value != 0 &amp;amp;&amp;amp; $value != $letztervalue) # Gerät wurde eingeschaltet&lt;br /&gt;
		{&lt;br /&gt;
			$t = $t - $sekunden;&lt;br /&gt;
		}		&lt;br /&gt;
		if($value == 0 &amp;amp;&amp;amp; $value != $letztervalue)  # Gerät wurde ausgeschaltet&lt;br /&gt;
		{&lt;br /&gt;
			$t = $t + $sekunden;&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
								# Value sichern für endberechnung und doppelte Werte&lt;br /&gt;
		$letztervalue = $value;&lt;br /&gt;
		$letztersekunden = $sekunden;		&lt;br /&gt;
	}	&lt;br /&gt;
	if($reading eq &amp;quot;state&amp;quot; &amp;amp;&amp;amp; $value ne &amp;quot;running&amp;quot;) # die Selektion ist beendet, Summensekunden in Format hhh:mm:ss umwamdeln&lt;br /&gt;
	{&lt;br /&gt;
		if ($letztervalue == 0) # am Ende der Auswertung ist Status immer noch switch-on&lt;br /&gt;
		{   &lt;br /&gt;
			$t =  $t - $startzeit;&lt;br /&gt;
	&lt;br /&gt;
		}&lt;br /&gt;
		if ($letztervalue == -1)  #wenn keine Werte kamen&lt;br /&gt;
		{&lt;br /&gt;
			if( $initvalue != 0 ) # Gerät ganze Zeit an&lt;br /&gt;
			{&lt;br /&gt;
				$t = AttrVal(&amp;quot;Rep.powerOnTime&amp;quot;,&amp;quot;timeDiffToNow&amp;quot;,98);&lt;br /&gt;
				Log3 $name, 5, &amp;quot;Gerät ganze Zeit an&amp;quot;;&lt;br /&gt;
			}		&lt;br /&gt;
			if($initvalue == 0 )  # Gerät ganze Zeit aus&lt;br /&gt;
			{&lt;br /&gt;
				$t = 0;&lt;br /&gt;
				Log3 $name, 5, &amp;quot;Gerät ganze Zeit an&amp;quot;;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                my $ut = $hash-&amp;gt;{&amp;quot;.updateTime&amp;quot;};&lt;br /&gt;
                $hash-&amp;gt;{&amp;quot;.updateTime&amp;quot;} = 0;&lt;br /&gt;
		fhem(&amp;quot;setreading $name switch_on_time_sec $t&amp;quot;);&lt;br /&gt;
		&lt;br /&gt;
		my $m = int $t/60;&lt;br /&gt;
		my $s = $t - ($m*60);&lt;br /&gt;
		my $h = int $m/60;&lt;br /&gt;
		$m = $m - ($h*60);&lt;br /&gt;
		my $timestring = sprintf(&amp;quot;%03d:%02d:%02d&amp;quot;,$h,$m,$s);&lt;br /&gt;
		&lt;br /&gt;
		fhem(&amp;quot;setreading $name switch_on_time $timestring (hhh:mm:ss)&amp;quot;);&lt;br /&gt;
		&lt;br /&gt;
		Log3 $name, 3, &amp;quot;$name - switch-on time was $timestring (hhh:mm:ss)&amp;quot;;&lt;br /&gt;
                $hash-&amp;gt;{&amp;quot;.updateTime&amp;quot;} = $ut;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
               &lt;br /&gt;
&lt;br /&gt;
Es werden zwei zusätzliche Readings im Device Rep.powerOnTime generiert, &#039;&#039;&#039;switch_on_time&#039;&#039;&#039; und &#039;&#039;&#039;switch_on_time_sec&#039;&#039;&#039;.&lt;br /&gt;
Das Reading &#039;&#039;&#039;switch_on_time_sec&#039;&#039;&#039; ist die summarische &amp;quot;EIN&amp;quot;-Zeit in Sekunden der letzten 24 Stunden und kann gut zur weiteren Auswertung genutzt werden.&lt;br /&gt;
&#039;&#039;&#039;switch_on_time&#039;&#039;&#039; ist eine in hhh:mm:ss formatierte Angabe des Readingswertes von &#039;&#039;&#039;switch_on_time_sec&#039;&#039;&#039; zur leichteren Lesbarkeit.&lt;br /&gt;
&lt;br /&gt;
Natürlich kann man &#039;&#039;&#039;switch_on_time_sec&#039;&#039;&#039; wiederum loggen um z.B. daraus eine grafische Anzeige zu erstellen, die die Entwicklung der täglichen &amp;quot;EIN&amp;quot;-Zeiten über einen längeren Zeitraum darstellen könnte (z.B. Heizzeiten).&lt;br /&gt;
&lt;br /&gt;
Mit kleinen Abwandlungen könnten zum Beispiel auch die täglichen Raumlüftungszeiten (Fenter &amp;quot;open&amp;quot;, &amp;quot;closed&amp;quot;) ausgewertet und überwacht werden.&lt;br /&gt;
Wird die vorgegeben &amp;quot;open&amp;quot;-Zeit unterschritten, könnte ein Alarm ausgelöst werden.&lt;br /&gt;
&lt;br /&gt;
Wie üblich können die Auswertungszeitgrenzen durch die Zeit-spezifischen Attribute timestamp_begin, timestamp_end usw. den Anforderungen entsprechend abgeändert werden.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Code Snippets]]&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=SSCal_-_Integration_des_Synology_Calendar_Servers&amp;diff=38697</id>
		<title>SSCal - Integration des Synology Calendar Servers</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=SSCal_-_Integration_des_Synology_Calendar_Servers&amp;diff=38697"/>
		<updated>2023-11-09T10:55:33Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: veraltete &amp;quot;source&amp;quot;-Angaben in &amp;quot;syntaxhighlight&amp;quot; geändert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=Integration des Synology Calendar Servers&lt;br /&gt;
|ModType=d&lt;br /&gt;
|ModCmdRef=SSCal&lt;br /&gt;
|ModForumArea=Unterstützende Dienste&lt;br /&gt;
|ModTechName=57_SSCal.pm&lt;br /&gt;
|ModOwner=DS_Starter}}&lt;br /&gt;
&lt;br /&gt;
= Zweckbeschreibung und Voraussetzungen =&lt;br /&gt;
&lt;br /&gt;
Mit diesem Modul erfolgt die Integration des Synology Calendar Servers in FHEM. Die Verbindung zum Kalenderserver erfolgt über eine Session ID nach erfolgreichem Login. Anforderungen/Abfragen des Servers werden intern in einer Queue gespeichert und sequentiell abgearbeitet. Dadurch gehen Kalenderabfragen auch dann nicht verloren, wenn der Synology Kalender zeitweise nicht zur Verfügung stehen sollte.&lt;br /&gt;
Die Kalendereinträge werden im Klartext als Blockeinträge in den Readings aufgelistet.  &lt;br /&gt;
Der Synology Calendar Server ist für den Synology Server Besitzer ein Teil einer private Cloud Lösung.&lt;br /&gt;
&lt;br /&gt;
Es können sowohl Terminkalender (Events) als auch Aufgabenlisten (ToDo&#039;s) abgefragt und verarbeitet werden. Für diese verschiedenen Kalenderarten kann das Modul unterschiedliche Device-Models definieren, Model &#039;&#039;&#039;Diary&#039;&#039;&#039; für Terminkalender und Model &#039;&#039;&#039;Tasks&#039;&#039;&#039; für Aufgabenlisten.&lt;br /&gt;
&lt;br /&gt;
Voraussetzung ist ein installiertes Calendar Package und ein Nutzerkonto mit der Zugehörigkeit zur Gruppe Administratoren auf der Synology DS.&lt;br /&gt;
&lt;br /&gt;
Das Modul benötigt einige FHEM und Perl Standardmodule die installiert sein müssen. Die Commandref zum Modul enthält diese Angaben aktuell. Mit dem [https://fhem.de/commandref.html#Installer Installer-Modul] ist es ebenfalls möglich eventuell fehlende Perl-Module zu ermitteln und ggf. zu installieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Definition eines Synology Kalenderdevices =&lt;br /&gt;
&lt;br /&gt;
[[Datei:sscal1.PNG|right|thumb|200px|initiale Definition]]&lt;br /&gt;
Die Definition erfolgt mit:&lt;br /&gt;
&lt;br /&gt;
 define &amp;lt;Name&amp;gt; SSCal &amp;lt;Adresse Synology Server&amp;gt; [&amp;lt;Port&amp;gt;] [&amp;lt;Protokoll&amp;gt;] [Tasks]&lt;br /&gt;
&lt;br /&gt;
* Port: Port der Synology Diskstation (default 5000)&lt;br /&gt;
* Protokoll: Protokoll zur Kommunikation mit dem Kalender-Server, http oder https (default http)&lt;br /&gt;
* Zusatz Tasks: definiert eine Aufgabenliste anstatt eines Terminkalenders&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Angaben Port, Protokoll und Tasks sind optional. Der Zusatz &#039;&#039;&#039;Tasks&#039;&#039;&#039; definiert ein Aufgabenlisten-Device mit MODEL=Tasks. Per default wird ein Terminkalender-Device mit MODEL=Diary, Port=5000 und Protokoll=http erstellt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispieldefinitionen:&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
 define Appointments SSCal 192.168.2.10               # Terminkalender mit Standardport&lt;br /&gt;
 define Calendar SSCal 192.168.2.10 5001 https        # Terminkalender mit HTTPS-Protokoll&lt;br /&gt;
 define Tasklist SSCAL ds.myds.org 5001 https Tasks   # Aufgabenliste mit HTTPS-Protokoll &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nach der Definition des Devices gibt es zunächst nur den Set-Befehl &#039;&#039;&#039;credentials&#039;&#039;&#039;.&lt;br /&gt;
[[Datei:sscal2.PNG|right|thumb|300px|Kalenderabruf durchgeführt]]&lt;br /&gt;
Mit dem Befehl:&lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;name&amp;gt; credentials &amp;lt;User&amp;gt; &amp;lt;Passwort&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ist im Kalender-Device der für den Kalenderzugriff verwendete Nutzer und dessen Paßwort zu speichern.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; &amp;lt;br&amp;gt;&lt;br /&gt;
Der Nutzer &#039;&#039;&#039;muß&#039;&#039;&#039; Mitglied der Administrator-Group auf der Synology Diskstation sein und muß zusätzlich auch die entsprechend benötigte Berechtigung zum Lesen und/oder Schreiben des/der relevanten Kalender haben. Die Kalenderberechtigungen können direkt in der [https://www.synology.com/de-de/knowledgebase/DSM/help/Calendar/calendar_desc Synology Kalenderapplikation] eingestellt werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind die Credentials korrekt, werden die auf der Synology verfügbaren (und für den Nutzer freigegeben) Kalender automatisch abgerufen.&lt;br /&gt;
Dieser Vorgang ist durch den state &#039;&#039;&#039;running&#039;&#039;&#039; und dem OPMODE &#039;&#039;&#039;listcal&#039;&#039;&#039; in den Internals gekennzeichnet. Nach einem erfolgreichen Abruf, der am Anfang etwas länger dauern kann, springt der Status des Devices auf &#039;&#039;&#039;done&#039;&#039;&#039;. Damit ist das Kalenderdevice grundsätzlich einsatzbereit.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Terminkalender und Aufgabenlisten auswählen und Einträge abrufen =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:sscal3.PNG|right|thumb|300px|Popup von getCalendars]]&lt;br /&gt;
Nach der initialen Definition des Kalenderdevices müssen ein oder mehrere Kalender ausgewählt werden, deren Termine (Events) abgerufen werden sollen.&lt;br /&gt;
Welche Kalender vom Modul erkannt wurden, kann mit dem Befehl&lt;br /&gt;
&lt;br /&gt;
 get &amp;lt;name&amp;gt; getCalendars&lt;br /&gt;
&lt;br /&gt;
ermittelt werden. Die angezeigte Liste enthält sowohl Terminkalender (Type Event) als auch Aufgabenkalender (Type ToDo).&lt;br /&gt;
&lt;br /&gt;
Mit dem Attribut &#039;&#039;&#039;usedCalendars&#039;&#039;&#039; wählt man den/die relevanten Kalender über ein Popup aus. Alternativ kann dem nachfolgend ausgeführten &#039;&#039;&#039;calUpdate&#039;&#039;&#039; Befehl die abzurufende Kalenderliste direkt mitgegeben werden.&lt;br /&gt;
&lt;br /&gt;
Ohne Änderung der Zeitabgrenzung werden die Termine 5 Tage vor und 5 Tage nach dem aktuellen Datum abgerufen. Um diese Zeitgrenzen zu verändern, werden die Attribute &#039;&#039;&#039;cutOlderDays&#039;&#039;&#039; bzw. &#039;&#039;&#039;cutLaterDays&#039;&#039;&#039; verwendet. &lt;br /&gt;
&lt;br /&gt;
Mit dem Befehl:&lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;name&amp;gt; calUpdate [Kalenderliste]&lt;br /&gt;
&lt;br /&gt;
[[Datei:sscal4.PNG|right|thumb|300px|Kalendereinträge abgerufen]]&lt;br /&gt;
werden Terminkalendereinträge manuell abgerufen. Die optional anzugebende Kalenderliste ist eine durch Komma getrennte Liste von abzurufenden Kalendernamen. Die Kalendernamen können Leerzeichen enthalten, z.B.:&lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;name&amp;gt; calUpdate Heikos Kalender,Abfall&lt;br /&gt;
&lt;br /&gt;
Im Standard werden sowohl einmalige, als auch wiederkehrende Events abgerufen und dargestellt. Möchte man die wiederkehrenden Events vom Abruf ausschließen, muss das Attribut &#039;&#039;&#039;showRepeatEvent&#039;&#039;&#039; explizit auf &#039;&#039;&#039;false&#039;&#039;&#039; gestellt werden.&lt;br /&gt;
&lt;br /&gt;
Mit dem Befehl &#039;&#039;&#039;calUpdate&#039;&#039;&#039; werden nur Kalender verarbeitet, die dem definierten Model, &amp;quot;Diary&amp;quot; oder &amp;quot;Tasks&amp;quot;, entsprechen. Kalender abweichenden Typs werden ignoriert.&lt;br /&gt;
&lt;br /&gt;
Aufgaben können Fälligkeitstermine enthalten. Sind diese enthalten, werden Aufgaben deren Fälligkeitstermine sich außerhalb der durch die Attribute &#039;&#039;&#039;cutOlderDays&#039;&#039;&#039; bzw. &#039;&#039;&#039;cutLaterDays&#039;&#039;&#039; festgelegten Zeitgrenzen befinden, gefiltert und nicht dargestellt.&lt;br /&gt;
[[Datei:sscal8.PNG|right|thumb|300px|Kalenderübersicht in Detailanzeige]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:sscal9.PNG|right|thumb|300px|Spalte &amp;quot;Map&amp;quot; mit GPS-Koordinaten Icon]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wurden Termin- bzw. Aufgabenlisten erfolgreich abgerufen, wird per default sowohl in der Raumansicht als auch in der Detailansicht eine Kalenderübersicht angezeigt. Mit den Attributen &#039;&#039;&#039;tableInRoom&#039;&#039;&#039; bzw. &#039;&#039;&#039;tableInDetail&#039;&#039;&#039; können diese Übersichten ausgeschaltet werden (setzen auf &amp;quot;0&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ist in den Terminen ein GPS-Wert gespeichert, wird in der tabellarischen Terminübersicht per default ein Weltkugel-Icon angezeigt, vorausgesetzt man hat auch das Feld &#039;&#039;&#039;Map&#039;&#039;&#039; im Attribut &#039;&#039;&#039;tableFields&#039;&#039;&#039; mit ausgewählt. Ein &amp;quot;Klick&amp;quot; auf dieses Icon öffnet eine neue Browserseite mit den im Termin gespeicherten Koordinaten in Google Maps.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Alle Abrufaufgaben werden zunächst in eine Queue eingestellt, die sequentiell abgearbeitet wird. Sollte der Synology Kalender zum Beispiel während einer Wartung temporär nicht verfügbar sein, erfolgt eine Wiederholung der anstehenden Aufgaben nach einer gewissen Wartezeit. Diese Wartezeit vergrößert sich mit zunehmenden Fehlversuchen.&lt;br /&gt;
&lt;br /&gt;
Wurde für eine Abrufaufgabe ein dauerhafter Fehler diagnostiziert, wird diese Aufgabe von der weiteren Abarbeitung ausgeschlossen und verbleibt zur Dokumentation in der Queue (siehe auch &#039;&#039;&#039;set &amp;lt;name&amp;gt; listSendqueue&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das Reading &#039;&#039;&#039;QueueLenth&#039;&#039;&#039; zeigt die aktuelle Queue-Länge an. Sollten die Einträge nicht auf &amp;quot;0&amp;quot; abgebaut werden, sollte mit &lt;br /&gt;
&lt;br /&gt;
 set &amp;lt;name&amp;gt; listSendqueue &lt;br /&gt;
&lt;br /&gt;
die Queue aufgelistet und analysiert werden, durch welche Fehlerzustände die verbliebenen Einträge nicht abgearbeitet werden konnten.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== non-blocking Verarbeitung ==&lt;br /&gt;
&lt;br /&gt;
Das Kalendermodul ist non-blocking implementiert. In der Definition des Devices sollte die IP-Adresse der Synology Diskstation angegeben werden. Wird statt dessen ein DNS-Name verwendet, ist darauf zu achten im global Device einen validen DNS-Server im Attribut &#039;&#039;&#039;dnsServer&#039;&#039;&#039; zu hinterlegen.&lt;br /&gt;
&lt;br /&gt;
In Abhängigkeit der Menge abgerufener Kalender und Termine kann allerdings die Aufbereitung der Daten sehr aufwändig sein und FHEM dennoch blockieren.&lt;br /&gt;
Um das zu verhindern, kann das Parsing der Kalenderdaten in einen Hintergrundprozess verlagert werden. Dazu ist das Attribut &#039;&#039;&#039;asyncMode=1&#039;&#039;&#039; zu setzen. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== regelmäßiger automatischer Datenabruf ==&lt;br /&gt;
&lt;br /&gt;
Über das Attribut &#039;&#039;&#039;interval&#039;&#039;&#039; wird ein regelmäßigen Abruf der Kalendereinträge ermöglicht. &lt;br /&gt;
Es sind die Sekunden zwischen den Abrufen anzugeben. Mit &#039;&#039;&#039;0&#039;&#039;&#039; wird der automatische Datenabruf ausgeschaltet. Gleiches gilt wenn das Attribut wieder gelöscht wird.&lt;br /&gt;
&lt;br /&gt;
Im Reading &#039;&#039;&#039;nextUpdate&#039;&#039;&#039; wird der Modus &amp;quot;Automatic&amp;quot; und die Zeit des nächsten Abrufes dargestellt, z.B.:  &lt;br /&gt;
&lt;br /&gt;
  nextUpdate  Automatic - next polltime: 09:49:59&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== FHEM Eventgenerierung und Empfehlung zu Attributen ==&lt;br /&gt;
&lt;br /&gt;
Je nach Umfang der abgerufenen Daten können sehr viele Readings erstellt werden. Um eine zu umfangreiche Eventgenerierung in FHEM zu verhindern, ist nach der Definition des Kalenderdevices das Attribut &#039;&#039;&#039;event-on-update-reading&#039;&#039;&#039; voreingestellt auf:&lt;br /&gt;
	&lt;br /&gt;
 attr &amp;lt;SSCal-Device&amp;gt; event-on-update-reading .*Summary.*,state&lt;br /&gt;
&lt;br /&gt;
Es werden demzufolge nur Events für die Terminzusammenfassung und für state erzeugt. Der User kann die Einstellung natürlich seinen Erfordernissen entsprechend anpassen. &lt;br /&gt;
Sollen Events für alle Readings erstellt werden, muss &#039;&#039;&#039;event-on-update-reading&#039;&#039;&#039; auf &#039;&#039;&#039;.*&#039;&#039;&#039; eingestellt werden.&lt;br /&gt;
&lt;br /&gt;
Nach dem Abruf von Terminen oder Aufgaben wird per default eine tabellarische Übersicht sowohl in der Raumsicht als auch in der Datailansicht erstellt. Will man diese Übersichten abschalten, sind dazu die Attribute &#039;&#039;&#039;tableInRoom&#039;&#039;&#039; bzw. &#039;&#039;&#039;tableInDetail&#039;&#039;&#039; explizit auf &amp;quot;0&amp;quot; zu setzen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Empfehlung für das Setzen des Attributs &#039;&#039;&#039;stateFormat&#039;&#039;&#039;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;SSCal-Device&amp;gt; stateFormat &amp;lt;b&amp;gt;Status:&amp;lt;/b&amp;gt; done - &amp;lt;b&amp;gt;Last Update&amp;lt;/b&amp;gt;: 2020-02-02 19:57:47 - &amp;lt;b&amp;gt;Next Update&amp;lt;/b&amp;gt;: Automatic - next polltime: 20:57:46&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für die Funktionen des Moduls ist die UID eines Events nicht notwendig. Somit wird das Reading x_x_IcalUID nicht benötigt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr &amp;lt;SSCal-Device&amp;gt; suppressReading .*_95_IcalUID&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Schema der erzeugten Readings =&lt;br /&gt;
&lt;br /&gt;
Die Termine der abgerufenen Kalender werden in Blöcken erzeugt. &lt;br /&gt;
Jeder Block steht für einen Termin, dessen einzelne Eigenschaften mit einer laufenden Nummer vor dem Readingnamen gekennzeichnet sind.&lt;br /&gt;
&lt;br /&gt;
Diese laufende Nummer ist für den jeweiligen Readingnamen immer gleich. Da es für einen Termin eine oder auch mehrere Erinnerungstermine geben kann, wird das Reading &#039;&#039;&#039;notifyDateTime&#039;&#039;&#039; zusätzlich von einem laufenden Index angeführt.&lt;br /&gt;
[[Datei:sscal5.PNG|right|thumb|500px|Schema der Readings]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das allgemeine Schema der erzeugten Readings ist:&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;Blocknummer&amp;gt;_&amp;lt;Readingnummer&amp;gt;_&amp;lt;Readingname&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Zum Beispiel für die Anfangszeit und Endezeit eines Termins:&lt;br /&gt;
 &lt;br /&gt;
 0_02_Begin 2020-01-15 09:30:00&lt;br /&gt;
 0_03_End   2020-01-15 10:30:00&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das Reading &#039;&#039;&#039;notifyDateTime&#039;&#039;&#039; wird noch um einen Index ergänzt:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;Blocknummer&amp;gt;_&amp;lt;Readingnummer&amp;gt;_&amp;lt;Index&amp;gt;_&amp;lt;notifyDateTime&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zum Beispiel:&lt;br /&gt;
&lt;br /&gt;
 0_14_0_notifyDateTime 2020-01-15 09:25:00&lt;br /&gt;
 0_14_1_notifyDateTime 2020-01-15 03:30:00&lt;br /&gt;
 0_14_2_notifyDateTime 2020-01-14 09:30:00&lt;br /&gt;
 0_14_3_notifyDateTime 2020-01-12 09:30:00&lt;br /&gt;
 0_14_4_notifyDateTime 2020-01-11 09:30:00&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Set-Befehle =&lt;br /&gt;
&lt;br /&gt;
; calUpdate: Die Einträge der ausgewählten Kalender werden abgerufen. Die relevanten Kalender werden im Attribut usedCalendars angegeben. Alternativ können ein oder mehrere Kalender als eine durch Komma getrennte Liste dem Befehl direkt übergeben werden, z.B.:&lt;br /&gt;
&lt;br /&gt;
::: set &amp;lt;name&amp;gt; calUpdate Heikos Kalender,Abfall&lt;br /&gt;
&lt;br /&gt;
: Die Kalendernamen können Leerzeichen enthalten. Welche Kalender erkannt wurden, kann mit dem Befehl&lt;br /&gt;
&lt;br /&gt;
::: get &amp;lt;name&amp;gt; getCalendars&lt;br /&gt;
&lt;br /&gt;
: ermittelt werden. Es werden nur die Kalender abgerufen, deren Typ zum Model des SSCal-Devices passen. D.h. ist das Model &#039;&#039;&#039;Diary&#039;&#039;&#039;, werden Kalender vom Typ &#039;&#039;&#039;Event&#039;&#039;&#039; verarbeitet und das Model &#039;&#039;&#039;Tasks&#039;&#039;&#039; verarbeitet Kalender des Typs &#039;&#039;&#039;ToDo&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
; cleanCompleteTasks (nur Model &amp;quot;Tasks&amp;quot;): In den selektierten Aufgabenlisten (siehe Attribut usedCalendars) werden alle abgeschlossenen Aufgaben gelöscht.&lt;br /&gt;
&lt;br /&gt;
; deleteEventId: die angegebene Event Id (siehe Reading x_x_EventId) wird aus dem Kalender bzw. der Aufgabenliste gelöscht. Die aktuell ermittelten Event Id&#039;s werden über eine Drop-Down Liste zur Auswahl bereitgestellt.&lt;br /&gt;
&lt;br /&gt;
; credentials: Speicherung der Zugangsdaten.&lt;br /&gt;
::: set &amp;lt;name&amp;gt; credentials User Passwort&lt;br /&gt;
&lt;br /&gt;
; eraseReadings: Löscht alle Kalenderreadings&lt;br /&gt;
&lt;br /&gt;
; listSendqueue: Zeigt alle Einträge in der Sendqueue. Die Queue ist normalerweise nur kurzfristig gefüllt, kann aber im Problemfall dauerhaft Einträge enthalten. Dadurch kann der bei der jeweiligen Abrufaufgabe aufgetretene Fehler ermittelt werden.&lt;br /&gt;
&lt;br /&gt;
; logout: Der User wird ausgeloggt und die Session beendet&lt;br /&gt;
&lt;br /&gt;
; purgeSendqueue: löscht Einträge in der Sendequeue. Es stehen verschiedene Optionen ja nach Situation zur Verfügung:&lt;br /&gt;
::: -all- = löscht alle in der Sendequeue vorhandenen Einträge&lt;br /&gt;
::: -permError- = löscht alle Einträge, die durch einen permanenten Error von der weiteren Verarbeitung ausgeschlossen sind&lt;br /&gt;
::: -&amp;lt;Index&amp;gt;- = löscht einen eindeutigen Eintrag der Sendequeue&lt;br /&gt;
&lt;br /&gt;
; restartSendqueue: Die Abarbeitung der Einträge in der Sendequeue wird manuell neu angestoßen. Dies ist normalerweise nicht notwendig. Die Sendequeue wird bei der Initialisierung jeder neuen Aufgabe implizit neu gestartet.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Get-Befehle =&lt;br /&gt;
&lt;br /&gt;
[[Datei:sscal7.PNG|right|thumb|300px|get calAsHtml Popup]]&lt;br /&gt;
;apiInfo: Ruft die API Informationen des Synology Calendars ab und öffnet ein Popup mit diesen Informationen.&lt;br /&gt;
&lt;br /&gt;
;calAsHtml: Zeigt ein Popup mit einer Übersicht der Termine/Aufgaben. In eigenen Perl-Routinen (z.B. bei Einbindung in weblink) kann die Übersicht abgerufen mit:&lt;br /&gt;
::: { SSCal_calAsHtml (&amp;quot;&amp;lt;SSCal-Device&amp;gt;&amp;quot;) } &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;getCalendars: Ruft die auf der Synology vorhandenen Kalender ab und öffnet ein Popup mit Informationen über die jeweiligen Kalender.&lt;br /&gt;
&lt;br /&gt;
;storedCredentials: zeigt die gespeicherten User/Passwort Kombination&lt;br /&gt;
&lt;br /&gt;
;versionNotes: Zeigt Informationen und Hilfen zum Modul&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Attribute =&lt;br /&gt;
&lt;br /&gt;
;asyncMode: wenn &amp;quot;1&amp;quot; wird das Datenparsing in einen Hintergrundprozess ausgelagert und vermeidet Blockierungssituationen&lt;br /&gt;
&lt;br /&gt;
;createATDevs: wenn &amp;quot;1&amp;quot; werden bei der Erkennung von FHEM-Kommandos bzw. auszuführenden Perl-Routinen im Kalendereintrag durch SSCal automatisiert at-Devices zur termingerechten Ausführung dieser Kommandos erstellt, geändert und gelöscht. Lesen sie bitte dazu die detailliierte Beschreibung im Abschnitt [[SSCal - Integration des Synology Calendar Servers#at-Devices für Steuerungen automatisch erstellen und verwalten lassen | at-Devices für Steuerungen automatisch erstellen und verwalten lassen]]  &lt;br /&gt;
&lt;br /&gt;
;cutOlderDays: Terminkalendereinträge und Aufgabenkalendereinträge mit Fälligkeitstermin älter als die angegeben Tage werden von der Verarbeitung ausgeschlossen (default: 5)&lt;br /&gt;
::: attr &amp;lt;name&amp;gt; cutOlderDays 30 &lt;br /&gt;
&lt;br /&gt;
;cutLaterDays: Terminkalendereinträge und Aufgabenkalendereinträge mit Fälligkeitstermin später als die angegeben Tage werden von der Verarbeitung ausgeschlossen (default: 5)&lt;br /&gt;
::: attr &amp;lt;name&amp;gt; cutLaterDays 90 &lt;br /&gt;
&lt;br /&gt;
;filterCompleteTask (nur Model &amp;quot;Tasks&amp;quot;): Es werden Einträge in Aufgabenkalendern entsprechend der Fertigstellung gefiltert:&lt;br /&gt;
::: 1 = nur fertig gestellte Aufgaben werden angezeigt &lt;br /&gt;
::: 2 = nur nicht fertige Aufgaben werden angezeigt&lt;br /&gt;
::: 3 = es werden fertige und nicht fertige Aufgaben angezeigt (default)&lt;br /&gt;
&lt;br /&gt;
;filterDueTask (nur Model &amp;quot;Tasks&amp;quot;): Es werden Einträge in Aufgabenkalendern mit/ohne Fälligkeit gefiltert:&lt;br /&gt;
::: 1 = nur Einträge mit Fälligkeitstermin werden angezeigt &lt;br /&gt;
::: 2 = nur Einträge ohne Fälligkeitstermin werden angezeigt&lt;br /&gt;
::: 3 = es werden Einträge mit und ohne Fälligkeitstermin angezeigt (default)&lt;br /&gt;
&lt;br /&gt;
;interval: Automatischer Abrufintervall der Kalendereintträge in Sekunden. Ist &amp;quot;0&amp;quot; agegeben, wird kein automatischer Datenabruf ausgeführt. Soll jede Stunde die Einträge der gewählten Kalender abgerufen werden, wird das Attribut wie folgt gesetzt:&lt;br /&gt;
::: attr &amp;lt;name&amp;gt; interval 3600&lt;br /&gt;
&lt;br /&gt;
;loginRetries: Anzahl der Versuche für das inititiale User login (default: 3)&lt;br /&gt;
&lt;br /&gt;
;showRepeatEvent (nur Model &amp;quot;Diary&amp;quot;): Wenn &amp;quot;true&amp;quot;, werden neben einmaligen Terminen ebenfalls wiederkehrende Termine ausgewertet. (default: true) &lt;br /&gt;
&lt;br /&gt;
;showPassInLog: Wenn &amp;quot;1&amp;quot;, wird das Passwort bzw. die SID im Log mit angezeigt. (default: 0)&lt;br /&gt;
&lt;br /&gt;
;tableColumnMap: Legt fest, wie der Link zur Karte in der Tabellspalte &amp;quot;Map&amp;quot; bzw. &amp;quot;Karte&amp;quot; gestaltet wird.&lt;br /&gt;
::: icon - es wird ein durch den User anpassbares Symbol angezeigt (default)&lt;br /&gt;
::: data - es werden die GPS-Daten angezeigt&lt;br /&gt;
::: text - es wird ein durch den Nutzer einstellbarer Text verwendet&lt;br /&gt;
&lt;br /&gt;
Der Nutzer kann weitere Anpassungen des verwendeten Icons oder Textes in den Eigenschaften des Attributs &amp;quot;tableSpecs&amp;quot; vornehmen. Siehe dazu Kapitel [[SSCal_-_Integration_des_Synology_Calendar_Servers#Darstellung_der_.C3.9Cbersichtstabelle_in_Raum-_und_Detailansicht_beeinflussen | Darstellung der Übersichtstabelle in Raum- und Detailsicht beeinflussen]]&lt;br /&gt;
&lt;br /&gt;
;tableInDetail: Eine Termin/Aufgabenübersicht wird in der Detailansicht erstellt (default: 1) bzw. ausgeschaltet (0).&lt;br /&gt;
&lt;br /&gt;
;tableInRoom: Eine Termin/Aufgabenübersicht wird in der Raumansicht erstellt (default: 1) bzw. ausgeschaltet (0).&lt;br /&gt;
&lt;br /&gt;
;tableFields: Auswahl der in der Termin/Aufgabenübersicht (Raum- bzw. Detailansicht) anzuzeigenden Felder über eine Drop-Down Liste&lt;br /&gt;
&lt;br /&gt;
;tableSpecs: Über verschiedene Schlüssel-Wertpaar Kombinationen kann die Darstellung der Informationen in der Übersichtstabelle angepasst werden. Das Kapitel [[SSCal_-_Integration_des_Synology_Calendar_Servers#Darstellung_der_.C3.9Cbersichtstabelle_in_Raum-_und_Detailansicht_beeinflussen | Darstellung der Übersichtstabelle in Raum- und Detailsicht beeinflussen]] liefert detailiierte Informationen dazu.&lt;br /&gt;
&lt;br /&gt;
;timeout: Timeout für den Datenabruf in Sekunden. (default: 20)&lt;br /&gt;
&lt;br /&gt;
;usedCalendars: Auswahl der abzurufenden Kalender über ein Popup. Die Liste der Kalender wird beim Start des Moduls initial gefüllt, kann danach aber ebenfalls durch den Befehl &amp;quot;get &amp;lt;name&amp;gt; getCalendars&amp;quot; manuell ausgeführt werden. Wurde noch kein erfolgreicher Kalenderabruf ausgeführt, enthält dieses Attribut lediglich den Eintrag &lt;br /&gt;
::: --wait for Calendar list--&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Darstellung der Übersichtstabelle in Raum- und Detailansicht beeinflussen =&lt;br /&gt;
&lt;br /&gt;
Im Standard wwird sowohl in der Raum- als auch Detailansicht eine Tabelle mit den aktuell abgerufenen Terminen bzw. Aufgaben angezeigt. Die verwendeten Spalten der Tabelle sind vorbelegt, können aber durch das Attribut:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;Device&amp;gt; tableFields &lt;br /&gt;
&lt;br /&gt;
verändert werden. Es wird eine Drop-Down-Liste mit einer Auswahl der möglichen Tabellenfelder bereitgestellt.&lt;br /&gt;
&lt;br /&gt;
Das Attribut &#039;&#039;&#039;tableSpecs&#039;&#039;&#039; besteht aus Schlüssel-Wert Paaren, die in &#039;&#039;&#039;{ }&#039;&#039;&#039; eingeschlossen werden müssen und miteinander kombiniert sein können. &lt;br /&gt;
Weiterhin können Schlüssel auch Subschlüssel enthalten, die ebenfalls in &#039;&#039;&#039;{ }&#039;&#039;&#039; eingeschlossen werden. In den nachfolgenden Beispielen wird die Verwendung vorgestellt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Allgemeine Gestaltung des Tabellenheaders und der Spalten ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Mit den Subschlüsseln &#039;&#039;&#039;noHeader&#039;&#039;&#039; =&amp;gt; 1 kann die Headerzeile der Tabelle ausgeschaltet werden. Der Subschlüssel &#039;&#039;&#039;headerAlign&#039;&#039;&#039; dient der Ausrichtung der Headerspalten und &#039;&#039;&#039;columnAlign&#039;&#039;&#039; der Ausrichtung der Inhaltsspalten. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Inhalt Attribut tableSpecs: &amp;lt;br&amp;gt; Allgemeine Gestaltung des Tabellenheaders und der Spalten !! Erläuterungen !! Aussehen &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;width:55%&amp;quot; |&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{ 						 &lt;br /&gt;
  &amp;quot;cellStyle&amp;quot;  =&amp;gt; {&lt;br /&gt;
                    &amp;quot;noHeader&amp;quot;    =&amp;gt; &amp;quot;1&amp;quot;,&lt;br /&gt;
                    &amp;quot;headerAlign&amp;quot; =&amp;gt; &amp;quot;center&amp;quot;,&lt;br /&gt;
                    &amp;quot;columnAlign&amp;quot; =&amp;gt; &amp;quot;left&amp;quot;,&lt;br /&gt;
                  },&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
| &#039;&#039;&#039;noHeader 1&#039;&#039;&#039; verbirgt die Headerzeile, &#039;&#039;&#039;noHeader 0&#039;&#039;&#039; zeigt sie an (Standard). Die Subschlüssel &#039;&#039;&#039;headerAlign&#039;&#039;&#039; und &#039;&#039;&#039;columnAlign&#039;&#039;&#039; können die Werte left, center und right annehmen und dienen der Ausrichtung der Spalten im Header bzw. Body der Tabelle. &lt;br /&gt;
&lt;br /&gt;
Der Subschlüssel &#039;&#039;&#039;columnAlign&#039;&#039;&#039; legt zunächst die Ausrichtung für alle Spalten des Tabellbodys fest. Die Spaltenausrichtung kann aber zusätzlich für jede Spalte spezifisch eingestellt werden, wie im nachfolgenden Beispiel gezeigt.&lt;br /&gt;
| [[Datei:sscal25.PNG|200px]]&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{ 						 &lt;br /&gt;
  &amp;quot;cellStyle&amp;quot;             =&amp;gt; {&lt;br /&gt;
                               &amp;quot;noHeader&amp;quot;            =&amp;gt; &amp;quot;0&amp;quot;,&lt;br /&gt;
                               &amp;quot;headerAlign&amp;quot;         =&amp;gt; &amp;quot;center&amp;quot;,&lt;br /&gt;
                               &amp;quot;columnAlign&amp;quot;         =&amp;gt; &amp;quot;left&amp;quot;,&lt;br /&gt;
                               &amp;quot;columnSymbolAlign&amp;quot;   =&amp;gt; &amp;quot;center&amp;quot;,&lt;br /&gt;
                               &amp;quot;columnDaysLeftAlign&amp;quot; =&amp;gt; &amp;quot;center&amp;quot;,&lt;br /&gt;
                             },&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
| Die &#039;&#039;&#039;Ausrichtung&#039;&#039;&#039; jeder Spalte kann &#039;&#039;&#039;separat&#039;&#039;&#039; erfolgen. Die Subschlüssel dafür heißen &#039;&#039;&#039;column&amp;lt;Spaltenname&amp;gt;Align&#039;&#039;&#039;. Demzufolge betreffen die im Beispiel dargestellten Subschlüssel &#039;&#039;&#039;columnSymbolAlign&#039;&#039;&#039; und &#039;&#039;&#039;columnDaysLeftAlign&#039;&#039;&#039; die Spalten &#039;&#039;&#039;Symbol&#039;&#039;&#039; sowie &#039;&#039;&#039;DaysLeft&#039;&#039;&#039; und werden abweichend von Standard zentriert dargestellt. Die Werte können &#039;&#039;&#039;left&#039;&#039;&#039;, &#039;&#039;&#039;center&#039;&#039;&#039; oder &#039;&#039;&#039;right&#039;&#039;&#039; sein.&lt;br /&gt;
&lt;br /&gt;
Die weiteren Subschlüssel zur Ausrichtung der Spalten heißen dementsprechend:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| columnBeginAlign&lt;br /&gt;
| columnEndAlign&lt;br /&gt;
|-&lt;br /&gt;
| columnDaysLeftLongAlign&lt;br /&gt;
| columnWeekdayAlign&lt;br /&gt;
|-&lt;br /&gt;
| columnTimezoneAlign&lt;br /&gt;
| columnSummaryAlign&lt;br /&gt;
|-&lt;br /&gt;
| columnDescriptionAlign&lt;br /&gt;
| columnStatusAlign&lt;br /&gt;
|-&lt;br /&gt;
| columnCompletionAlign&lt;br /&gt;
| columnLocationAlign&lt;br /&gt;
|-&lt;br /&gt;
| columnMapAlign&lt;br /&gt;
| columnCalendarAlign&lt;br /&gt;
|-&lt;br /&gt;
| columnEventIdAlign&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
| [[Datei:sscal26.PNG|200px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Gestaltung der Spalte &amp;quot;Map&amp;quot; bzw. &amp;quot;Karte&amp;quot; ==&lt;br /&gt;
&lt;br /&gt;
In der Spalte &#039;&#039;&#039;Map&#039;&#039;&#039; bzw. &#039;&#039;&#039;Karte&#039;&#039;&#039; wird bei Vorhandensein von GPS-Daten ein Link zur Karte von &#039;&#039;&#039;Google Maps&#039;&#039;&#039; (default) oder &#039;&#039;&#039;OpenStreetMap&#039;&#039;&#039; angeboten.&lt;br /&gt;
Die Auswahl, welcher Kartenprovider verwendet werden soll, erfolgt über den Schlüssel &#039;&#039;&#039;columnMapProvider&#039;&#039;&#039; im Attribut &#039;&#039;&#039;tableSpecs&#039;&#039;&#039;.&lt;br /&gt;
Der Wert in der Spalte Map kann als Icon (default), Text oder der GPS-Daten selbst dargestellt werden. Das Attribut &#039;&#039;&#039;tableColumnMap&#039;&#039;&#039; legt fest, wie der Wert dargestellt wird:&lt;br /&gt;
&lt;br /&gt;
  attr &amp;lt;Device&amp;gt; tableColumnMap &amp;lt;icon | data | text&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Über folgende Schüssel wird das verwendete Icon bzw. ein eigener Link-Text festgelegt und der Kartenprovider ausgewählt:&lt;br /&gt;
  &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Inhalt Attribut tableSpecs: &amp;lt;br&amp;gt; Gestaltung Spalte &amp;quot;Map&amp;quot; !! Erläuterungen !! Aussehen &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;width:45%&amp;quot; |&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{ &lt;br /&gt;
  &amp;quot;columnMapIcon&amp;quot;         =&amp;gt; &amp;quot;rc_WEB&amp;quot;,&lt;br /&gt;
  &amp;quot;columnMapText&amp;quot;         =&amp;gt; &amp;quot;Hier gehts zur Karte&amp;quot;,&lt;br /&gt;
  &amp;quot;columnMapProvider&amp;quot;     =&amp;gt; &amp;quot;GoogleMaps&amp;quot;,&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
| Der Icon-Dateiname im Schlüssel &#039;&#039;&#039;columnMapIcon&#039;&#039;&#039; wird ohne Endung angegeben. Im Schlüssel &#039;&#039;&#039;columnMapProvider&#039;&#039;&#039; kann &amp;quot;OpenStreetMap&amp;quot; oder &amp;quot;GoogleMaps&amp;quot; enthalten sein.&lt;br /&gt;
| [[Datei:sscal10.PNG|200px]]&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;width:45%&amp;quot; |&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{ &lt;br /&gt;
  &amp;quot;columnMapIcon&amp;quot;         =&amp;gt; &amp;quot;rc_WEB@red&amp;quot;,&lt;br /&gt;
  &amp;quot;columnMapText&amp;quot;         =&amp;gt; &amp;quot;Hier gehts zur Karte&amp;quot;,&lt;br /&gt;
  &amp;quot;columnMapProvider&amp;quot;     =&amp;gt; &amp;quot;GoogleMaps&amp;quot;,&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
| Das Icon kann eingefärbt werden. Entweder mit der Farbangabe hinter &#039;&#039;&#039;@&#039;&#039;&#039; oder dem Farbcode wie &#039;&#039;&#039;@#DF0101&#039;&#039;&#039;&lt;br /&gt;
| [[Datei:sscal11.PNG|200px]]&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{ &lt;br /&gt;
  &amp;quot;columnMapIcon&amp;quot;         =&amp;gt; {&lt;br /&gt;
                               &amp;quot;Status&amp;quot; =&amp;gt; &amp;quot;eq &#039;ended&#039; &amp;quot;,&lt;br /&gt;
                               &amp;quot;icon&amp;quot;   =&amp;gt; &amp;quot;rc_WEB@grey&amp;quot;,                                &lt;br /&gt;
                             },&lt;br /&gt;
  &amp;quot;columnMapProvider&amp;quot;     =&amp;gt; &amp;quot;GoogleMaps&amp;quot;,&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
| Das Icon wird in &amp;quot;rc_WEB geändert und grau eingefärbt, wenn eine zweite Bedingung wahr ist. Der Schlüssel der zweiten Bedingung ist ein Readingname ohne Block- und Readingnummer gefolgt von einer Bedingung (&amp;quot;eq&amp;quot;) und einem Wert (&amp;quot;ended&amp;quot;) auf den geprüft wird.&lt;br /&gt;
Ist die Bedingung unwahr, wird das Standardicon eingefügt.  &lt;br /&gt;
| [[Datei:sscal12.PNG|200px]]&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{ &lt;br /&gt;
  &amp;quot;columnMapIcon&amp;quot;     =&amp;gt; [&lt;br /&gt;
                         {&lt;br /&gt;
                           &amp;quot;Status&amp;quot; =&amp;gt; &amp;quot;eq &#039;ended&#039; &amp;quot;,&lt;br /&gt;
                           &amp;quot;icon&amp;quot;   =&amp;gt; &amp;quot;rc_WEB@grey&amp;quot;,                                &lt;br /&gt;
                         },&lt;br /&gt;
                         {&lt;br /&gt;
                           &amp;quot;Status&amp;quot; =&amp;gt; &amp;quot;eq &#039;upcoming&#039; &amp;quot;,&lt;br /&gt;
                           &amp;quot;icon&amp;quot;   =&amp;gt; &amp;quot;rc_WEB@red&amp;quot;,&lt;br /&gt;
                         }&lt;br /&gt;
                         ], &lt;br /&gt;
  &amp;quot;columnMapText&amp;quot;      =&amp;gt; &amp;quot;Hier gehts zur Karte&amp;quot;,&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
| Es können mehrere Bedingungen angegeben werden. Diese werden in Gruppen angegeben. Die Gruppen werden von oben nach unten abgearbeitet. Ist eine Gruppe wahr, wird der Wert im Schlüssel &amp;quot;icon&amp;quot; zurück gegeben. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Eine Gruppe ist in &#039;&#039;&#039;[ ]&#039;&#039;&#039; einzufügen.&lt;br /&gt;
&lt;br /&gt;
Es können je Gruppe weitere Bedingungen hinzugefügt werden, die alle &amp;quot;wahr&amp;quot; sein müssen um das in dieser Gruppe eingetragene Icon zurück zu geben. Der Schlüssel der Bedingung ist immer ein Readingname ohne Block- und Readingnummer gefolgt von einer Bedingung und dem Wert zum Vergleich. Zum Beispiel &amp;quot;daysLeft&amp;quot; wenn das Reading &amp;quot;x_x_daysLeft&amp;quot; ausgewertet werden soll. Das Modul übernimmt selbstständig die korrekte Zuweisung des Readings im aktuellen Block.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
| [[Datei:sscal13.PNG|200px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mit dem Schlüssel &#039;&#039;&#039;columnMapText&#039;&#039;&#039; wird ein eigener Text für den Karten-Link in Spalte Map hinterlegt. Damit der Text anstatt eines Icon dargestellt wird, schaltet man diese Option mit dem Attribut  &lt;br /&gt;
&lt;br /&gt;
  attr &amp;lt;Device&amp;gt; tableColumnMap text&lt;br /&gt;
&lt;br /&gt;
ein. Im Schlüssel columnMapText können verschiedene vordefinierte Variablen verwendet werden:&lt;br /&gt;
&lt;br /&gt;
  $NAME - der Name des SSCal-Devices&lt;br /&gt;
  $BNR  - Blocknummer eines Readings&lt;br /&gt;
  $we   - siehe holiday2we&lt;br /&gt;
  $hms  - Zeit im sprintf-Format &amp;quot;hh:mm:ss&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
  $sec, $min, $hour, $mday, $month, $year, $wday, $yday, $isdst - siehe Perl localtime&lt;br /&gt;
&lt;br /&gt;
Der Schlüssel wird dann wie folgt definiert:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Inhalt Attribut tableSpecs: &amp;lt;br&amp;gt; Gestaltung Spalte &amp;quot;Map&amp;quot; als Text !! Erläuterungen !! Aussehen &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;width:50%&amp;quot; |&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{ 						 &lt;br /&gt;
  &amp;quot;columnMapText&amp;quot;         =&amp;gt; &amp;quot;Hier gehts zur Karte&amp;quot;,&lt;br /&gt;
  &amp;quot;columnMapProvider&amp;quot;     =&amp;gt; &amp;quot;OpenStreetMap&amp;quot;,&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
| Der Text im Schlüssel &amp;quot;columnMapText&amp;quot; wird als Linktext in der Spalte &amp;quot;Map&amp;quot; verwendet.&lt;br /&gt;
| [[Datei:sscal14.PNG|200px]]&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{ 						 &lt;br /&gt;
  &amp;quot;columnMapText&amp;quot;         =&amp;gt; &amp;quot;{ ReadingsVal(&#039;$NAME&#039;, &#039;$BNR_35_Location&#039;,&#039;&#039;) }&amp;quot;,&lt;br /&gt;
  &amp;quot;columnMapProvider&amp;quot;     =&amp;gt; &amp;quot;OpenStreetMap&amp;quot;,&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
| Im Schlüssel &amp;quot;columnMapText&amp;quot; kann eine Perl-Routine (eingeschlossen in &#039;&#039;&#039;{ }&#039;&#039;&#039;) hinterlegt werden, die einen Text zurückliefert. In diesem Beispiel wird als Linktext der Inhalt des Readings &#039;&#039;&#039;Location&#039;&#039;&#039; benutzt und wird als anklickbaren Text in der Spalte &amp;quot;Map&amp;quot; angezeigt. Die &amp;quot;35&amp;quot; vor dem Readingnamen &amp;quot;Location&amp;quot; ist die Readingnummer (siehe Kapitel [[SSCal - Integration des Synology Calendar Servers#Schema der erzeugten Readings | Schema der erzeugten Readings]]). &lt;br /&gt;
| [[Datei:sscal15.PNG|200px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Gestaltung der Spalte &amp;quot;Days left&amp;quot; bzw. &amp;quot;Resttage&amp;quot; ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Die Spalte &amp;quot;Resttage&amp;quot; zeigt die verbleibende Zeit bis zum Eintritt des Termins. Ist der Termin beendet bzw. in der Vergangenheit, bleibt diese Spalte leer.&lt;br /&gt;
&lt;br /&gt;
Um diese Spalte als Icon darzustellen, wird der Schlüssel &#039;&#039;&#039;columnDaysLeftIcon&#039;&#039;&#039; verwendet. Es können mehrere Subschlüssel angewendet werden die logisch durch &#039;&#039;&#039;und&#039;&#039;&#039; verknüpft sind. D.h. alle Bedingungen der Subschlüssel müssen wahr werden damit die Gruppe wahr wird.&lt;br /&gt;
&lt;br /&gt;
Dabei können mehrere Gruppen von Subschlüsseln verwendet werden um abhängig von unterschiedlichen Readingwerten das resultierende Icon zu wählen oder einzufärben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Inhalt Attribut tableSpecs: &amp;lt;br&amp;gt; Gestaltung Spalte &amp;quot;Resttage&amp;quot; als Icon !! Erläuterungen !! Aussehen &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;width:55%&amp;quot; |&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{ 						 &lt;br /&gt;
  &amp;quot;columnDaysLeftIcon&amp;quot;    =&amp;gt; {&lt;br /&gt;
                               &amp;quot;Summary&amp;quot;  =&amp;gt; &amp;quot;=~ /[Tt]onne|Restabfall/&amp;quot;,&lt;br /&gt;
                               &amp;quot;Status&amp;quot;   =&amp;gt; &amp;quot;ne &#039;ended&#039; &amp;quot;,&lt;br /&gt;
                               &amp;quot;icon&amp;quot;     =&amp;gt; &amp;quot;Tonne_green&amp;quot;,&lt;br /&gt;
                             },&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
| Der Text im Reading &amp;quot;x_x_Summary&amp;quot; wird ausgewertet und ergibt &#039;&#039;&#039;wahr&#039;&#039;&#039; wenn er &amp;quot;Tonne&amp;quot; oder &amp;quot;tonne&amp;quot; oder &amp;quot;Reastabfall&amp;quot; im String trägt. &lt;br /&gt;
Der Inhalt des Readings &amp;quot;x_x_Status&amp;quot; muß ungleich &amp;quot;ended&amp;quot; sein damit diese Auswertung &#039;&#039;&#039;wahr&#039;&#039;&#039; wird. &lt;br /&gt;
&lt;br /&gt;
Beide Bedingen müssen &#039;&#039;&#039;wahr&#039;&#039;&#039; sein, damit das angegeben &amp;quot;Icon&amp;quot; in der Spalte angezeigt wird. Deswegen wird in den ersten zwei Zeilen der Tabelle kein Tonnen-Icon eingefügt.&lt;br /&gt;
| [[Datei:sscal16.PNG|200px]]&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{ 						 &lt;br /&gt;
  &amp;quot;columnDaysLeftIcon&amp;quot;    =&amp;gt; [&lt;br /&gt;
                             {&lt;br /&gt;
                               &amp;quot;Summary&amp;quot;  =&amp;gt; &amp;quot;=~ /Gelbe Tonne/&amp;quot;,&lt;br /&gt;
                               &amp;quot;icon&amp;quot;     =&amp;gt; &amp;quot;dustbin@#DF7401&amp;quot;,    &lt;br /&gt;
                             },&lt;br /&gt;
                             {&lt;br /&gt;
                               &amp;quot;Summary&amp;quot;  =&amp;gt; &amp;quot;=~ /Biotonne/&amp;quot;,&lt;br /&gt;
                               &amp;quot;icon&amp;quot;     =&amp;gt; &amp;quot;dustbin@brown&amp;quot;,    &lt;br /&gt;
                             },	&lt;br /&gt;
                             {&lt;br /&gt;
                               &amp;quot;Summary&amp;quot;  =&amp;gt; &amp;quot;=~ /Restabfall/&amp;quot;,&lt;br /&gt;
                               &amp;quot;icon&amp;quot;     =&amp;gt; &amp;quot;dustbin@black&amp;quot;,&lt;br /&gt;
                             },&lt;br /&gt;
                             {&lt;br /&gt;
                               &amp;quot;Summary&amp;quot;  =&amp;gt; &amp;quot;=~ /Papier/&amp;quot;,&lt;br /&gt;
                               &amp;quot;icon&amp;quot;     =&amp;gt; &amp;quot;dustbin@blue&amp;quot;,&lt;br /&gt;
                             },&lt;br /&gt;
                             {&lt;br /&gt;
                               &amp;quot;Status&amp;quot;   =&amp;gt; &amp;quot;=~ /ended/&amp;quot;,&lt;br /&gt;
                               &amp;quot;icon&amp;quot;     =&amp;gt; &amp;quot;dustbin@grey&amp;quot;,&lt;br /&gt;
                             },&lt;br /&gt;
                             ],&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
| Der Schlüssel &#039;&#039;&#039;columnDaysLeftIcon&#039;&#039;&#039; kann einen oder mehrere Subschlüssel enthalten. &lt;br /&gt;
Mehrere Subschlüssel werden wie hier dargestellt als Gruppe zusammengefasst und in [ ] eingeschlossen. Im Beispiel wird der Text im Reading &amp;quot;x_x_Summary&amp;quot; ausgewertet und wenn die Bedingung zutrifft das Icon und dessen Farbe entsprechend gesetzt.&lt;br /&gt;
 &lt;br /&gt;
Die Gruppen werden von oben nach unten abgearbeitet. Die letzte &amp;quot;wahre&amp;quot; Gruppe siegt. &lt;br /&gt;
| [[Datei:sscal17.PNG|200px]]&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{ 						 &lt;br /&gt;
  &amp;quot;columnDaysLeftIcon&amp;quot;    =&amp;gt; [&lt;br /&gt;
                             {&lt;br /&gt;
                               &amp;quot;Status&amp;quot;   =&amp;gt; &amp;quot;!~ /ended/ &amp;quot;,&lt;br /&gt;
                               &amp;quot;daysLeft&amp;quot; =&amp;gt; &amp;quot;&amp;gt;= 2&amp;quot;,&lt;br /&gt;
                               &amp;quot;icon&amp;quot;     =&amp;gt; &amp;quot;10px-kreis-gruen&amp;quot;,    &lt;br /&gt;
                             },&lt;br /&gt;
                             {&lt;br /&gt;
                               &amp;quot;Status&amp;quot;   =&amp;gt; &amp;quot;!~ /ended/ &amp;quot;,&lt;br /&gt;
                               &amp;quot;daysLeft&amp;quot; =&amp;gt; &amp;quot;&amp;gt;= 16&amp;quot;,&lt;br /&gt;
                               &amp;quot;icon&amp;quot;     =&amp;gt; &amp;quot;10px-kreis-gelb&amp;quot;,    &lt;br /&gt;
                             },&lt;br /&gt;
							 {&lt;br /&gt;
                               &amp;quot;Status&amp;quot;   =&amp;gt; &amp;quot;!~ /ended/ &amp;quot;,&lt;br /&gt;
                               &amp;quot;daysLeft&amp;quot; =&amp;gt; &amp;quot;&amp;gt;= 30&amp;quot;,&lt;br /&gt;
                               &amp;quot;icon&amp;quot;     =&amp;gt; &amp;quot;10px-kreis-rot&amp;quot;,&lt;br /&gt;
                             },&lt;br /&gt;
                             ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
| Der Schlüssel &#039;&#039;&#039;columnDaysLeftIcon&#039;&#039;&#039; kann einen oder mehrere Subschlüssel enthalten. &lt;br /&gt;
Mehrere Subschlüssel werden wie hier dargestellt als Gruppe zusammengefasst und in [ ] eingeschlossen. Im Beispiel werden die Inhalte der Readings &amp;quot;x_x_Status&amp;quot; und &amp;quot;x_x_dayLeft&amp;quot; ausgewertet. &lt;br /&gt;
&lt;br /&gt;
Wenn alle zwei Bedingungen &#039;&#039;&#039;wahr&#039;&#039;&#039; sind, wird die jeweilige Gruppe &#039;&#039;&#039;wahr&#039;&#039;&#039; und das angegebene Icon in der Spalte angezeigt.  &lt;br /&gt;
 &lt;br /&gt;
Die Gruppen werden von oben nach unten abgearbeitet. Die letzte &amp;quot;wahre&amp;quot; Gruppe siegt. &lt;br /&gt;
| [[Datei:sscal18.PNG|200px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Gestaltung der Spalte &amp;quot;State&amp;quot; bzw. &amp;quot;Status&amp;quot; ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Die Spalte &amp;quot;Status&amp;quot; zeigt den aktuellen Status eines Termins an. Abhängig davon sowie den Inhalten weiterer Readings kann in dieser Spalte ein Icon anstatt des Statustextes angezeigt werden.&lt;br /&gt;
&lt;br /&gt;
Um diese Spalte als Icon darzustellen, wird der Schlüssel &#039;&#039;&#039;columnStateIcon&#039;&#039;&#039; verwendet. Es können mehrere Subschlüssel angewendet werden die logisch durch &#039;&#039;&#039;und&#039;&#039;&#039; verknüpft sind. D.h. alle Bedingungen der Subschlüssel müssen wahr sein damit die Gruppe wahr wird.&lt;br /&gt;
&lt;br /&gt;
Dabei können mehrere Gruppen von Subschlüsseln verwendet werden, um abhängig von unterschiedlichen Readingwerten das resultierende Icon zu wählen oder einzufärben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Inhalt Attribut tableSpecs: &amp;lt;br&amp;gt; Gestaltung Spalte &amp;quot;Status&amp;quot; als Icon !! Erläuterungen !! Aussehen &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;width:55%&amp;quot; |&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{ 						 &lt;br /&gt;
  &amp;quot;columnStateIcon&amp;quot;       =&amp;gt; [&lt;br /&gt;
                             {&lt;br /&gt;
                               &amp;quot;Status&amp;quot;   =&amp;gt; &amp;quot;eq &#039;ended&#039; &amp;quot;,&lt;br /&gt;
                               &amp;quot;icon&amp;quot;     =&amp;gt; &amp;quot;ios-off&amp;quot;,&lt;br /&gt;
                             },&lt;br /&gt;
                             {&lt;br /&gt;
                               &amp;quot;Status&amp;quot;   =&amp;gt; &amp;quot;eq &#039;upcoming&#039; &amp;quot;,&lt;br /&gt;
                               &amp;quot;icon&amp;quot;     =&amp;gt; &amp;quot;ios-on-for-timer-green&amp;quot;,&lt;br /&gt;
                             },&lt;br /&gt;
                             {&lt;br /&gt;
                               &amp;quot;Status&amp;quot;   =&amp;gt; &amp;quot;eq &#039;upcoming&#039; &amp;quot;,&lt;br /&gt;
                               &amp;quot;daysLeft&amp;quot; =&amp;gt; &amp;quot;&amp;gt;= 4&amp;quot;,&lt;br /&gt;
                               &amp;quot;icon&amp;quot;     =&amp;gt; &amp;quot;ios-on-for-timer-blue&amp;quot;,&lt;br /&gt;
                             },&lt;br /&gt;
                             ],&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
| Der Inhalt des Readings &amp;quot;x_x_Status&amp;quot; wird ausgewertet und abhängig von dessen Inhalt das Icon bestimmt. &lt;br /&gt;
&lt;br /&gt;
In der untersten Gruppe muß außerdem der Inhalt von &amp;quot;x_x_daysLeft&amp;quot; größer/gleich &amp;quot;4&amp;quot; sein damit diese Gruppe &#039;&#039;&#039;wahr&#039;&#039;&#039; wird.  &lt;br /&gt;
&lt;br /&gt;
Alle Bedingungen in einer Gruppe müssen &#039;&#039;&#039;wahr&#039;&#039;&#039; sein, damit das angegebene &amp;quot;Icon&amp;quot; in der Spalte angezeigt wird. Die Gruppen werden der Reihe nach von oben nach unten ausgewertet. Die letzte &#039;&#039;&#039;wahre&#039;&#039;&#039; Gruppe gewinnt und deren Icon wird dargestellt.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Gruppen werden immer in &#039;&#039;&#039;[ ]&#039;&#039;&#039; eingeschlossen.&lt;br /&gt;
| [[Datei:sscal19.PNG|200px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Gestaltung der Spalte &amp;quot;Symbol&amp;quot; ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Sofern man mit dem Attribut &#039;&#039;&#039;tableFields&#039;&#039;&#039; die Spalte &#039;&#039;&#039;Symbol&#039;&#039;&#039; mit auswählt, wird in der tabellarischen Übersicht jede Tabellenzeile von einem Standardicon angeführt. Das Standardicon ist abhängig vom Internal MODEL des Kalenders, d.h. ob es sich um einen Terminkalender oder eine Aufgabenliste handelt.&lt;br /&gt;
&lt;br /&gt;
Dieses Standardicon kann mit dem Schlüssel &#039;&#039;&#039;columnSymbolIcon&#039;&#039;&#039; den persönlichen Bedürfnissen entsprechend angepasst werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Inhalt Attribut tableSpecs: &amp;lt;br&amp;gt; Gestaltung der Spalte &amp;quot;Symbol&amp;quot; !! Erläuterungen !! Aussehen &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;width:55%&amp;quot; |&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{ 						 &lt;br /&gt;
  &amp;quot;columnSymbolIcon&amp;quot; =&amp;gt; &amp;quot;time_manual_mode&amp;quot;, &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
| Mit einer einfachen Schlüssel - Wert Zuweisung kann das Ico geändert werden.&lt;br /&gt;
| [[Datei:sscal22.PNG|200px]]&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
 &amp;quot;columnSymbolIcon&amp;quot; =&amp;gt; [&lt;br /&gt;
                       { &lt;br /&gt;
                         &amp;quot;Weekday&amp;quot; =&amp;gt; &amp;quot;eq &#039;Montag&#039; &amp;quot;,&lt;br /&gt;
                         &amp;quot;icon&amp;quot; =&amp;gt; &amp;quot;edit_numeric_1&amp;quot;,&lt;br /&gt;
                       },&lt;br /&gt;
                       { &lt;br /&gt;
                         &amp;quot;Weekday&amp;quot; =&amp;gt; &amp;quot;eq &#039;Dienstag&#039; &amp;quot;,&lt;br /&gt;
                         &amp;quot;icon&amp;quot; =&amp;gt; &amp;quot;edit_numeric_2&amp;quot;,&lt;br /&gt;
                       },&lt;br /&gt;
                       { &lt;br /&gt;
                         &amp;quot;Weekday&amp;quot; =&amp;gt; &amp;quot;eq &#039;Mittwoch&#039; &amp;quot;,&lt;br /&gt;
                         &amp;quot;icon&amp;quot; =&amp;gt; &amp;quot;edit_numeric_3&amp;quot;,&lt;br /&gt;
                       },&lt;br /&gt;
                       { &lt;br /&gt;
                         &amp;quot;Weekday&amp;quot; =&amp;gt; &amp;quot;eq &#039;Donnerstag&#039; &amp;quot;,&lt;br /&gt;
                         &amp;quot;icon&amp;quot; =&amp;gt; &amp;quot;edit_numeric_4&amp;quot;,&lt;br /&gt;
                       },&lt;br /&gt;
                       { &lt;br /&gt;
                         &amp;quot;Weekday&amp;quot; =&amp;gt; &amp;quot;eq &#039;Freitag&#039; &amp;quot;,&lt;br /&gt;
                         &amp;quot;icon&amp;quot; =&amp;gt; &amp;quot;edit_numeric_5&amp;quot;,&lt;br /&gt;
                       },&lt;br /&gt;
                       { &lt;br /&gt;
                         &amp;quot;Weekday&amp;quot; =&amp;gt; &amp;quot;eq &#039;Samstag&#039; &amp;quot;,&lt;br /&gt;
                         &amp;quot;icon&amp;quot; =&amp;gt; &amp;quot;edit_numeric_6&amp;quot;,&lt;br /&gt;
                       },&lt;br /&gt;
                       { &lt;br /&gt;
                         &amp;quot;Weekday&amp;quot; =&amp;gt; &amp;quot;eq &#039;Sontag&#039; &amp;quot;,&lt;br /&gt;
                         &amp;quot;icon&amp;quot; =&amp;gt; &amp;quot;edit_numeric_7&amp;quot;,&lt;br /&gt;
                       },&lt;br /&gt;
                       ],&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
| Durch die Auswertung des Readings &amp;quot;x_x_Weekday&amp;quot; wird in diesem Beispiel die Zeile des Kalendereintrags in der Spalte &#039;&#039;&#039;Symbol&#039;&#039;&#039; nummeriert. &lt;br /&gt;
Die Bedingung in einer Gruppe muß &#039;&#039;&#039;wahr&#039;&#039;&#039; sein, damit das angegebene &amp;quot;Icon&amp;quot; in der Spalte angezeigt wird. Die Gruppen werden der Reihe nach von oben nach unten ausgewertet. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Gruppen werden immer in &#039;&#039;&#039;[ ]&#039;&#039;&#039; eingeschlossen. &lt;br /&gt;
| [[Datei:sscal23.PNG|200px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Optimierung der Tabelle für smallscreen Styles ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Für bestimmte Styles ist es sinnvoll die Tabellengestaltung flexibel zu gestalten, sodass z.B. Spalten umgebrochen werden können um Platz zu sparen. In dem Schlüssel &#039;&#039;&#039;smallScreenStyles&#039;&#039;&#039; wird hinterlegt, für welche Styles die optimierte Anpassung gelten soll.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Inhalt Attribut tableSpecs: &amp;lt;br&amp;gt; Optimierung der Tabelle für Smallscreen Styles !! Erläuterungen !! Aussehen &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;width:55%&amp;quot; |&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{ 						 &lt;br /&gt;
  &amp;quot;smallScreenStyles&amp;quot; =&amp;gt; &amp;quot;darksmallscreen,smallscreen,default&amp;quot;,&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
| Es wird als Schlüsselwert eine durch Komma getrennte Liste der Styles eingetragen, für eine optimierte Anpassung der Tabelle vorgenommen werden soll.&lt;br /&gt;
| [[Datei:sscal20.PNG|200px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Beispiele mit Kombinationen von Schlüsseln ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Alle oben genannten Schlüssel und Varianten können miteinander kombiniert werden. Im Ergebnis werden die jeweiligen Spalten der Übersichtstabelle entsprechend der Auswertungergebnisse ihrer Definitionen dargestellt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Inhalt Attribut tableSpecs: &amp;lt;br&amp;gt; Schlüsselkombinationen !! Erläuterungen !! Aussehen &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;width:55%&amp;quot; |&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;columnMapIcon&amp;quot;         =&amp;gt; [{&lt;br /&gt;
                               &amp;quot;Status&amp;quot; =&amp;gt; &amp;quot;eq &#039;ended&#039; &amp;quot;,&lt;br /&gt;
                               &amp;quot;icon&amp;quot;   =&amp;gt; &amp;quot;rc_WEB@grey&amp;quot;,                                &lt;br /&gt;
                             },&lt;br /&gt;
                             {&lt;br /&gt;
                               &amp;quot;daysLeft&amp;quot; =&amp;gt; &amp;quot;&amp;gt;= 1 &amp;quot;,&lt;br /&gt;
                               &amp;quot;icon&amp;quot;   =&amp;gt; &amp;quot;rc_WEB&amp;quot;,                                &lt;br /&gt;
                             }],&lt;br /&gt;
  &amp;quot;columnMapProvider&amp;quot;     =&amp;gt; &amp;quot;GoogleMaps&amp;quot;,&lt;br /&gt;
  &amp;quot;columnMapText&amp;quot;         =&amp;gt; &amp;quot;{ ReadingsVal(&#039;$NAME&#039;, &#039;$BNR_35_Location&#039;,&#039;&#039;) }&amp;quot;,&lt;br /&gt;
  &amp;quot;smallScreenStyles&amp;quot;     =&amp;gt; &amp;quot;darksmallscreen,smallscreen&amp;quot;,&lt;br /&gt;
  &amp;quot;columnStateIcon&amp;quot;       =&amp;gt; [&lt;br /&gt;
                             {&lt;br /&gt;
                               &amp;quot;Status&amp;quot;   =&amp;gt; &amp;quot;eq &#039;ended&#039; &amp;quot;,&lt;br /&gt;
                               &amp;quot;icon&amp;quot;     =&amp;gt; &amp;quot;ios-off&amp;quot;,   &lt;br /&gt;
                             },&lt;br /&gt;
                             {&lt;br /&gt;
                               &amp;quot;Status&amp;quot;   =&amp;gt; &amp;quot;eq &#039;upcoming&#039; &amp;quot;,&lt;br /&gt;
                               &amp;quot;icon&amp;quot;     =&amp;gt; &amp;quot;ios-on-for-timer-green&amp;quot;,   &lt;br /&gt;
                             },&lt;br /&gt;
                             {&lt;br /&gt;
                               &amp;quot;Status&amp;quot;   =&amp;gt; &amp;quot;eq &#039;upcoming&#039; &amp;quot;,&lt;br /&gt;
                               &amp;quot;daysLeft&amp;quot; =&amp;gt; &amp;quot;&amp;gt;= 4&amp;quot;,&lt;br /&gt;
                               &amp;quot;icon&amp;quot;     =&amp;gt; &amp;quot;ios-on-for-timer-blue&amp;quot;,   &lt;br /&gt;
                             },							 &lt;br /&gt;
                             ],&lt;br /&gt;
  &amp;quot;columnDaysLeftIcon&amp;quot;    =&amp;gt; [&lt;br /&gt;
                             {&lt;br /&gt;
                               &amp;quot;Summary&amp;quot;  =&amp;gt; &amp;quot;=~ /Gelbe Tonne/&amp;quot;,&lt;br /&gt;
                               &amp;quot;icon&amp;quot;     =&amp;gt; &amp;quot;dustbin@#DF7401&amp;quot;,    &lt;br /&gt;
                             },&lt;br /&gt;
                             {&lt;br /&gt;
                               &amp;quot;Summary&amp;quot;  =&amp;gt; &amp;quot;=~ /Biotonne/&amp;quot;,&lt;br /&gt;
                               &amp;quot;icon&amp;quot;     =&amp;gt; &amp;quot;dustbin@brown&amp;quot;,    &lt;br /&gt;
                             },	&lt;br /&gt;
                             {&lt;br /&gt;
                               &amp;quot;Summary&amp;quot;  =&amp;gt; &amp;quot;=~ /Restabfall/&amp;quot;,&lt;br /&gt;
                               &amp;quot;icon&amp;quot;     =&amp;gt; &amp;quot;dustbin@black&amp;quot;,&lt;br /&gt;
                             },&lt;br /&gt;
                             {&lt;br /&gt;
                               &amp;quot;Summary&amp;quot;  =&amp;gt; &amp;quot;=~ /Papier/&amp;quot;,&lt;br /&gt;
                               &amp;quot;icon&amp;quot;     =&amp;gt; &amp;quot;dustbin@blue&amp;quot;,&lt;br /&gt;
                             },&lt;br /&gt;
                             {&lt;br /&gt;
                               &amp;quot;Status&amp;quot;   =&amp;gt; &amp;quot;=~ /ended/&amp;quot;,&lt;br /&gt;
                               &amp;quot;icon&amp;quot;     =&amp;gt; &amp;quot;dustbin@grey&amp;quot;,&lt;br /&gt;
                             },&lt;br /&gt;
                             ],&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
| Zusätzlich zu der aufgezeigten Definition ist das Attribut &#039;&#039;&#039;tableColumnMap&#039;&#039;&#039; auf &#039;&#039;&#039;icon&#039;&#039;&#039; gestellt um in der Spalte &#039;&#039;&#039;Map&#039;&#039;&#039; nicht den im Schüssel &#039;&#039;&#039;columnMapText&#039;&#039;&#039; definierten Text (Auswertung von ReadingsVal) zu zeigen, sondern das im Schlüssel &#039;&#039;&#039;columnMapIcon&#039;&#039;&#039; angegebene Icon.&lt;br /&gt;
| [[Datei:sscal21.PNG|200px]]&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;smallScreenStyles&amp;quot;  =&amp;gt; &amp;quot;dark,default&amp;quot;,&lt;br /&gt;
  &amp;quot;columnSymbolIcon&amp;quot;   =&amp;gt; [ &lt;br /&gt;
                          {&lt;br /&gt;
                            &amp;quot;Summary&amp;quot;  =&amp;gt; &amp;quot;eq &#039;Biotonne&#039; &amp;quot;,&lt;br /&gt;
                            &amp;quot;icon&amp;quot;     =&amp;gt; &amp;quot;message_garbage@brown&amp;quot;,&lt;br /&gt;
                          },&lt;br /&gt;
                          {&lt;br /&gt;
                            &amp;quot;Summary&amp;quot;  =&amp;gt; &amp;quot;eq &#039;Gelbe Tonne&#039; &amp;quot;,&lt;br /&gt;
                            &amp;quot;icon&amp;quot;     =&amp;gt; &amp;quot;message_garbage@orange&amp;quot;,&lt;br /&gt;
                          },&lt;br /&gt;
                          {&lt;br /&gt;
                            &amp;quot;Summary&amp;quot;  =&amp;gt; &amp;quot;eq &#039;Papiertonne&#039; &amp;quot;,&lt;br /&gt;
                            &amp;quot;icon&amp;quot;     =&amp;gt; &amp;quot;message_garbage@blue&amp;quot;,&lt;br /&gt;
                          },&lt;br /&gt;
                          {&lt;br /&gt;
                            &amp;quot;Summary&amp;quot;  =&amp;gt; &amp;quot;=~ /Restabfall/ &amp;quot;,&lt;br /&gt;
                            &amp;quot;icon&amp;quot;     =&amp;gt; &amp;quot;message_garbage@Wheat&amp;quot;,&lt;br /&gt;
                          },&lt;br /&gt;
                          ],&lt;br /&gt;
  &amp;quot;columnDaysLeftIcon&amp;quot; =&amp;gt; [	&lt;br /&gt;
                          {&lt;br /&gt;
                            &amp;quot;Summary&amp;quot;  =&amp;gt; &amp;quot;=~ /[Tt]onne|Restabfall/&amp;quot;,&lt;br /&gt;
                            &amp;quot;Status&amp;quot;   =&amp;gt; &amp;quot;ne &#039;ended&#039; &amp;quot;,&lt;br /&gt;
                            &amp;quot;daysLeft&amp;quot; =&amp;gt; &amp;quot;&amp;lt;= 4&amp;quot;,&lt;br /&gt;
                            &amp;quot;icon&amp;quot;     =&amp;gt; &amp;quot;message_garbage_collection@orange&amp;quot;,&lt;br /&gt;
                          },&lt;br /&gt;
                          {&lt;br /&gt;
                            &amp;quot;Summary&amp;quot;  =&amp;gt; &amp;quot;=~ /[Tt]onne|Restabfall/&amp;quot;,&lt;br /&gt;
                            &amp;quot;Status&amp;quot;   =&amp;gt; &amp;quot;ne &#039;ended&#039; &amp;quot;,&lt;br /&gt;
                            &amp;quot;daysLeft&amp;quot; =&amp;gt; &amp;quot;&amp;lt;= 2&amp;quot;,&lt;br /&gt;
                            &amp;quot;icon&amp;quot;     =&amp;gt; &amp;quot;message_garbage_collection@green&amp;quot;,&lt;br /&gt;
                          },&lt;br /&gt;
                          {&lt;br /&gt;
                            &amp;quot;Summary&amp;quot;  =&amp;gt; &amp;quot;=~ /[Tt]onne|Restabfall/&amp;quot;,&lt;br /&gt;
                            &amp;quot;Status&amp;quot;   =&amp;gt; &amp;quot;ne &#039;ended&#039; &amp;quot;,&lt;br /&gt;
                            &amp;quot;daysLeft&amp;quot; =&amp;gt; &amp;quot;&amp;gt; 4&amp;quot;,&lt;br /&gt;
                            &amp;quot;icon&amp;quot;     =&amp;gt; &amp;quot;bag@grey&amp;quot;,&lt;br /&gt;
                          },&lt;br /&gt;
                          ],&lt;br /&gt;
  &amp;quot;columnStateIcon&amp;quot;       =&amp;gt; [&lt;br /&gt;
                             {&lt;br /&gt;
                               &amp;quot;Status&amp;quot;   =&amp;gt; &amp;quot;eq &#039;ended&#039; &amp;quot;,&lt;br /&gt;
                               &amp;quot;icon&amp;quot;     =&amp;gt; &amp;quot;1px-spacer&amp;quot;,&lt;br /&gt;
                             },&lt;br /&gt;
                             {&lt;br /&gt;
                               &amp;quot;Status&amp;quot;   =&amp;gt; &amp;quot;eq &#039;started&#039; &amp;quot;,&lt;br /&gt;
                               &amp;quot;icon&amp;quot;     =&amp;gt; &amp;quot;10px-kreis-gruen&amp;quot;,&lt;br /&gt;
                             },&lt;br /&gt;
                             {&lt;br /&gt;
                               &amp;quot;Status&amp;quot;   =&amp;gt; &amp;quot;eq &#039;upcoming&#039; &amp;quot;,&lt;br /&gt;
                               &amp;quot;icon&amp;quot;     =&amp;gt; &amp;quot;10px-kreis-gelb&amp;quot;,&lt;br /&gt;
                             },&lt;br /&gt;
                             {&lt;br /&gt;
                               &amp;quot;Status&amp;quot;   =&amp;gt; &amp;quot;eq &#039;alarmed&#039; &amp;quot;,&lt;br /&gt;
                               &amp;quot;icon&amp;quot;     =&amp;gt; &amp;quot;10px-kreis-rot&amp;quot;,&lt;br /&gt;
                             },&lt;br /&gt;
                             ],&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
| Dieses Beispiel zeigt eine Konfiguration zur Anzeige eines Abfallkalenders. Es werden nur die minimal notwendigen Informationsspalten angezeigt.&lt;br /&gt;
| [[Datei:sscal24.PNG|200px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Termintabelle als Weblink einfügen =&lt;br /&gt;
&lt;br /&gt;
Zur Einbindung in ein Weblink-Device oder zur Verwendung in eigenen Perl-Routinen stellt SSCal die Subroutine &#039;&#039;&#039;SSCal_calAsHtml&#039;&#039;&#039; zur Verfügung. Sie liefert ein HTML-Output zurück, welches dem eingestellten Tabellenaufbau in der Detail- bzw. Raumübersicht entspricht.&lt;br /&gt;
[[Datei:sscal27.PNG|right|thumb|300px|Spaltensteuerung Tabelle bei weblink Einbindung ]]&lt;br /&gt;
&lt;br /&gt;
Die Definition des Weblink-Devices erfolgt:&lt;br /&gt;
&lt;br /&gt;
 define SynCal.Abfall.WBL weblink htmlCode { FHEM::SSCal::calAsHtml  (&amp;quot;SynCal1&amp;quot;) }&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SynCal1&#039;&#039;&#039; ist der Name des SSCal-Devices dessen Ausgabetabelle eingebunden werden soll. &lt;br /&gt;
&lt;br /&gt;
Möglicherweise sollen die Spalten Start/Ende jeweils nur als eine und nicht zwei (Datum/Zeit) Spalten dargestellt werden.&lt;br /&gt;
Im Attribut &#039;&#039;&#039;tableSpecs&#039;&#039;&#039; steuert der Schlüssel &#039;&#039;&#039;smallScreenStyles&#039;&#039;&#039; den Aufbau dieser Spalten in Abhängigkleit vom verwendeten Style des aufrufenden FHEMWEB Devices. Bei einer programmtechnischen Verwendung muss diese Information explizit mitgegeben werden.&lt;br /&gt;
&lt;br /&gt;
Verwendet z.B. das FHEMWEB Device &amp;quot;WEB.BLACK&amp;quot; das Style &amp;quot;dark&amp;quot; und dieses ist im Schlüssel hinterlegt (&amp;quot;smallScreenStyles&amp;quot; =&amp;gt; &amp;quot;dark&amp;quot;), erfolgt die Definition des Weblink-Devices in dieser Form:&lt;br /&gt;
&lt;br /&gt;
 define SynCal.Abfall.WBL weblink htmlCode { FHEM::SSCal::calAsHtml  (&amp;quot;SynCal1&amp;quot;,&amp;quot;WEB.BLACK&amp;quot;) }&lt;br /&gt;
&lt;br /&gt;
Dadurch simuliert man gegenüber der FHEM::SSCal::calAsHtml Routine den Aufruf über das FHEMWEB-Device &amp;quot;WEB.BLACK&amp;quot; und die Routine wertet für dieses Device den eventuell vorhandenen Schlüssel &amp;quot;smallScreenStyles&amp;quot; =&amp;gt; &amp;quot;dark&amp;quot; aus, was zur Darstellung der optimierten Ansicht führt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Reagieren auf Events und eine FHEM-Aktivität erstellen =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Das SSCal-Modul bietet für den Anwender zusätzliche Hilfsmittel an, um aus einem Kalendereintrag Steuerungen für Geräte oder Mitteilungen aufzubauen. Die wesentlichen sind nachfolgend beschrieben.&lt;br /&gt;
&lt;br /&gt;
== at-Devices für Steuerungen automatisch erstellen und verwalten lassen ==&lt;br /&gt;
&lt;br /&gt;
Um aus FHEM-Befehlen (z.B. &amp;quot;set lampe on&amp;quot;) oder Perl-Routine Aufrufen (z.B. checkit()) automatisch eine zeitgesteuerte FHEM-Aktion zu erstellen, kann diese Funktionalität mit dem Attribut:&lt;br /&gt;
&lt;br /&gt;
 attr &amp;lt;SSCal&amp;gt; createATDevs 1&lt;br /&gt;
&lt;br /&gt;
eingeschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Es wird der Eintrag im Reading &#039;&#039;&#039;Description&#039;&#039;&#039; ausgewertet, was dem Feld &#039;&#039;&#039;Beschreibung&#039;&#039;&#039; im Synology Kalender WebUI entspricht.&lt;br /&gt;
Um als FHEM-Befehl erkannt zu werden, muss der Text in der Beschreibung in &#039;&#039;&#039;{ }&#039;&#039;&#039; eingefasst sein bzw. in doppelte &#039;&#039;&#039;{{ }}&#039;&#039;&#039; zur Kennzeichnung einer Perl-Routine.&lt;br /&gt;
Der Kalendereintrag muss ebenfalls eine defininierte Anfangszeit in der Zukunft enthalten. Für beendete oder bereits gestartete Ereignisse wird kein at-Device erstellt.&lt;br /&gt;
&lt;br /&gt;
Sind die Voraussetzungen erfüllt, wird für jedes erkannte Befehls-Ereignis ein at-Device erstellt und die Werte aus dem Kalendereintrag übernommen:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Begin&#039;&#039;&#039;&lt;br /&gt;
| Starttermin im at-Device&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Description&#039;&#039;&#039;&lt;br /&gt;
| der FHEM-Befehl bzw. die auszuführende Perl-Routine&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Summary&#039;&#039;&#039;&lt;br /&gt;
| wird in das alias-Attribut des at übernommen&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;Location&#039;&#039;&#039;&lt;br /&gt;
| wird als room-Attribut im at verwendet falls gesetzt. Sonst wird das room-Attribut des SSCal-Devices übernommen&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Name der erstellten at-Devices folgenden dem Schema:&lt;br /&gt;
&lt;br /&gt;
 SSCal.&amp;lt;SSCal-Device&amp;gt;.&amp;lt;Event-ID&amp;gt;.&amp;lt;ISO-Startzeit&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Bei jedem erneuten Einlesen des Kalenders werden eventuell bereits vorhandene at-Devices gelöscht, die durch das &#039;&#039;&#039;&amp;lt;SSCal-Device&amp;gt;&#039;&#039;&#039; erstellt wurden. Dadurch werden im Kalender vorgenommene Änderungen bestehender Termine und deren Inhalte übernommen. Im Kalender gelöschte Termine werden ebenfalls erkannt und die referenzierten at-Devices in FHEM gelöscht. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beipiel:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ein Kalendereintrag mit den Readings:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     2_01_Summary          bald beginnend&lt;br /&gt;
     2_03_Description      {{ Perl-Routine }}&lt;br /&gt;
     2_05_Begin            2020-02-17 20:45:00&lt;br /&gt;
     2_10_End              2020-02-17 21:45:00&lt;br /&gt;
     2_15_Timezone         Europe/Berlin&lt;br /&gt;
     2_17_Status           alarmed&lt;br /&gt;
     2_20_daysLeft         0&lt;br /&gt;
     2_25_daysLeftLong     in 0 Tagen&lt;br /&gt;
     2_30_Weekday          Montag&lt;br /&gt;
     2_50_isAllday         0&lt;br /&gt;
     2_55_isRepeatEvt      0&lt;br /&gt;
     2_80_0_notifyDateTime 2020-02-16 20:45:00&lt;br /&gt;
     2_90_calName          Testkalender&lt;br /&gt;
     2_98_EventId          2000&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
führt zur Erstellung des at-Devices &#039;&#039;&#039;SSCal.SynCal3.2000.20200217T204500&#039;&#039;&#039; mit der Definition:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
defmod SSCal.SynCal3.2000.20200217T204500 at 2020-02-17T20:45:00 { Perl-Routine }&lt;br /&gt;
attr SSCal.SynCal3.2000.20200217T204500 comment created automatic by SSCal &amp;quot;SynCal3&amp;quot; &lt;br /&gt;
attr SSCal.SynCal3.2000.20200217T204500 alias bald beginnend&amp;quot; &lt;br /&gt;
attr SSCal.SynCal3.2000.20200217T204500 room SSCal&lt;br /&gt;
&lt;br /&gt;
setstate SSCal.SynCal3.2000.20200217T204500 Next: 2020-02-17 20:45:00&lt;br /&gt;
setstate SSCal.SynCal3.2000.20200217T204500 2020-02-17 19:44:09 state Next: 2020-02-17 20:45:00&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== zusätzliches composite-Event für eigene Logiken ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Für jedes Ereignis, welches einen Begin-Zeitpunkt enthält, werden zuätzliche composite-Events bei jedem erneuten Einlesen eines Kalenders erstellt. Der Event &#039;&#039;&#039;composite&#039;&#039;&#039; enthält die Informationsfelder:&lt;br /&gt;
&lt;br /&gt;
* Blocknummer des Termins&lt;br /&gt;
* Event-ID des Termins&lt;br /&gt;
* Kennzeichen für ein Serientermin (0=kein Serientermin oder 1=Serientermin)&lt;br /&gt;
* Startzeitpunkt im ISO 8601 Format&lt;br /&gt;
* Status des Events &lt;br /&gt;
* den Text in &#039;&#039;&#039;Description&#039;&#039;&#039; (entspricht dem Feld Beschreibung im Synology Kalender WebUI) bzw. den Text in &#039;&#039;&#039;Summary&#039;&#039;&#039; falls &#039;&#039;&#039;Description&#039;&#039;&#039; nicht gesetzt ist&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Event &#039;&#039;&#039;compositeBlockNumbers&#039;&#039;&#039; enthält die Blocknummern aller Termine des Kalenders. Sind keine Termine vorhanden, enthält dieser Event nur den Wert &#039;&#039;&#039;none&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ausschnitt aus dem Eventmonitor:&lt;br /&gt;
&lt;br /&gt;
 2020-02-14 13:19:11 SSCal SynCal2 compositeBlockNumbers: 00 01 02 03 04 05 06 07 08 09 10                # alle Block-Nr&lt;br /&gt;
 2020-02-14 13:19:11 SSCal SynCal2 composite: 00 1983 0 2020-02-14T13:15:00 started {set lampe on}        # FHEM-Befehl&lt;br /&gt;
 2020-02-14 13:19:11 SSCal SynCal2 composite: 01 1984 0 2020-02-14T15:15:00 alarmed {set lampe off}       # FHEM-Befehl &lt;br /&gt;
 2020-02-14 13:35:31 SSCal SynCal2 composite: 02 1985 1 2020-02-14T18:00:00 upcoming {{ &amp;lt;Perl-Routine&amp;gt; }} # Perl-Routine&lt;br /&gt;
&lt;br /&gt;
Das ISO Format des Zeitstempels kann unmittelbar zur Erstellung eines &#039;&#039;&#039;at&#039;&#039;&#039; verwendet werden. Um die Verwendung des Kalenderinhaltes als FHEM-Befehl zu deklarieren, kann bei der Erstellung des Kalendereintrages das Ereignis in &#039;&#039;&#039;{ }&#039;&#039;&#039; eingefasst werden um z.B. in einem &#039;&#039;&#039;notify&#039;&#039;&#039; darauf zu filtern.&lt;br /&gt;
&lt;br /&gt;
Die nachfolgende Definition eines notify-Devices zeigt eine mögliche Verfahrensweise um bei Erkennung eines FHEM-Befehls automatisch ein at-Device mit einem entsprechenden Startzeitpunkt für die Ausführung des angegebenen Befehls zu definieren:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SynCal.*:.*composite.* &lt;br /&gt;
{ &lt;br /&gt;
  my ($PART0, $PART1)                     = split(&amp;quot;: &amp;quot;, $EVENT,2);; &lt;br /&gt;
  my ($bnr,$id,$repeat,$isot,$tate,$cmd)  = split(&amp;quot; &amp;quot;,  $PART1,6);;&lt;br /&gt;
  if ($tate =~ /upcoming|alarmed/ &amp;amp;&amp;amp; $cmd =~ /^\s*\{(.*)\}\s*$/) {&lt;br /&gt;
    $cmd    = $1;&lt;br /&gt;
    if(!$repeat) {&lt;br /&gt;
        Log3($NAME, 3, &amp;quot;$NAME - Command received. Create/modify \&amp;quot;SSCal.$id\&amp;quot; - Timestamp: $isot, Command: $cmd&amp;quot;);;&lt;br /&gt;
        fhem(&amp;quot;defmod SSCal.$id at $isot $cmd&amp;quot;);;&lt;br /&gt;
    } else {&lt;br /&gt;
        my $ao = $isot;&lt;br /&gt;
        $ao    =~ s/[-:]//g;&lt;br /&gt;
        Log3($NAME, 3, &amp;quot;$NAME - Command received. Create/modify \&amp;quot;SSCal.$id.$ao\&amp;quot; - Timestamp: $isot, Command: $cmd&amp;quot;);;&lt;br /&gt;
        fhem(&amp;quot;defmod SSCal.$id.$ao at $isot $cmd&amp;quot;);;	    &lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Funktionsweise:&#039;&#039;&#039; &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wird ein composite-Event eines SSCal-Devices mit dem Betreff eingeschlossen in &#039;&#039;&#039;{ }&#039;&#039;&#039; erkannt und ist der Status dieses Termins &amp;quot;upcoming&amp;quot; oder &amp;quot;alarmed&amp;quot;, wird ein at-Device mit dem Startzeitpunkt und dem Befehl (ohne die einschließenden { }) aus dem Event erstellt. Ist das Device bereits vorhanden, wird das Device aktualisiert. &#039;&#039;&#039;Durch eine eindeutige Zuordung des Kalendereintrags zu dem at-Device über die Event-ID im Namen wird in dem Fall, dass es kein Serientermin ist, der Start des FHEM-Befehl automatisch angepasst wenn man den Zeitpunkt im Kalender verändert.&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
Zusätzlich wird ein Logeintrag mit verbose 3 zur Protokollierung erstellt.&lt;br /&gt;
Soll statt FHEM-Befehl eine Perl-Routine ausgeführt werden, schließt man den Betreff des Kalendereintrags in doppelte &#039;&#039;&#039;{{ }}&#039;&#039;&#039; ein. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
== Urlaub/Abwesenheiten automatisiert in holiday Device Steuerdatei übernehmen ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Mit Hilfe des Events &#039;&#039;&#039;compositeBlockNumbers&#039;&#039;&#039; können Urlaubs- oder allgemeine Abwesenheitstermine aus einem Kalender automatisch in ein holiday Device bzw. die Steuerdatei des holiday Devices übertragen werden.&lt;br /&gt;
&lt;br /&gt;
Zu diesem Zweck werden zwei Subroutinen in der 99_myUtils.pm erstellt und ein Notify um auf den Event zu reagieren und die Subroutine &#039;&#039;&#039;SSCalToHoliday&#039;&#039;&#039; auszuführen.&lt;br /&gt;
&lt;br /&gt;
In dem Beispiel wird davon ausgegangen:&lt;br /&gt;
&lt;br /&gt;
* das holiday Device verwendet die Datei (HOLIDAYFILE) ./FHEM/central.holiday &lt;br /&gt;
* die Abwesenheiten werden durch die Signalwörter &#039;&#039;&#039;Urlaub&#039;&#039;&#039; bzw. &#039;&#039;&#039;Abwesend&#039;&#039;&#039; gekennzeichnet&lt;br /&gt;
* das Kalenderdevice, welches die Urlaubsdaten enthält, heißt &#039;&#039;&#039;SynCal2&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es werden die Routinen &#039;&#039;&#039;SSCalToHoliday&#039;&#039;&#039; und &#039;&#039;&#039;SSCalWriteHoliday&#039;&#039;&#039; in die Datei 99_myUtils.pm eingefügt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;Perl&amp;quot;&amp;gt;&lt;br /&gt;
###################################################################################################&lt;br /&gt;
###    Urlaubstermine auswerten mit 57_SSCal.pm&lt;br /&gt;
###    Aufruf der Funktion aus Notify&lt;br /&gt;
###    &lt;br /&gt;
###    $event = compositeBlockNumbers-$EVENT und enthält alle Blocknummern des Kalenders, z.B.&lt;br /&gt;
###    compositeBlockNumbers: 00 01 02 03 04 05 06 07 08 09 10 11 12 13&lt;br /&gt;
###&lt;br /&gt;
####################################################################################################&lt;br /&gt;
sub SSCalToHoliday($$$) {&lt;br /&gt;
   my ($name,$fName,$event) = @_;&lt;br /&gt;
   my $hash           = $defs{$name};&lt;br /&gt;
   my ($reading,$evt) = split(&amp;quot;: &amp;quot;,$event,2);&lt;br /&gt;
   my (@bnr)          = split(&amp;quot; &amp;quot;,$evt);&lt;br /&gt;
    &lt;br /&gt;
   my @SigList        = qw/Urlaub Abwesend/;                             # Signalwörter im Kalender für &amp;quot;Abwesenheit&amp;quot;&lt;br /&gt;
   my @ul;   &lt;br /&gt;
&lt;br /&gt;
   foreach my $bnr (@bnr) {&lt;br /&gt;
       last if($bnr eq &amp;quot;none&amp;quot;);&lt;br /&gt;
       my $status  = ReadingsVal($name, $bnr.&amp;quot;_17_Status&amp;quot;,  &amp;quot;&amp;quot;);         # Status&lt;br /&gt;
       my $summary = ReadingsVal($name, $bnr.&amp;quot;_01_Summary&amp;quot;, &amp;quot;&amp;quot;);         # Summary&lt;br /&gt;
       my $begin   = ReadingsVal($name, $bnr.&amp;quot;_05_Begin&amp;quot;,   &amp;quot;&amp;quot;);         # Starttermin&lt;br /&gt;
       my $end     = ReadingsVal($name, $bnr.&amp;quot;_10_End&amp;quot;,     &amp;quot;&amp;quot;);         # Endtermin&lt;br /&gt;
   &lt;br /&gt;
       if($status =~ /upcoming|alarmed|started/) {                       # Termine beginnen in Zukunft, Signalwort aus &lt;br /&gt;
                                                                         # Liste enthalten ?               &lt;br /&gt;
           if (grep {$summary =~ /$_/} @SigList) {               &lt;br /&gt;
               my ($sy,$sm,$sd,$sh,$smin,$ss) = ($begin =~ /(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/);&lt;br /&gt;
               my ($ey,$em,$ed,$eh,$emin,$es) = ($end   =~ /(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/);&lt;br /&gt;
               &lt;br /&gt;
               if($sy != $ey) {                                          # wenn Jahreswechsel vorliegt zwei Sätze erzeugen&lt;br /&gt;
                   push(@ul, &amp;quot;4 $sm-$sd 12-31 $summary&amp;quot;);                # 4 12-09 12-31 Urlaub Teil1&lt;br /&gt;
                   push(@ul, &amp;quot;4 01-01 $em-$ed $summary&amp;quot;);                # 4 01-01 01-05 Urlaub Teil2&lt;br /&gt;
                    &lt;br /&gt;
               } else {&lt;br /&gt;
                   my $ue = &amp;quot;4 $sm-$sd $em-$ed $summary&amp;quot;;&lt;br /&gt;
                   push(@ul, $ue);&lt;br /&gt;
               }&lt;br /&gt;
           } &lt;br /&gt;
       }&lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   if (@ul) {&lt;br /&gt;
       Log3 ($name, 4, &amp;quot;$name - Argument list for SSCalWriteHoliday:&amp;quot;);&lt;br /&gt;
       foreach my $i (@ul) {&lt;br /&gt;
           Log3 ($name, 4, &amp;quot;$name - $i&amp;quot;);&lt;br /&gt;
       }&lt;br /&gt;
   } else {&lt;br /&gt;
       Log3 ($name, 4, &amp;quot;$name - No absence time detected. All absence will be deleted.&amp;quot;);&lt;br /&gt;
   }&lt;br /&gt;
   &lt;br /&gt;
   SSCalWriteHoliday($name,$fName,@ul);&lt;br /&gt;
       &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
############################################################################&lt;br /&gt;
###    Schreibroutine Urlaub in File (central.holiday) &lt;br /&gt;
############################################################################&lt;br /&gt;
sub SSCalWriteHoliday(@) {&lt;br /&gt;
  my ($name,$fName,@ul) = @_;&lt;br /&gt;
  $fName = $attr{global}{modpath}.&amp;quot;/FHEM/&amp;quot;.$fName;&lt;br /&gt;
&lt;br /&gt;
  my $param = {&lt;br /&gt;
               FileName   =&amp;gt; $fName,&lt;br /&gt;
               ForceType  =&amp;gt; &amp;quot;file&amp;quot;,&lt;br /&gt;
              };&lt;br /&gt;
  &lt;br /&gt;
  my ($err, @old) = FileRead($param);&lt;br /&gt;
  if($err) {&lt;br /&gt;
      Log3 ($name, 2, &amp;quot;$name - Couldn&#039;t read file: $err&amp;quot;);&lt;br /&gt;
      return;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  my @new;                                                             # neue Liste zum Schreiben&lt;br /&gt;
  my $del = 0;&lt;br /&gt;
  &lt;br /&gt;
  foreach my $l (@old) {&lt;br /&gt;
      if($l =~ m/^# Time of absence from Calendar $name/i) {&lt;br /&gt;
          $del = 1;&lt;br /&gt;
      }&lt;br /&gt;
	  &lt;br /&gt;
      if($l =~ m/^# End Time of absence from Calendar $name/i) {&lt;br /&gt;
          $del = 0;&lt;br /&gt;
		  next;&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      if ($del) {&lt;br /&gt;
          next;     &lt;br /&gt;
      } else {&lt;br /&gt;
          push (@new, $l);&lt;br /&gt;
          Log3 ($name, 4, &amp;quot;$name - add line: $l&amp;quot;); &lt;br /&gt;
      }  &lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  unshift (@ul, &amp;quot;# Time of absence from Calendar $name, updated: &amp;quot;.TimeNow());&lt;br /&gt;
  push    (@ul, &amp;quot;# End Time of absence from Calendar $name&amp;quot;);&lt;br /&gt;
  push    (@new, @ul);&lt;br /&gt;
 &lt;br /&gt;
  Log3 ($name, 4, &amp;quot;$name - -&amp;gt; Start new list write into $fName &amp;lt;-&amp;quot;);&lt;br /&gt;
  foreach my $i (@new) {&lt;br /&gt;
      Log3 ($name, 4, &amp;quot;$name - $i&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  Log3 ($name, 4, &amp;quot;$name - -&amp;gt; End new list &amp;lt;-&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  $err = FileWrite($param, @new);&lt;br /&gt;
  if($err) {&lt;br /&gt;
      Log3 ($name, 2, &amp;quot;$name - Couldn&#039;t write holiday data into $fName: $err&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
return;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das folgende &#039;&#039;&#039;Notify&#039;&#039;&#039; (Raw-Definition) wird verwendet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define N.SSCalWriteHolidays notify SynCal2:compositeBlockNumbers:.* { SSCalToHoliday($NAME,&amp;quot;central.holiday&amp;quot;,$EVENT) }&lt;br /&gt;
attr N.SSCalWriteHolidays devStateIcon active:remotecontrol/black_btn_GREEN:inactive inactive:remotecontrol/black_btn_RED:active&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Funktionsweise:&#039;&#039;&#039;  &amp;lt;br&amp;gt;&lt;br /&gt;
Wird der Event &#039;&#039;&#039;compositeBlockNumbers&#039;&#039;&#039; durch das Device &#039;&#039;&#039;SSCal2&#039;&#039;&#039; ausgelöst, wird die Subroutine &#039;&#039;&#039;SSCalToHoliday&#039;&#039;&#039; ausgeführt. Dieser Routine werden der auslösende Devicename ($NAME = SSCal2 in dem Beispiel), das HOLIDAYFILE und der komplette Event übergeben.&lt;br /&gt;
&lt;br /&gt;
Das Event compositeBlockNumbers enthält die Blocknummern aller Termine im Kalenderdevice. Im Array &#039;&#039;&#039;@SigList&#039;&#039;&#039; werden alle Signalwörter hinterlegt, die bei Vorhandensein im Reading x_x_Summary eine Abwesenheit kennzeichnen. &lt;br /&gt;
Wird eines dieser Signalwörter erkannt und ist der dazu gehörige Termin nicht vergangen, erfolgt die Übersetzung in das durch holiday verarbeitbare Format und der Termineintrag in die Datei &#039;&#039;&#039;central.holiday&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Beispiel für einen Eintrag: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Time of absence from Calendar SynCal2, updated: 2020-03-05 21:20:47&lt;br /&gt;
4 03-28 04-04 Urlaub - Nordsee&lt;br /&gt;
# End Time of absence from Calendar SynCal2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Änderungen oder Löschen des Termins im Synology-Kalender führen ebenfalls zu einer automatischen Anpassung oder Löschen des Eintrags in der holiday-Steuerdatei.&lt;br /&gt;
&lt;br /&gt;
Damit können Zeiten der Abwesenheiten über Kalendereinträge an FHEM übermittelt und durch holiday ausgewertet werden (Stichwort holiday2we bzw. $we). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Anwendungsbeispiele =&lt;br /&gt;
&lt;br /&gt;
== Backup des FHEM Filesystems über Synology Kalendereinplanung ==&lt;br /&gt;
&lt;br /&gt;
In diesem [[SSFile_-_Integration_der_Synology_File_Station#Backup_des_FHEM_Filesystems_.C3.BCber_Synology_Kalendereinplanung|Beitrag]] ist beschrieben, wie mit dem Synology Modulen SSCal und SSFile eine übersichtliche und einfach konfigurierbare Sicherungslösung für die Verzeichnisse des FHEM-Servers aufgebaut werden kann. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
= Beschränkungen und Known Bugs =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Weiterentwicklungen und Testversionen =&lt;br /&gt;
&lt;br /&gt;
Weiterentwicklungen und Testversionen stelle ich in meinem contrib-Verzeichnis bereit.&lt;br /&gt;
&lt;br /&gt;
Eine Entwicklungsversion kann aus dem diesem Verzeichnis einfach per Download mit diesem Befehl in der FHEM Kommandozeile bezogen werden. Bitte so komplett mit den Ausführungszeichen am Anfang und Ende eingeben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 &amp;quot;wget -qO ./FHEM/57_SSCal.pm https://svn.fhem.de/fhem/trunk/fhem/contrib/DS_Starter/57_SSCal.pm&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Danach FHEM restarten.&lt;br /&gt;
&lt;br /&gt;
Durch Weiterentwicklung können sich jederzeit Änderungen ergeben. Im Zweifel das [https://forum.fhem.de/index.php/topic,106963.0.html Forum] konsultieren. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Links =&lt;br /&gt;
&lt;br /&gt;
Forumthread zu diesem Modul: https://forum.fhem.de/index.php/topic,106963.0.html    &amp;lt;br&amp;gt;&lt;br /&gt;
Synology KnowledgeBase: https://www.synology.com/de-de/knowledgebase/DSM/help/Calendar/calendar_desc&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=SiSi&amp;diff=38696</id>
		<title>SiSi</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=SiSi&amp;diff=38696"/>
		<updated>2023-11-09T10:54:46Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: veraltete &amp;quot;source&amp;quot;-Angaben in &amp;quot;syntaxhighlight&amp;quot; geändert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=Senden und Empfangen von Nachrichten (Text und Fotos) mit dem freien Messenger Signal&lt;br /&gt;
|ModType=x&lt;br /&gt;
|ModForumArea=Codeschnipsel&lt;br /&gt;
|ModFTopic=84996&lt;br /&gt;
|ModTechName=32_SiSi.pm&lt;br /&gt;
|ModOwner=Quantum ({{Link2FU|35410|Forum}})}}&lt;br /&gt;
Das Modul [[SiSi]] ermöglicht den Versand von Nachrichten über den Instant-Messaging-Dienst [https://signal.org Signal] aus FHEM heraus.&lt;br /&gt;
&lt;br /&gt;
{{Randnotiz|RNTyp=r|RNText=Dieses Modul wird derzeit (letzte Änderung: August 2018) nicht mehr aktiv gepflegt. Es entsteht jedoch (ab Januar 2021) mit [[Signalbot]] ein weiteres Modul zur Unterstützung des Signal Messenger Protokolls.}}&lt;br /&gt;
&lt;br /&gt;
Um dies zu ermöglichen, sind mehrere Schritte notwendig:&lt;br /&gt;
#Installation des [https://github.com/AsamK/signal-cli Signal Messenger Command Line Interface (signal-cli)].&lt;br /&gt;
#Registrierung einer Rufnummer bei Signal&lt;br /&gt;
#Einrichtung der [https://de.wikipedia.org/wiki/D-Bus D-Bus]-Schnittstelle&lt;br /&gt;
#Inbetriebnahme des FHEM-Moduls&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Diese Anleitung geht davon aus, dass&lt;br /&gt;
*als Betriebssystem Debian oder Raspbian verwendet wird&lt;br /&gt;
*FHEM im Verzeichnis &#039;&#039;/opt/fhem&#039;&#039; installiert wurde (ansonsten müssen die Pfade in der Anleitung angepasst werden)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Alle in dieser Anleitung vorkommenden Textstellen in spitzen Klammern (z.B. &amp;lt;ErsetzMich&amp;gt;) sind durch eigene Werte zu ersetzen, sofern es sich nicht um Auszüge aus Konfigurationsdateien handelt.&lt;br /&gt;
&lt;br /&gt;
==Voraussetzungen==&lt;br /&gt;
Um sowohl das &#039;&#039;signal-cli&#039;&#039; als auch das Modul verwenden zu können, müssen bestimmmte Linux-Pakete installiert sein. Im Folgenden eine Liste der Pakete für Debian/Raspbian:&lt;br /&gt;
*&#039;&#039;&#039;&#039;&#039;libunixsocket-java&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;&#039;&#039;dbus&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;&#039;&#039;libnet-dbus-perl&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;&#039;&#039;haveged&#039;&#039;&#039;&#039;&#039; (Dient dazu, genügend Entropie für den Zufallszahlengenerator zu erzeugen.)&lt;br /&gt;
*&#039;&#039;&#039;&#039;&#039;openjdk-11-jre-headless&#039;&#039;&#039;&#039;&#039; (Es sollte eine Version &amp;gt;= 11 installiert werden. Welche genau, hängt von Betriebssystem und dem Installationszeitpunkt ab. Diese ist als Default JRE mit Debian Stretch verfügbar. Installationen, die auf einer früheren Debian Version aufsetzen, müssen gegebenfalls auf Stretch geupgraded werden). Die aktuellsten Informationen über das benötigte JRE findest du [https://github.com/AsamK/signal-cli#installation hier].&lt;br /&gt;
&lt;br /&gt;
Optional kann noch das Paket &#039;&#039;&#039;&#039;&#039;shared-mime-info&#039;&#039;&#039;&#039;&#039; installiert werden wenn ein gesendeter Anhang nicht direkt im Chatverlauf angezeigt werden soll, sondern erst durch einen Klick auf das Datei-Icon.&lt;br /&gt;
&lt;br /&gt;
Installation der Pakete in einem Rutsch:&lt;br /&gt;
 sudo apt-get update&lt;br /&gt;
 sudo apt-get install libunixsocket-java dbus libnet-dbus-perl shared-mime-info haveged openjdk-11-jre-headless&lt;br /&gt;
&lt;br /&gt;
==Installation des signal-cli==&lt;br /&gt;
[https://github.com/AsamK/signal-cli signal-cli] ist ein Kommandozeilen-Interface für [https://github.com/signalapp/libsignal-service-java libsignal-service-java]&amp;lt;ref&amp;gt;libsignal-service-java ist eine Java/Android Bibliothek zur Kommunikation mit dem Signal Messaging Service&amp;lt;/ref&amp;gt;. Es unterstützt das Registrieren und Verifizieren einer Rufnummer sowie das Senden und Empfangen von Nachrichten.&lt;br /&gt;
&lt;br /&gt;
Der erste Schritt zur Installation von &#039;&#039;signal-cli&#039;&#039; ist, die aktuellste Versionsnummer auf der GitHub-Seite des Projektes unter &amp;quot;[https://github.com/AsamK/signal-cli/releases Releases]&amp;quot; zu finden. Zum Zeitpunkt der Erstfassung dieser Anleitung war das die Version 0.6.0.&lt;br /&gt;
&lt;br /&gt;
Anschließend wird die Release heruntergeladen und als Benutzer &#039;&#039;&#039;&#039;&#039;fhem&#039;&#039;&#039;&#039;&#039; in den Wurzelordner von FHEM (z.B. &#039;&#039;/opt/fhem&#039;&#039;) entpackt.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
export VERSION=0.6.0&lt;br /&gt;
wget https://github.com/AsamK/signal-cli/releases/download/v&amp;quot;${VERSION}&amp;quot;/signal-cli-&amp;quot;${VERSION}&amp;quot;.tar.gz&lt;br /&gt;
sudo -u fhem tar xf signal-cli-&amp;quot;${VERSION}&amp;quot;.tar.gz -C /opt/fhem&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zur einfacheren Handhabung kann der neu erstellte Ordner umbenannt und ein symbolischer Link in &#039;&#039;/usr/local/bin/&#039;&#039; erstellt werden.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
sudo mv /opt/fhem/signal-cli-&amp;quot;${VERSION}&amp;quot; /opt/fhem/signal-cli&lt;br /&gt;
sudo ln -sf /opt/fhem/signal-cli/bin/signal-cli /usr/local/bin/&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Registrierung einer Rufnummer==&lt;br /&gt;
Um Signal nutzen zu können, ist eine Rufnummer zwingend erforderlich. Für diesen Fall empfiehlt es sich, eine Nummer zu verwenden, die nicht schon für die Kommunikation mit Signal verwendet wird. Zum Beispiel eine Festnetznummer. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Alternativ&#039;&#039;&#039; kannst du den Signal Bot auch mit deiner eigenen Rufnummer verknüpfen, analog zum Verknüpfen deiner Rufnummer mit z.B. der Desktop Installation von Signal. Siehe dazu den Abschnitt &amp;quot;Verknüpfen mehrerer Accounts&amp;quot; weiter unten.&lt;br /&gt;
&lt;br /&gt;
=== Registrierung mit neuer Nummer ===&lt;br /&gt;
&lt;br /&gt;
Die Registrierung einer Nummer läuft wie folgt ab:&lt;br /&gt;
#Registrierung der Nummer mittels &#039;&#039;signal-cli&#039;&#039;&lt;br /&gt;
#Erhalt einer Textnachricht mit dem Verifizierungscode an angegebene Nummer. Wenn an der Rufnummer keine Textnachrichten empfangen werden können, kann - wie in diesem Beispiel - mit dem Parameter &#039;&#039;--voice&#039;&#039; ein Sprachanruf erzwungen werden. In beiden Fällen kann es durchaus etwas länger dauern, bis man den Verifizierungscode erhält.&lt;br /&gt;
#Verifizierung der Nummer mittels &#039;&#039;signal-cli&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|Alle der folgenden Befehle werden als Benutzer &#039;&#039;&#039;&#039;&#039;fhem&#039;&#039;&#039;&#039;&#039; ausgeführt, damit die Konfigurationsdateien im Home-Verzeichnis des Benutzers (z.B. &#039;&#039;~/.local/share/signal-cli&#039;&#039;) landen.}}&lt;br /&gt;
&lt;br /&gt;
Im ersten Schritt registriert man eine Nummer mittels &#039;&#039;signal-cli&#039;&#039;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;sudo -u fhem signal-cli -u &amp;lt;Telefonnummer&amp;gt; register --voice&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Wenn alles in Ordnung ist, erhält man keine Rückmeldung. Wenn es lange dauert, hat man nicht genug Entropie. &lt;br /&gt;
Kurz darauf erhält man einen Sprachanruf auf Englisch, mit dem einem der sechsstellige Verifizierungscode yyyyyy mitgeteilt wird.&lt;br /&gt;
&lt;br /&gt;
Im zweiten Schritt wird diese Nummer mit Hilfe des erhaltenen Codes verifiziert.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;sudo -u fhem signal-cli -u &amp;lt;Telefonnummer&amp;gt; verify &amp;lt;VerificationCode&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Auch hier gibt es keine Rückmeldung, solange alles funktioniert hat.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
War die Registrierung erfolgreich, können nun Nachrichten via &#039;&#039;signal-cli&#039;&#039; versendet werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;sudo -u fhem signal-cli -u &amp;lt;RegistrierteNummer&amp;gt; send -m &amp;quot;Greetings from FHEM!&amp;quot; &amp;lt;Empfängernummer&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Verknüpfen mehrerer Accounts ===&lt;br /&gt;
Das Verknüpfen mehrerer Devices / Installationen / Bots unter der selben Rufnummer nennt sich Provisioning und ist [https://github.com/AsamK/signal-cli/wiki/Linking-other-devices-(Provisioning) hier] beschrieben. Es ist ähnlich dem Vorgehen der Registrierung einer neuen Telefonnummer, nur dass du hier deine eigene Nummer wiederverwenden kannst. ACHTUNG: Das bedeutet allerdings, dass alle Nachrichten, die über den Bot verschickt werden, unter deiner Nummer und somit unter deinem Account und Namen verschickt werden. Empfänger deiner Nachrichten sehen diese also als Teil deines Chats mit jenen Empfängern. Für den Empfänger ist daher nicht ersichtlich, dass die Nachrichten automatisiert von einem Bot verschickt wurden. Schickst du eine Nachricht an dich selbst, taucht diese in deinem Signal Messenger im Chat &amp;quot;Notiz an mich&amp;quot; auf.&lt;br /&gt;
&lt;br /&gt;
Um den Signal Bot mit deinem Account zu verknüpfen gehst du wie [https://github.com/AsamK/signal-cli/wiki/Linking-other-devices-(Provisioning) hier] beschrieben vor. Installiere am besten noch das Paket [https://fukuchi.org/works/qrencode/ qrencode].&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt-get install qrencode&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Danach führst du diesen Befehl aus:&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo signal-cli link -n &amp;quot;optional device name&amp;quot; | tee &amp;gt;(xargs -L 1 qrencode -t utf8)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Dieser Befehl generiert einen QR Code im Terminal, den du mit deinem Hauptgerät (vermutlich dein Handy) scannst und somit das neue &amp;quot;Gerät&amp;quot; hinzufügst. Navigate in Signal dazu in die Einstellungen &amp;gt; Gekoppelte Geräte und wähle &amp;quot;Neues Gerät koppeln&amp;quot;. Danach ist das Gerät erfolgreich verknüpft und du kannst wie unten beschrieben mit der Einrichtung fortfahren.&lt;br /&gt;
&lt;br /&gt;
== Einrichten der Kommunikation über D-Bus ==&lt;br /&gt;
Damit das FHEM-Modul über die D-Bus Schnittstelle mit &#039;&#039;signal-cli&#039;&#039; kommunizieren kann, ist die Einrichtung von D-Bus sowie die Erstellung eines [https://de.wikipedia.org/wiki/Systemd systemd]-Scripts notwendig.&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|Alle der folgenden drei Dateien müssen als Benutzer &#039;&#039;&#039;&#039;&#039;root&#039;&#039;&#039;&#039;&#039; angelegt und editiert werden.}}&lt;br /&gt;
&lt;br /&gt;
;/etc/dbus-1/system.d/org.asamk.Signal.conf&lt;br /&gt;
Die Datei in einem Editor öffnen&lt;br /&gt;
 sudo nano /etc/dbus-1/system.d/org.asamk.Signal.conf&lt;br /&gt;
und mit folgendem Inhalt befüllen&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt; &amp;lt;!--*-nxml-*--&amp;gt;&lt;br /&gt;
&amp;lt;!DOCTYPE busconfig PUBLIC &amp;quot;-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN&amp;quot;&lt;br /&gt;
        &amp;quot;http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;busconfig&amp;gt;&lt;br /&gt;
        &amp;lt;policy user=&amp;quot;fhem&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;allow own=&amp;quot;org.asamk.Signal&amp;quot;/&amp;gt;&lt;br /&gt;
                &amp;lt;allow send_destination=&amp;quot;org.asamk.Signal&amp;quot;/&amp;gt;&lt;br /&gt;
                &amp;lt;allow receive_sender=&amp;quot;org.asamk.Signal&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;/policy&amp;gt;&lt;br /&gt;
&lt;br /&gt;
        &amp;lt;policy context=&amp;quot;default&amp;quot;&amp;gt;&lt;br /&gt;
                &amp;lt;allow send_destination=&amp;quot;org.asamk.Signal&amp;quot;/&amp;gt;&lt;br /&gt;
                &amp;lt;allow receive_sender=&amp;quot;org.asamk.Signal&amp;quot;/&amp;gt;&lt;br /&gt;
        &amp;lt;/policy&amp;gt;&lt;br /&gt;
&amp;lt;/busconfig&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;/usr/share/dbus-1/system-services/org.asamk.Signal.service&lt;br /&gt;
Die Datei in einem Editor öffnen&lt;br /&gt;
 sudo nano /usr/share/dbus-1/system-services/org.asamk.Signal.service&lt;br /&gt;
und mit folgendem Inhalt befüllen&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[D-BUS Service]&lt;br /&gt;
Name=org.asamk.Signal&lt;br /&gt;
Exec=/bin/false&lt;br /&gt;
SystemdService=dbus-org.asamk.Signal.service&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;/etc/systemd/system/signal.service&lt;br /&gt;
Die Datei in einem Editor öffnen&lt;br /&gt;
 sudo nano /etc/systemd/system/signal.service&lt;br /&gt;
und mit folgendem Inhalt befüllen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=Send secure messages to Signal clients&lt;br /&gt;
Requires=dbus.socket&lt;br /&gt;
After=dbus.socket&lt;br /&gt;
Wants=network-online.target&lt;br /&gt;
After=network-online.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=dbus&lt;br /&gt;
Environment=&amp;quot;SIGNAL_CLI_OPTS=-Xms2m&amp;quot;&lt;br /&gt;
ExecStart=/opt/fhem/signal-cli/bin/signal-cli -u +49xxxxxxxxxxx --config /opt/fhem/.local/share/signal-cli daemon --system&lt;br /&gt;
User=fhem&lt;br /&gt;
BusName=org.asamk.Signal&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
Alias=dbus-org.asamk.Signal.service&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Achtung!&#039;&#039;&#039;&lt;br /&gt;
* Die Rufnummer im Script muss durch die in den vorigen Schritten registrierte ersetzt werden.&lt;br /&gt;
* Außerdem muss unter Umständen der Pfad des FHEM-Wurzelverzeichnisses angepasst werden.&lt;br /&gt;
* Der Pfad zur Konfigurationsdatei ist je nach signal-cli Version anders:&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;0.6.1:&lt;br /&gt;
 $HOME/.config/signal/data/&lt;br /&gt;
 oder&lt;br /&gt;
 $HOME/.config/textsecure/data/&lt;br /&gt;
&lt;br /&gt;
;&amp;gt;=0.6.1&lt;br /&gt;
 $HOME/.local/share/signal-cli/data/&lt;br /&gt;
&lt;br /&gt;
Sind alle Dateien angelegt, können die Services mit diesen Befehlen aktiviert und gestartet werden.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
sudo systemctl daemon-reload&lt;br /&gt;
sudo systemctl reload dbus.service&lt;br /&gt;
sudo systemctl enable signal.service&lt;br /&gt;
sudo systemctl start signal.service&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ob alles funktioniert, kann wie folgt getestet werden:&lt;br /&gt;
*D-Bus:&lt;br /&gt;
 sudo -u fhem dbus-send --system --type=method_call --print-reply --dest=&amp;quot;org.asamk.Signal&amp;quot; /org/asamk/Signal org.asamk.Signal.sendMessage string:&amp;lt;Nachricht&amp;gt; array:string: string:&amp;lt;EmpfängerNummer&amp;gt;&lt;br /&gt;
*signal-cli über D-Bus:&lt;br /&gt;
 sudo -u fhem signal-cli --dbus-system  send -m &amp;quot;&amp;lt;Nachricht&amp;gt;&amp;quot; &amp;lt;EmpfängerNummer&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Einbindung des FHEM-Moduls ==&lt;br /&gt;
Solange das Modul &#039;&#039;&#039;32_SiSi.pm&#039;&#039;&#039; noch nicht via FHEM-Update verteilt wird, ist eine manuelle Installation notwendig. Das geschieht, in dem es von der [https://github.com/Quantum1337/32_SiSi.pm GitHub-Seite] des Modul-Autors heruntergeladen und in den FHEM-Ordner kopiert wird.&lt;br /&gt;
&lt;br /&gt;
Der Befehl&lt;br /&gt;
 wget https://raw.githubusercontent.com/Quantum1337/32_SiSi.pm/master/FHEM/32_SiSi.pm&lt;br /&gt;
speichert das Modul im aktuellen Verzeichnis.&lt;br /&gt;
&lt;br /&gt;
Mit den folgenden Befehlen wird das Modul ins das FHEM-Verzeichnis verschoben und anschließend die Datei-Rechte angepasst.&lt;br /&gt;
 sudo mv 32_SiSi.pm /opt/fhem/FHEM/&lt;br /&gt;
 sudo chown fhem:dialout /opt/fhem/FHEM/32_SiSi.pm&lt;br /&gt;
&lt;br /&gt;
Anschließend wird noch die lokale CommandRef aktualisiert:&lt;br /&gt;
 cd /opt/fhem&lt;br /&gt;
 sudo /usr/bin/perl contrib/commandref_join.pl&lt;br /&gt;
&lt;br /&gt;
Zum Abschluss wird das Modul noch FHEM bekannt gemacht. Dazu in der FHEM-Kommandozeile folgenden Befehl eingeben:&lt;br /&gt;
 reload 32_SiSi.pm&lt;br /&gt;
&lt;br /&gt;
==Verwendung des FHEM-Moduls==&lt;br /&gt;
Die genaue Verwendung des Moduls 32_SiSi.pm ist in der CommandRef beschrieben. Hier deshalb nur ein kleines Beispiel.&lt;br /&gt;
&lt;br /&gt;
SiSi-Device definieren:&lt;br /&gt;
 define Signal SiSi&lt;br /&gt;
&lt;br /&gt;
Dem Device mitteilen, dass es eine Verbindung zum signal-cli D-Bus Service herstellen soll:&lt;br /&gt;
 attr Signal enable yes&lt;br /&gt;
&lt;br /&gt;
Eine Standard-Empfängernummer definieren, falls im Befehlsaufruf keine angegeben ist:&lt;br /&gt;
 attr Signal defaultPeer +49170zzzzzzzz&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anschließend kann aus FHEM heraus eine Nachricht gesendet werden:&lt;br /&gt;
 set Signal msg Hurra, es funktioniert!&lt;br /&gt;
&lt;br /&gt;
===Zusammenspiel mit den Modulen Msg und Roommate===&lt;br /&gt;
Um mithilfe des Moduls [[Msg]] Signal-Nachrichten versenden zu können, ist im Device &#039;&#039;globalMsg&#039;&#039; das Attribut &#039;&#039;&#039;msgCmdPush&#039;&#039;&#039; zu setzen.&lt;br /&gt;
 attr globalMsg msgCmdPush set %DEVICE% msg @%RECIPIENT% %MSG%&lt;br /&gt;
&lt;br /&gt;
Optional kann ein Standard-Empfänger gesetzt werden der die Nachricht erhält, wenn beim Aufruf von &#039;&#039;Msg&#039;&#039; kein Empfänger angegeben wurde:&lt;br /&gt;
 attr globalMsg msgContactPush &amp;lt;Signal-Device&amp;gt;:&amp;lt;Empfängernummer&amp;gt;&lt;br /&gt;
Danach kann mit &amp;lt;code&amp;gt;msg Testnachricht&amp;lt;/code&amp;gt; eine Signal-Nachricht versendet werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Werden {{Link2CmdRef|Anker=ROOMMATE|Lang=de|Label=ROOMMATE-Devices}} verwendet, kann jedem eine Kontaktadresse hinterlegt werden, damit beim Aufruf von &#039;&#039;Msg&#039;&#039; einfach der Device-Name anstatt der Nummer angegeben werden kann. (Funktioniert natürlich  bei jedem anderen Device auch. Aber ein ROOMMATE-Device macht das ganze anschaulicher.)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
attr &amp;lt;ROOMMATE-Device&amp;gt; msgContactPush &amp;lt;Signal-Device&amp;gt;:&amp;lt;Empfängernummer&amp;gt;&lt;br /&gt;
&lt;br /&gt;
z.B.:&lt;br /&gt;
attr rr_Max msgContactPush Signal:+49...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Anschließend kann mit &amp;lt;code&amp;gt;msg @rr_Max Testnachricht&amp;lt;/code&amp;gt; eine Nachricht an Max gesendet werden.&lt;br /&gt;
&lt;br /&gt;
==Hinweise==&lt;br /&gt;
Derzeit ist es aufgrund von Einschränkungen in der D-Bus-API noch nicht möglich, mit dem SiSi-Modul neue Fingerprints von Kontakten hinzuzufügen oder aus Gruppen auszutreten. Daher muss beides noch manuell auf der Linux-Kommandozeile erfolgen.&lt;br /&gt;
&lt;br /&gt;
;Neuer Fingerprint&lt;br /&gt;
:Mit folgendem Befehl wird dieser Nummer wieder vertraut und &#039;&#039;signal-cli&#039;&#039; fügt den geänderten Fingerprint dann automatisch zu seiner Liste hinzu.&lt;br /&gt;
:&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;sudo -u fhem signal-cli -u &amp;lt;FHEM-NUMMER&amp;gt; trust -a &amp;lt;Nummer mit geänderten Fingerprint&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Aus einer Gruppe austreten&lt;br /&gt;
:Soll die &amp;quot;FHEM-Signal-Rufnummer&amp;quot; aus einer bestehende Gruppe entfernt werden, kann dieser Aufruf von &#039;&#039;signal-cli&#039;&#039; verwendet werden.&lt;br /&gt;
:&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;sudo -u fhem signal-cli -u &amp;lt;FHEM-NUMMER&amp;gt; quitGroup -g &amp;lt;GroupID&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Querverweise==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Signal]]&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=SIGNALduino_Compilieren&amp;diff=38695</id>
		<title>SIGNALduino Compilieren</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=SIGNALduino_Compilieren&amp;diff=38695"/>
		<updated>2023-11-09T10:51:46Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: veraltete &amp;quot;source&amp;quot;-Angaben in &amp;quot;syntaxhighlight&amp;quot; geändert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
== SIGNALduino in die Arduino Entwicklungsumgebung einbinden ==&lt;br /&gt;
Zur Inbetriebnahme von [[SIGNALduino]] auf der Arduino IDE (getestet mit auf Arduino V1.6.7) müssen die Quelltexte von [https://github.com/RFD-FHEM/SIGNALDuino/ GitHub] (Stand Feb. 2017) geladen werden.&lt;br /&gt;
&lt;br /&gt;
Dort &amp;lt;code&amp;gt;Clone or download&amp;lt;/code&amp;gt; und danach &amp;lt;code&amp;gt;Download ZIP&amp;lt;/code&amp;gt; klicken und das ZIP-Archiv auspacken oder auf der Kommandozeile &amp;lt;code&amp;gt;git clone https://github.com/RFD-FHEM/SIGNALDuino.git&amp;lt;/code&amp;gt; ausführen.&lt;br /&gt;
&lt;br /&gt;
Es werden folgende Dateien benötigt:&lt;br /&gt;
* Die Datei &amp;lt;code&amp;gt;RF_Receiver.ino&amp;lt;/code&amp;gt; in einen Ordner &amp;lt;code&amp;gt;RF_Receiver&amp;lt;/code&amp;gt;, am besten direkt ins &amp;lt;code&amp;gt;Arduino&amp;lt;/code&amp;gt; Verzeichnis der IDE kopieren.&lt;br /&gt;
* Im &amp;lt;code&amp;gt;libraries&amp;lt;/code&amp;gt; Ordner der Arduino IDE am besten einen Ordner mit Namen &amp;lt;code&amp;gt;SIGNALduino&amp;lt;/code&amp;gt; anlegen, dort müssen dann die Dateien &amp;lt;code&amp;gt;bitstore&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;signalDecoder&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;SimpleFIFO&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;TimerOne&amp;lt;/code&amp;gt; (jeweils &amp;lt;code&amp;gt;.cpp&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;.h&amp;lt;/code&amp;gt; Datei) abgelegt werden.&lt;br /&gt;
* In diesem &amp;lt;code&amp;gt;SIGNALduino&amp;lt;/code&amp;gt; Verzeichnis ist dann noch ein Unterverzeichnis &amp;lt;code&amp;gt;config&amp;lt;/code&amp;gt; anzulegen, dort muss die Datei &amp;lt;code&amp;gt;known_16bit_timers.h&amp;lt;/code&amp;gt; abgelegt werden.&lt;br /&gt;
&lt;br /&gt;
Struktur der SIGNALduino libraries:[[Datei:SIGNALduino-ViaArduinoEnvironment.jpg]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In der Arduino Entwicklungsumgebung unter &amp;lt;code&amp;gt;Werkzeuge&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;Board&amp;lt;/code&amp;gt; &amp;lt;tt&amp;gt;&#039;&#039;&#039;&amp;quot;Arduino Nano&amp;quot;&#039;&#039;&#039;&amp;lt;/tt&amp;gt; und unter &amp;lt;code&amp;gt;Werkzeuge&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;Prozessor&amp;lt;/code&amp;gt; &amp;lt;tt&amp;gt;&#039;&#039;&#039;&amp;quot;ATmega328&amp;quot;&#039;&#039;&#039;&amp;lt;/tt&amp;gt; angeben. Nach Einstecken des SIGNALduinos in die USB Buchse noch den entsprechenden &amp;lt;code&amp;gt;COM-Port&amp;lt;/code&amp;gt; unter &amp;lt;code&amp;gt;Werkzeuge&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;Port&amp;lt;/code&amp;gt; angeben, danach sollte sich der Scetch &amp;lt;code&amp;gt;RF_Receiver.ino&amp;lt;/code&amp;gt; übersetzen und auf den SIGNALduino laden lassen.&lt;br /&gt;
&lt;br /&gt;
== SIGNALduino mit Makefile unter Linux ==&lt;br /&gt;
Wer lieber auf der Kommandozeile arbeitet kann SIGNALduino auch mit einem Makefile übersetzen und laden.&lt;br /&gt;
Benötigt werden dazu:&lt;br /&gt;
* Der Cross-Compiler und alle Werkzeuge für Arduino bzw. AVR. Bei Ubuntu und Debian Systemen:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=bash&amp;gt;&lt;br /&gt;
# Arduino Pakete installieren:&lt;br /&gt;
sudo apt-get install arduino arduino-core arduino-mighty-1284p arduino-mk&lt;br /&gt;
# AVR&lt;br /&gt;
sudo apt-get install flashrom gcc-avr avrdude avr-libc binutils-avr&lt;br /&gt;
# Die Unterstützung der Braillezeile kann zu Konflikten um den seriellen Port führen&lt;br /&gt;
sudo apt-get remove brltty brltty-x11&lt;br /&gt;
# Arduino-Makefile verwendet YAML und serialport in Perl&lt;br /&gt;
sudo apt-get libdevice-serialport-perl libyaml-perl&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
In den Paketen sind die Arduino Quellen und Arduino-Makefile enthalten.&lt;br /&gt;
Bei wem das aber nicht klappt, der sollte wie hier beschrieben die neuesten Versionen verwenden.&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/RFD-FHEM/SIGNALDuino.git SIGNALDuino Quelltexte]&lt;br /&gt;
&amp;lt;syntaxhighlight lang=bash&amp;gt;&lt;br /&gt;
# Hier kann man natürlich jedes beliebige Verzeichnis nehmen.&lt;br /&gt;
mkdir -p ~/src/arduino; cd ~/src/arduino&lt;br /&gt;
# SIGNALDuino von github clonen&lt;br /&gt;
git clone https://github.com/RFD-FHEM/SIGNALDuino.git&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Die [https://www.arduino.cc/en/Main/Software Arduino Quellen] (optional)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=bash&amp;gt;&lt;br /&gt;
# siehe https://www.arduino.cc/en/Main/Software für neueste Version&lt;br /&gt;
wget https://downloads.arduino.cc/arduino-1.8.5-linux64.tar.xz&lt;br /&gt;
tar xvJf arduino-1.8.5-linux64.tar.xz&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Die neueste Version Arduino-Makefile (optional)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=bash&amp;gt;&lt;br /&gt;
# Neueste Version von github clonen&lt;br /&gt;
git clone https://github.com/sudar/Arduino-Makefile.git&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Jetzt muss in &amp;lt;code&amp;gt;SIGNALDuino/RF_Receiver&amp;lt;/code&amp;gt; noch ein &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; erstellt werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=make&amp;gt;&lt;br /&gt;
# Verzeichnis in dem die Arduino-Quellen liegen&lt;br /&gt;
ARDUINO_DIR=$(HOME)/src/arduino/arduino-1.8.5&lt;br /&gt;
# Verzeichnis mit dem Arduino-Makefile&lt;br /&gt;
ARDMK_DIR=$(HOME)/src/arduino/Arduino-Makefile&lt;br /&gt;
# Basisverzeichnis unter dem die AVR-Werkzeuge liegen&lt;br /&gt;
AVR_TOOLS_DIR=/usr&lt;br /&gt;
AVRDUDE_OPTS = -v&lt;br /&gt;
# Ab Arduino 1.5 sollte man die Architektur angeben.&lt;br /&gt;
ARCHITECTURE  = avr&lt;br /&gt;
BOARD_TAG = nano&lt;br /&gt;
BOARD_SUB = atmega328&lt;br /&gt;
USER_LIB_PATH += $(realpath ../src/_micro-api/libraries)&lt;br /&gt;
ARDUINO_LIBS += bitstore output signalDecoder SimpleFIFO TimerOne EEPROM&lt;br /&gt;
# Device des Arduino nano&lt;br /&gt;
MONITOR_PORT  = /dev/ttyUSB0&lt;br /&gt;
# AVRDUDE      = /usr/bin/avrdude&lt;br /&gt;
AVRDUDE_CONF = /etc/avrdude.conf&lt;br /&gt;
include $(ARDMK_DIR)/Arduino.mk&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Wer die Arduino Quellen und Arduino-Makefile aus der Paketverwaltung verwenden möchte, kann folgendes ändern:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=make&amp;gt;&lt;br /&gt;
ARDUINO_DIR=/usr/share/arduino&lt;br /&gt;
ARDMK_DIR=$(ARDUINO_DIR)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit Stand vom 17.02.2018 müssen jetzt noch ein paar kleine Fehler beseitigt werden:&lt;br /&gt;
Präprozessor-Direktiven werden nicht mit Semikolon abgeschlossen&lt;br /&gt;
* in &amp;lt;code&amp;gt;RF_Receiver/RF_Receiver.ino&amp;lt;/code&amp;gt;&lt;br /&gt;
:* &amp;lt;code&amp;gt;#define CMP_NEWSD&amp;lt;/code&amp;gt; statt &amp;lt;code&amp;gt;#define CMP_NEWSD;&amp;lt;/code&amp;gt;&lt;br /&gt;
Linux unterscheidet Groß- und Kleinschreibung bei Dateien:&lt;br /&gt;
* in &amp;lt;code&amp;gt;src/_micro-api/libraries/output/src/output.h&amp;lt;/code&amp;gt;&lt;br /&gt;
* und in &amp;lt;code&amp;gt;src/_micro-api/libraries/signalDecoder/src/signalDecoder.h&amp;lt;/code&amp;gt;&lt;br /&gt;
:* &amp;lt;code&amp;gt;  #include &amp;quot;Arduino.h&amp;quot;&amp;lt;/code&amp;gt; statt &amp;lt;code&amp;gt;  #include &amp;quot;arduino.h&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
Das Makefile ignoriert Bibliotheken ohne &amp;lt;code&amp;gt;library.properties&amp;lt;/code&amp;gt;&lt;br /&gt;
* in &amp;lt;code&amp;gt;src/_micro-api/libraries/signalDecoder&amp;lt;/code&amp;gt; fehlt &amp;lt;code&amp;gt;library.properties&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=bash&amp;gt;&lt;br /&gt;
cd src/_micro-api/libraries/signalDecoder&lt;br /&gt;
cp ../bitstore/library.properties .&lt;br /&gt;
sed -i &#039;s/bitstore/signalDecoder/g&#039; library.properties&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Danach kann SIGNALDuino für den Arduino Nano übersetzt werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=bash&amp;gt;&lt;br /&gt;
cd RF_Receiver&lt;br /&gt;
make&lt;br /&gt;
# Auf den Arduino laden (flashen)&lt;br /&gt;
make upload&lt;br /&gt;
# Aufräumen mit&lt;br /&gt;
make clean&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== SIGNALDuino konfigurieren und testen ==&lt;br /&gt;
[[Datei:Fhemduino_schematic.png|mini|FHEMduino bzw. SIGNALDuino Schaltplan]]&lt;br /&gt;
In der Datei &amp;lt;code&amp;gt;RF_Receiver.ino&amp;lt;/code&amp;gt; sind u.a. folgende Einstellungen:&lt;br /&gt;
* &amp;lt;code&amp;gt;BAUDRATE&amp;lt;/code&amp;gt; Die Datenrate mit der SIGNALDuino mit dem PC kommuniziert (Voreinstellung 57600). Man kann also z.B. mit &amp;lt;code&amp;gt;minicom -D /dev/ttyUSB0 -8 -b 57600&amp;lt;/code&amp;gt; die Kommunikation testen.&lt;br /&gt;
* &amp;lt;code&amp;gt;PIN_LED&amp;lt;/code&amp;gt; Der Pin an dem die LED zur Signalisierung von Nachrichten angeschlossen ist (Voreinstellung D13 = LED &amp;lt;code&amp;gt;L&amp;lt;/code&amp;gt; auf dem Nano).&lt;br /&gt;
* &amp;lt;code&amp;gt;PIN_RECEIVE&amp;lt;/code&amp;gt; Der Pin zum Empfang von Daten (Voreinstellung D2).&lt;br /&gt;
* &amp;lt;code&amp;gt;PIN_SEND&amp;lt;/code&amp;gt; Der Pin zum Senden von Daten (Voreinstellung D11).&lt;br /&gt;
&lt;br /&gt;
Öffnet man ein Terminal (z.B. &amp;lt;code&amp;gt;minicom&amp;lt;/code&amp;gt; siehe oben) so kann man die Kommandoschnittstelle des SIGNALDuino probieren:&lt;br /&gt;
* Eingabe &amp;quot;&amp;lt;code&amp;gt;?&amp;lt;/code&amp;gt; Enter&amp;quot; listet die verfügbaren Kommandos: &#039;&#039;Use one of V i R t X F S P C G&#039;&#039;&lt;br /&gt;
:* &amp;lt;code&amp;gt;V&amp;lt;/code&amp;gt;: Zeigt die Version der Software&lt;br /&gt;
:* &amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt;: Präfix für ein Intertechno-Kommando.&lt;br /&gt;
:* &amp;lt;code&amp;gt;R&amp;lt;/code&amp;gt;: Zeigt den freien Arbeitsspeicher (RAM) in Bytes&lt;br /&gt;
:* &amp;lt;code&amp;gt;t&amp;lt;/code&amp;gt;: Zeigt die Dauer des Betriebs seit dem letzten Start in Sekunden (uptime).&lt;br /&gt;
:* &amp;lt;code&amp;gt;XQ&amp;lt;/code&amp;gt;: Empfänger abschalten (RX Quit)&lt;br /&gt;
:* &amp;lt;code&amp;gt;XE&amp;lt;/code&amp;gt;: Empfänger einschalten (RX Enable)&lt;br /&gt;
:* &amp;lt;code&amp;gt;F&amp;lt;/code&amp;gt;: Filter wechseln (derzeit ohne Funktion)&lt;br /&gt;
:* &amp;lt;code&amp;gt;S&amp;lt;/code&amp;gt;: Präfix für das Aussenden von Nachrichten.&lt;br /&gt;
:* &amp;lt;code&amp;gt;P&amp;lt;/code&amp;gt;: Prüft die Kommunikation (Ping). Antwortet mit &amp;quot;OK&amp;quot;.&lt;br /&gt;
:* &amp;lt;code&amp;gt;CG&amp;lt;/code&amp;gt;: Abfrage der Konfiguration (Config Get) aus dem EEPROM.&lt;br /&gt;
:* &amp;lt;code&amp;gt;CES&amp;lt;/code&amp;gt;: Aktiviere Nachrichten mit Sync Puls (Config Enable Sync).&lt;br /&gt;
:* &amp;lt;code&amp;gt;CEC&amp;lt;/code&amp;gt;: Aktiviere Nachrichten mit Manchester Code (Config Enable Manchester Code).&lt;br /&gt;
:* &amp;lt;code&amp;gt;CEU&amp;lt;/code&amp;gt;: Aktiviere nicht synchronisierte Nachrichten (Config Enable Unsync).&lt;br /&gt;
:* &amp;lt;code&amp;gt;CD[SCU]&amp;lt;/code&amp;gt;: Deaktivieren den entsprechenden Nachrichtentyp (z.B. &amp;lt;code&amp;gt;CDU&amp;lt;/code&amp;gt; deaktiviert asynchron).&lt;br /&gt;
:* &amp;lt;code&amp;gt;G&amp;lt;/code&amp;gt;: Veraltete Abfrage der Konfiguration, sollte mit &amp;lt;code&amp;gt;CG&amp;lt;/code&amp;gt; gemacht werden.&lt;br /&gt;
&lt;br /&gt;
Als erstes sollte man mit dem Terminalprogramm ein großes &amp;quot;P&amp;quot; gefolgt von den Eingabetaste eingeben.&lt;br /&gt;
Bei korrekter Verbindung sollte der SIGNALDuino mit &amp;quot;OK&amp;quot; antworten.&lt;br /&gt;
&lt;br /&gt;
== Foren Links ==&lt;br /&gt;
* {{Link2Forum|Topic=58396|LinkText=SIGNALDuino Empfänger Firm- und Hardware}}&lt;br /&gt;
* {{Link2Forum|Topic=58397|LinkText=Signalduino Entwicklung Version 3.3.1 }}&lt;br /&gt;
* [http://www.nemcon.nl/blog2/wiring Beschreibung zu diversen Empfängern und Verbesserung der Empfangsleistung]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;br /&gt;
[[Kategorie:Other Components]]&lt;br /&gt;
[[Kategorie:Interfaces]]&lt;br /&gt;
[[Kategorie:Arduino]]&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Quick-Start/en&amp;diff=38694</id>
		<title>Quick-Start/en</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Quick-Start/en&amp;diff=38694"/>
		<updated>2023-11-09T10:50:38Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: veraltete &amp;quot;source&amp;quot;-Angaben in &amp;quot;syntaxhighlight&amp;quot; geändert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|zur deutschen Version geht es [[Quick-Start|hier]]}}&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
First step is to install FHEM on your server (dedicated hardware or virtual machine). We provide instructions for different operating systems [https://fhem.de/#Installation here].&lt;br /&gt;
&lt;br /&gt;
Having started FHEM the first time, please have a look at the FHEM logfile&amp;lt;ref&amp;gt;In most cases you&#039;ll find the log in &amp;lt;code&amp;gt;/opt/fhem/log&amp;lt;/code&amp;gt;&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Most installations use Linux as operating system for the server. So if not stated differently, the commands and examples provided here use the syntax for Linux&amp;lt;/ref&amp;gt;. The log file will look something like the following example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
2018.03.09 09:17:51 1: Including fhem.cfg&lt;br /&gt;
2018.03.09 09:17:51 3: telnetPort: port 7072 opened&lt;br /&gt;
2018.03.09 09:17:51 3: WEB: port 8083 opened&lt;br /&gt;
2018.03.09 09:17:51 3: WEBphone: port 8084 opened&lt;br /&gt;
2018.03.09 09:17:51 3: WEBtablet: port 8085 opened&lt;br /&gt;
2018.03.09 09:17:51 2: eventTypes: loaded 0 events from ./log/eventTypes.txt&lt;br /&gt;
2018.03.09 09:17:51 1: usb create starting&lt;br /&gt;
2018.03.09 09:17:51 3: [...]&lt;br /&gt;
2018.03.09 09:17:51 1: usb create end&lt;br /&gt;
2018.03.09 09:17:51 0: Featurelevel: 5.8&lt;br /&gt;
2018.03.09 09:17:51 0: Server started with 9 defined entities (fhem.pl:16349/2018-03-07 perl:5.024001 os:linux user:fhem pid:9341)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Talking to FHEM==&lt;br /&gt;
After installation, FHEM can be accessed by a {{Link2CmdRef|Anker=FHEMWEB|Lang=en|Label=FHEMWEB}}interface to be found at the following URL:&lt;br /&gt;
&#039;&#039;&#039;http://&amp;lt;fhem-server&amp;gt;:8083/fhem&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
{{Hinweis|You may add more FHEMWEB devices. This may be helpfull in case you want to use a different style than default &#039;&#039;f18&#039;&#039; on smaller display sizes or provide pages with limited options to controll FHEM for other users. In case you need a lower level communication channel to FHEM, e.g. for scripting or emergancy cases, have a look at [[Telnet|telnet]].}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
datei:ErsteSchritteInFhem01.png|Desktop version of the FHEM start screen just after installation &lt;br /&gt;
datei:erster_aufruf_smartphone.png|Smallscreen version of the start screen&lt;br /&gt;
Datei:Erster_aufruf_telnet.png|A new telnet connection after issuing a &#039;&#039;version&#039;&#039; command&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Elements of the web interface:&lt;br /&gt;
*The input box at the top is used to enter commands and here referred to as &amp;quot;command field&amp;quot;. Finish your typing with {{Taste|Enter}} to pass the commands to FHEM for processing.&lt;br /&gt;
*Left of the command field there&#039;s a symbol (+). Clicking will prompt a popup field to enter [[Import von Code Snippets|RAW-Code]] - a very effective way to enter multiple command lines in one step.&lt;br /&gt;
*The menu on the left starts with the item &#039;&#039;Save config&#039;&#039;. FHEM allows to change its configuration at runtime. To make changes permanent and keep them available after restart of FHEM or the server hardware also, they have to be written to a configuration file&amp;lt;ref&amp;gt;In most cases this is a text file, but you may also use a database. See {{Link2CmdRef|Anker=configDB|Lang=en|Label=configDB}} for how to use a database as configuration source&amp;lt;/ref&amp;gt;. If you see a red &#039;&#039;?&#039;&#039; beneath this menu item, this indicates unsaved changes of your configuration.&lt;br /&gt;
*Below &amp;quot;Save config&amp;quot; is a section listing the &amp;quot;rooms&amp;quot; known by FHEM. At first start you will only find the rooms &#039;&#039;Unsorted&#039;&#039; and &#039;&#039;Everything&#039;&#039;. New rooms will automatically appear if you assign the respective attribute&amp;lt;ref&amp;gt;Further informationen on the terminology used in a FHEM context is provided in our [[:Kategorie:Glossary|glossary (german)]]&amp;lt;/ref&amp;gt; to the devices&amp;lt;ref&amp;gt;Please note: The term &amp;quot;&#039;&#039;&#039;device&#039;&#039;&#039;&amp;quot; is often used used in the FHEM context in a special way. This could - but must not necessarily be - a physical piece of equipment. &amp;quot;Device&amp;quot; just is a term for any physical or virtual &amp;quot;object&amp;quot; that can be introduced in a FHEM system by a &#039;&#039;define&#039;&#039; or &#039;&#039;defmod&#039;&#039; command.&amp;lt;/ref&amp;gt; you add later on.&lt;br /&gt;
*The - preliminary - last section of the menu is built by some links you might find useful.&lt;br /&gt;
&lt;br /&gt;
==Securing the FHEM server component==&lt;br /&gt;
As you have already seen, in a fresh installation you merely have to be in the same network segment to have full access to the FHEM server. There&#039;s no encryption nor authorization by user or password. This is why you get respective warnings at FHEM&#039;s starting page.&lt;br /&gt;
FHEM may be secured using one of the following options:&lt;br /&gt;
&lt;br /&gt;
===allowed and SSL===&lt;br /&gt;
These two methods may be combined and can be used to secure one or both ways (telnet and web interface) to interact with and configure FHEM. Allowed restricts access by user authentication, SSL adds transport layer encryption (HTTPS/SSL).&lt;br /&gt;
&lt;br /&gt;
{{Randnotiz|RNTyp=b|RNText=For instructions on how to use FHEM commands and additional info just type &amp;lt;code&amp;gt;help &amp;lt;command&amp;gt;&amp;lt;/code&amp;gt; in the command field and press {{Taste|Enter}}.}}&lt;br /&gt;
It is recommended to define one or more &#039;&#039;allowed&#039;&#039; devices. For instructions on how to do this, please have a look at our {{Link2CmdRef|Anker=allowed|Lang=en|Label=CommandRef}} or just pass &amp;lt;code&amp;gt;help allowed&amp;lt;/code&amp;gt; to the command field.&lt;br /&gt;
&lt;br /&gt;
As long as there&#039;s no allowed device defined, FHEM restricts all interfaces access&#039; to the local network.&lt;br /&gt;
{{Randnotiz|RNTyp=b|RNText=The notation &amp;lt;code&amp;gt;&amp;lt;command&amp;gt; &amp;lt;parameter&amp;gt;&amp;lt;/code&amp;gt; is not only used here, but is also very common in other documents and examples you&#039;ll find when using FHEM. In these cases you are asked to replace the placeholder in the brackets (including the &amp;quot;&amp;lt;&amp;gt;&amp;quot;-brackets) by your own meaningful content.}}&lt;br /&gt;
&lt;br /&gt;
Additionally you may add for your FHEMWEB device, whose sole purpose is to serve you FHEM via browser, a {{Link2CmdRef|Anker=HTTPS|Lang=en|Label=HTTPS}} attribute to activate HTTPS for http connections. For telnet (being also to some extent also a TCP/IP port) please use the {{Link2CmdRef|Anker=SSL|Lang=en|Label=SSL}} attribute. &lt;br /&gt;
&lt;br /&gt;
By default, none of these securing methods is activated. If you are securing your server and FHEM by other methods you may switch off the respective warning using the global attribute {{Link2CmdRef|Anker=motd|Lang=en|Label=motd}}.&lt;br /&gt;
&lt;br /&gt;
===FHEM and the WWW===&lt;br /&gt;
If you intend to have access to FHEM not only from your local net it is highly recommended to take additional measures. Common options are to use a VPN (Virtual Private Network) and/or a reverse proxy server like [[Apache_Authentication_Proxy|Apache]] or [[HTTPS-Absicherung_%26_Authentifizierung_via_nginx_Webserver|nginx]].&lt;br /&gt;
&lt;br /&gt;
===Additional remarks on security===&lt;br /&gt;
Please note: Running a server system requires regular updates to the operating system and other software components installed on it. Besides that, any other components you use for home automation will contribute to the level of (non-)security of the entire system you run in the end.&lt;br /&gt;
&lt;br /&gt;
==Interfaces to the real world==&lt;br /&gt;
{{Randnotiz|RNTyp=b|RNText=If at this point you do not have any hardware to be included in your FHEM you may follow our [[First steps in FHEM|first steps in FHEM]] to get an impression how to configure devices in FHEM.}}To get information about what is happening in the real world, you have to somehow connect FHEM with it. &lt;br /&gt;
&lt;br /&gt;
Many FHEM installations use one or more USB devices (e.g. CUL, FHZ1x00, TCM, ZWave, ...) directly attached to the FHEM server for this task. To use this type of connection&amp;lt;ref&amp;gt;This also applies when devices are attached using serial interfaces provided at GPIO pins of single-board computers like the &#039;&#039;Raspberry Pi&#039;&#039;.&amp;lt;/ref&amp;gt; you need additional pieces of software, especially the Perl module &#039;&#039;serial&#039;&#039;&amp;lt;ref&amp;gt;The Perl-&#039;&#039;serial&#039;&#039;-module can either be installed by issuing the &amp;lt;code&amp;gt;sudo cpan Device::SerialPort&amp;lt;/code&amp;gt; command at OS level or by installing precompiled Debian packages (&#039;&#039;libdevice-serialport-perl&#039;&#039;). Beginning with Mac OS X 10.5 (Leopard) the module is also provided as package. If the perl module is not available for your operating  system you may use the &#039;&#039;@directio&#039;&#039;-option (see commandref for further information).&amp;lt;/ref&amp;gt;. Have a look at the respective part of the commandref for details about the configuration of your USB device(s). The Perl module is not required if the device is connected via Ethernet (e.g. HM-LAN or CUNO). &lt;br /&gt;
&lt;br /&gt;
===Automatic Configuration===&lt;br /&gt;
By default FHEM will try to identify commonly used USB devices like FHZ, CUL&amp;lt;ref&amp;gt;In a Linux environment, FHEM will also try to flash an attached CUL in case it&#039;s not yet programmed with firmware. For details see the descriptions of the commands &amp;lt;code&amp;gt;usb&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CUL flash&amp;lt;/code&amp;gt; in commandref.&amp;lt;/ref&amp;gt;, COC, ZWave or TCM. These just have to be attached when FHEM is starting to have FHEM write the respective parts to its configuration file. When attaching devices to a running FHEM you have to issue a &amp;lt;code&amp;gt;shutdown restart&amp;lt;/code&amp;gt; in the command field to start the auto configuration.&lt;br /&gt;
&lt;br /&gt;
Typically you&#039;ll have to do additional configuration work also for automatically detected devices by assigning the appropriate values to attributes. You can easily get an overview of the available attributes and to some extent also a set of values for them by just clicking the name of the device shown in the respective room. New devices in most cases can be found in the room &#039;&#039;Unsorted&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Once you have basic definitions of all of your USB devices it&#039;s recommended to deactivate the automatic recognition of USB devices by entering &amp;lt;code&amp;gt;attr initialUsbCheck disable 1&amp;lt;/code&amp;gt; to the command field.&lt;br /&gt;
	&lt;br /&gt;
===Manual Configuration===&lt;br /&gt;
{{Randnotiz|RNTyp=g|RNText=In commandref you&#039;ll find again a notation like &amp;lt;code&amp;gt;define &amp;lt;name&amp;gt; CUL &amp;lt;device&amp;gt; &amp;lt;FHTID&amp;gt;&amp;lt;/code&amp;gt;. Please replace the placeholders in the brackets with own content and also delete the brackets.}}&lt;br /&gt;
USB devices can easily also be configured manualy, especially in cases they are not automatically detected as described above. After plugging them in, just look where these are located in your file system - typically somewhere in the directory &amp;lt;code&amp;gt;/dev&amp;lt;/code&amp;gt;. E.g. a CUL will be found as a file &#039;&#039;/dev/ttyACM*&#039;&#039; in a Linux environment. Mac OS X will label the same device as &#039;&#039;/dev/cu.usbmodem*&#039;&#039;. Use this description (entire path and file name) to enter the define command directly in the command field.&lt;br /&gt;
Examples:&lt;br /&gt;
*A CUL stick can be defined like this: &amp;lt;code&amp;gt;define CUL1 CUL /dev/ttyACM0@9600 1234&amp;lt;/code&amp;gt;&amp;lt;ref&amp;gt;Please note: the number &amp;quot;1234&amp;quot; is just an example; replace this by your own parameter&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Z-Wave controller: &amp;lt;code&amp;gt;define ZWDongle ZWDongle /dev/serial/by-id/usb-0658_0200-if00@115200&amp;lt;/code&amp;gt;&amp;lt;ref&amp;gt;This type of representation of the USB device in the Linux file system can also be used. To get the information in that form, you just type &amp;lt;code&amp;gt;ls -l /dev/serial/by-id&amp;lt;/code&amp;gt; at operating system level&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Please consult the {{Link2CmdRef|Lang=en|Label=commandref}} for further information on configuration of a specific device.&lt;br /&gt;
&lt;br /&gt;
==Adding and configuring sensors and actors==&lt;br /&gt;
&lt;br /&gt;
===autocreate===&lt;br /&gt;
By default, FHEM is also configured to automatically add to your configuration all kinds of devices it detects when running. This especially happens when you use RF equipment. FHEM will use its &#039;&#039;autocreate&#039;&#039; function as soon as the respective device sends data over the air.&lt;br /&gt;
&lt;br /&gt;
So if you want to include sensors like S300 or FHT, all you have to do is to attach an appropriate USB device for reception of messages sent by your devices and wait, look out for changes in the logfile and refresh the FHEM webpage in your browser. The naming of newly detected devices is oriented on their technical parameters.&lt;br /&gt;
&lt;br /&gt;
===Rename===&lt;br /&gt;
{{Randnotiz|RNTyp=g|RNText=When renaming a device, also the respective logfiles and weblinks will be renamed automatically. Please note: It is possible to manually rename also the weblinks or logfiles, but in this case, the corresponding main device will not be renamed alongside.}}You may use the command &amp;lt;code&amp;gt;rename&amp;lt;/code&amp;gt; to change this to your needs and likes. So for example for a FHT sensor you can type in the command field:&lt;br /&gt;
&lt;br /&gt;
    rename FHT_1234 fht.kitchen &lt;br /&gt;
&lt;br /&gt;
===Manual Definition of Devices===&lt;br /&gt;
If you want to manually add a device or have to do so because autocreate won&#039;t work, you have to follow these steps:&lt;br /&gt;
&lt;br /&gt;
Wait until the device sends some data. In the FHEM logfile (available via the menu at &amp;quot;Unsorted -&amp;gt; FileLog -&amp;gt; Logfile -&amp;gt; text&amp;quot;) you may see e.g. the following line:&lt;br /&gt;
&lt;br /&gt;
    FS20 Unknown device &amp;lt;HOUSECODE&amp;gt;, Button &amp;lt;BTN&amp;gt; Code &amp;lt;CDE&amp;gt;, please define it  &lt;br /&gt;
&lt;br /&gt;
Add the new device by passing the following command to the command field:&lt;br /&gt;
&lt;br /&gt;
    define piri1 FS20 &amp;lt;HOUSECODE&amp;gt; &amp;lt;BTN&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
Set the appropriate &#039;&#039;model&#039;&#039; attribute:&lt;br /&gt;
&lt;br /&gt;
    attr piri1 model fs20piri  &lt;br /&gt;
&lt;br /&gt;
Once you did that, the other attributes you may set are restricted to the ones that really apply to the chosen model. &lt;br /&gt;
Also for other RF types of hardware devices not automatically recognized there should appear a similar line in the logfile.&lt;br /&gt;
&lt;br /&gt;
The exact procedure to include other types of RF equipment typically varies.&lt;br /&gt;
E.g. HomeMatic devices do not necessarily need to be under full control of FHEM (paired). To be included by autocreate, a HomeMatic device has to send a pairing request, and FHEM has to enter a special mode to accept this request. Enter &amp;lt;code&amp;gt;set CUL hmPairForSec 600&amp;lt;/code&amp;gt; in the command field to make the latter happen and see the manual of the device how to do it on that end. ZWave devices require a similar procedure with slightly different commands. &lt;br /&gt;
&lt;br /&gt;
===Including Devices by Sending Configuration Commands===&lt;br /&gt;
&lt;br /&gt;
Some types of devices require special RF commands to configure them for usage with a central unit like FHEM or to link them directly with other devices (e.g. a PIR message used directly by a switch). To include that type of hardware, you have to first manually configure FHEM to prepare it to send out these so called learning messages.&lt;br /&gt;
&lt;br /&gt;
E.g. a FS20 device can be defined like this:&lt;br /&gt;
&lt;br /&gt;
    define lamp1 FS20 1234 56&lt;br /&gt;
&lt;br /&gt;
Prepare the device by pressing its physical registration button until the LED starts blinking. Then you click on the link in the device&#039;s FHEM web page to send out the learning command. The LED should stop blinking to indicate that it now is programmed to house code 1234 and device code 56. You may also use the 4-base ELV notation instead. Once this is sucessfully done, you may again set model specific attributes to limit the available options to ones relevant for this model, e.g.:&lt;br /&gt;
&lt;br /&gt;
    attr lamp1 model fs20st&lt;br /&gt;
&lt;br /&gt;
{{Randnotiz|RNTyp=b|RNText=Whenever there&#039;s a (FHT/HomeMatic/EnOcean or other) device visible in FHEM after automatic or manual inclusion this not necessarily means it also is fully integrated or &amp;quot;paired&amp;quot;. It is highly recommended to check out first if there are still commands pending or options to be set and sent to the device first!}}Other types of RF systems (EnOcean/HomeMatic/ZWave) also need specific and substantial procedures to be followed to get these devices under full control of FHEM. Please have a look at the corresponding section of the commandref and the manual of the device before starting these procedures.&lt;br /&gt;
&lt;br /&gt;
==Basics about controlling your devices==&lt;br /&gt;
Once your sensors and actors are correctly defined in FHEM you will be able to control any of your actors using FHEM&#039;s telnet or web interface. &lt;br /&gt;
{{Randnotiz|RNTyp=b|RNText=If you start with FHEM and are able to read German, it&#039;s recommended to read the [http://fhem.de/Heimautomatisierung-mit-fhem.pdf Einführung in die Automatisierung mit FHEM]. This document is - beside some details - still up to date. Although new features like the f18 style, modules like {{Link2CmdRef|Anker=allowed|Label=allowed}} or {{Link2CmdRef|Anker=DOIF|Label=DOIF}} are not covered there, and the selection of available hardware systems has continued to increase since its last update. Nevertheless, this introduction still offers a quite comprehensive overview of the general procedures and possibilities with FHEM.&lt;br /&gt;
&lt;br /&gt;
The module DOIF has only a short {{Link2CmdRef|Anker=DOIF|Label=English commandref}}. The complete commandref is provided by the module maintainer only in {{Link2CmdRef|Anker=DOIF|Lang=de|Label=German with several example codes}}. If you can&#039;t understand this or don&#039;t want to get used to DOIF for this reason: you can use the full functionality of FHEM without DOIF. Use for example {{Link2CmdRef|Anker=notify|Label=notify}}, {{Link2CmdRef|Anker=at|Label=at}} and the other modules instead.}}&lt;br /&gt;
&lt;br /&gt;
===Timer===&lt;br /&gt;
The most basic way to implement timer functionality in FHEM is to define an &amp;quot;at&amp;quot;.&lt;br /&gt;
Examples and basic instructions you&#039;ll find in the {{Link2CmdRef|Lang=en|Anker=at|Label=commandref}}.&lt;br /&gt;
&lt;br /&gt;
===Reacting on events from the real world===&lt;br /&gt;
If you want FHEM to react to any message sent by one or more sensors or other devices (an &amp;quot;event&amp;quot; in FHEM terminology), you use an [[event handler]].&lt;br /&gt;
The basic event handler in FHEM is called {{Link2CmdRef|Lang=en|Anker=notify|Label=notify}}; another one is for example {{Link2CmdRef|Lang=en|Anker=DOIF|Label=DOIF}}.&lt;br /&gt;
&lt;br /&gt;
Please open a new tab in your browser with the [[Event monitor]] or open a telnet connection by:&lt;br /&gt;
&lt;br /&gt;
    telnet &amp;lt;fhemhost&amp;gt; 7072&lt;br /&gt;
&lt;br /&gt;
Once the connection is opened type:&lt;br /&gt;
&lt;br /&gt;
    inform timer &lt;br /&gt;
&lt;br /&gt;
Now you will see all events in the telnet connection or the Event Monitor. E.g.:&lt;br /&gt;
&lt;br /&gt;
    2011-12-16 21:51:55 FS20 myPiri on-for-timer 120 &lt;br /&gt;
&lt;br /&gt;
If you mark the line you want to react on, you may ask the assistant in the Event Monitor to help you to define a reaction to such an event. This may be something like:&lt;br /&gt;
&lt;br /&gt;
    define lampNotify notify myPiri set myLamp on &lt;br /&gt;
	&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
    define lampNotify notify myPiri:on.* set myLamp on &lt;br /&gt;
&lt;br /&gt;
To test if this notify or DOIF acts as expected you may use the &amp;lt;code&amp;gt;trigger&amp;lt;/code&amp;gt; command to simulate an event in the real world. E.g.:&lt;br /&gt;
&lt;br /&gt;
    trigger myPiri on-for-timer 120 &lt;br /&gt;
&lt;br /&gt;
[[at]], [[notify]] and other [[event handler]] like {{Link2CmdRef|Anker=DOIF_|Lang=de|Label=DOIF}}&amp;lt;ref&amp;gt;[[DOIF]] combines event control, time control, state machine and frontend in one modul&amp;lt;/ref&amp;gt;, {{Link2CmdRef|Anker=sequence|Lang=de|Label=sequence}}&amp;lt;ref&amp;gt;[[sequence]] handles series of [[Event|events]]&amp;lt;/ref&amp;gt;, {{Link2CmdRef|Anker=watchdog|Lang=de|Label=watchdog}}&amp;lt;ref&amp;gt;[[watchdog]] reacts on missing [[Event|events]]&amp;lt;/ref&amp;gt; etc. use either predefined FHEM commands, shell scripts or Perl one liners as arguments. For details and tips for Perl one liners please read the &#039;&#039;Perl specials&#039;&#039; section at the commandref.&lt;br /&gt;
You may use so-called regular expressions (&amp;quot;regex&amp;quot;) to build more complex conditions. These regex can be applied for analysis of events and as well in the execution part of the notify. A short introduction to regex is available e.g. here: https://regex101.com/.&lt;br /&gt;
&lt;br /&gt;
=== Combined time and event control ===&lt;br /&gt;
&lt;br /&gt;
Combined time and event control is possible with [[DOIF/Einsteigerleitfaden,_Grundfunktionen_und_Erläuterungen#Beispiel_C.29:_Kombinierte_Ereignis-_und_Zeitsteuerung|DOIF (time and event control)]], notify and other modules.&lt;br /&gt;
&lt;br /&gt;
The example shows a timespan combined with a readings value. Between 6 am and 7 pm a lamp is switched on, if the measured brightness is lower than 40. If the condition gets false, the lamp is switched off.&lt;br /&gt;
&lt;br /&gt;
DOIF-Solution:&lt;br /&gt;
 define di_lamp DOIF ([06:00-19:00] and [sensor:brightness] &amp;lt; 40) (set lamp on) DOELSE (set lamp off)&lt;br /&gt;
&lt;br /&gt;
==Record and present data==&lt;br /&gt;
[[Datei:SolarthermiePlot.png|350px|thumb|right|Example: plot of a solar heat system]]	&lt;br /&gt;
&lt;br /&gt;
===Record data: Logging===&lt;br /&gt;
To save data/events/messages to a logfile, you have to create one or several {{Link2CmdRef|Anker=FileLog|Lang=en|Label=FileLog}} devices. There&#039;s a helper function called &amp;lt;code&amp;gt;autocreate&amp;lt;/code&amp;gt;. This also adds a logfile to devices automatically recognized and included by the autocreate mechanism. For manually added devices you can use the option {{Link2CmdRef|Anker=createlog|Lang=en|Label=createlog}} which may be used in case you want to add additional logfiles, too. To write just one logfile for several devices to be logged combined, use an appropriate regular expression. &lt;br /&gt;
&lt;br /&gt;
For subsequent graphical presentation of the logged data, FHEMWEB offers the wizard described below.&lt;br /&gt;
&lt;br /&gt;
The size of each logfile will be determined by its wildcard characters (year/month/week/day). Please take a look at the {{Link2CmdRef|Anker=FileLog|Lang=en|Label=FileLog}} definition. You can enable archiving with the &#039;&#039;nrarchive&#039;&#039; or &#039;&#039;archivecmd&#039;&#039; attributes.&lt;br /&gt;
&lt;br /&gt;
Take a look at {{Link2CmdRef|Anker=dblog|Lang=en|Label=dblog}} to use a database instead of a regular file for logging.&lt;br /&gt;
&lt;br /&gt;
===From logged data to diagrams: Plotting===&lt;br /&gt;
&lt;br /&gt;
To build diagrams out of the logged data, just click on &amp;quot;Create SVG instance&amp;quot; in the detail view of each logfile. This will direct you to the &#039;&#039;gplot-Editor&#039;&#039;, a wizard guiding you through a lot of options to fulfill this task.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Gplot-Editor1.png]]&lt;br /&gt;
&lt;br /&gt;
Choose which of your sets of data should be part of your diagram. You may also mix data originating from different sources for your diagrams. Please note: Sometimes it&#039;s necessary to click on {{Taste|write .gplot file }}, especially to get the possibility to switch between different data sources. &lt;br /&gt;
&lt;br /&gt;
There&#039;s also a (German) article [[Plots_erzeugen|Plots erzeugen]] that will direct you to some practical examples. For further information also look at the commandref&#039;s {{Link2CmdRef|Anker=SVG|Lang=en|Label=SVG}} section.&lt;br /&gt;
&lt;br /&gt;
To include data in your diagrams not directly logged from within FHEM, add the &#039;&#039;readonly&#039;&#039; parameter to the FileLog definition. Make sure that there are no other devices named identically and enter something like the following to the command field (usually &#039;&#039;&#039;&#039;&#039;&amp;lt;regexp&amp;gt;&#039;&#039;&#039;&#039;&#039; needs to be identical to the device name, i.e. &#039;&#039;&#039;&#039;&#039;messages&#039;&#039;&#039;&#039;&#039; in this case):&lt;br /&gt;
:&amp;lt;code&amp;gt;define messages FileLog /var/log/messages &amp;lt;regexp&amp;gt; readonly &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Frontends: Adopting the web interface to your needs ==&lt;br /&gt;
So far [[FHEMWEB]] - to be exact FHEMWEB&#039;s default style &amp;quot;f18&amp;quot;  has been used as user interface between you and the FHEM server. &amp;quot;f18&amp;quot; is capable to adopt the web sites to different display sizes for all kind of gadgets like mobile phones, tablets or computers. &lt;br /&gt;
=== Styles ===&lt;br /&gt;
To change FHEMWEB&#039;s look and feel, you may choose other color shemes or styles. You are not limited to just one scheme, but may use different styles or color schemes for different FHEMWEB instanzes&amp;lt;ref&amp;gt;Just use a different port for each of them&amp;lt;/ref&amp;gt;. So you may see at one glance, if you are using a more administrative instance or just a very limited instance with just a few devices to interact&amp;lt;ref&amp;gt;For more info see commandref: {{Link2CmdRef|Anker=FHEMWEB|Lang=en|Label=FHEMWEB}} bzw. {{Link2CmdRef|Anker=allowed|Lang=en|Label=allowed}}&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Rooms and groups===&lt;br /&gt;
It makes sense to group your devices for structured access in FHEMWEB by setting the &#039;&#039;room&#039;&#039; and/or &#039;&#039;group&amp;lt;ref&amp;gt;To sort groups use the &#039;&#039;sortby&#039;&#039; attribute.&amp;lt;/ref&amp;gt; &#039;&#039;attributes, attribute &#039;&#039;defaultRoom&#039;&#039; will mark a starting page. FHEMWEB puts devices without a &#039;&#039;room&#039;&#039; attribute into the &amp;quot;Unsorted&amp;quot; room, new room names will be added to the menu on the left&amp;lt;ref&amp;gt;For even more structuring options in rooms use the delimiter &amp;quot;-&amp;gt;&amp;quot;. This will generate sub-rooms, e.g. &amp;lt;code&amp;gt;attr &amp;lt;device&amp;gt; room MyLogics-&amp;gt;Light&amp;lt;/code&amp;gt;.&amp;lt;/ref&amp;gt; . Devices in the room &amp;quot;hidden&amp;quot; will not be shown by default.&lt;br /&gt;
&lt;br /&gt;
You can also define a stripped down FHEMWEB instance by defining the menu entries to be hidden in the &#039;&#039;hiddenroom&#039;&#039; FHEMWEB attribute.&lt;br /&gt;
&lt;br /&gt;
Edit the colors / fonts by changing the style.css (&amp;quot;Edit files&amp;quot; -&amp;gt; style.css) or create you own style (see stylesheetPrefix), so it won&#039;t be overwritten by the next update command.&lt;br /&gt;
&lt;br /&gt;
===More options on the frontend side===&lt;br /&gt;
FHEMWEB offers a new style, called &#039;&#039;&#039;[https://forum.fhem.de/index.php?topic=82351.0 f18]&#039;&#039;&#039;. This overcomes the need for several FHEMWEB instances for different screen sizes. Give it a try!&lt;br /&gt;
Using a completely different frontend is also possible. Browse the wiki or forum board &#039;&#039;FHEM » Frontends&#039;&#039; to find the solution that fits your needs best!&lt;br /&gt;
&lt;br /&gt;
==Complex structures==&lt;br /&gt;
Put your devices into different rooms. You can use the &amp;lt;code&amp;gt;room=&amp;lt;roomname&amp;gt;&amp;lt;/code&amp;gt; filter to set different devices at once. This is just a simple example: See the {{Link2CmdRef|Anker=devspec|Lang=en|Label=devspec}} section for details.&lt;br /&gt;
For more complex scenarios consider the {{Link2CmdRef|Anker=structure|Lang=en|Label=structure}} module. You can define different structure levels like floors, buildings, etc. and set all elements of a given structure at once.&lt;br /&gt;
&lt;br /&gt;
==Shortlist: commands to learn first==&lt;br /&gt;
*{{Link2CmdRef|Anker=list|Lang=en|Label=list}} - ([[list|Wiki]])&lt;br /&gt;
*{{Link2CmdRef|Anker=define|Lang=en|Label=define}}&lt;br /&gt;
*{{Link2CmdRef|Anker=defmod|Lang=en|Label=defmod}}&lt;br /&gt;
*{{Link2CmdRef|Anker=version|Lang=en|Label=version}} - ([[version|Wiki]])&lt;br /&gt;
*{{Link2CmdRef|Anker=update|Lang=en|Label=update}} - ([[update|Wiki]])&lt;br /&gt;
*{{Link2CmdRef|Anker=shutdown|Lang=en|Label=shutdown}}&lt;br /&gt;
*{{Link2CmdRef|Anker=DOIF|Lang=en|Label=DOIF}} - ([[DOIF|Wiki]])&lt;br /&gt;
*{{Link2CmdRef|Anker=notify|Lang=en|Label=notify}} - ([[notify|Wiki]])&lt;br /&gt;
*{{Link2CmdRef|Anker=at|Lang=en|Label=at}} - ([[at|Wiki]])&lt;br /&gt;
*{{Link2CmdRef|Anker=sleep|Lang=en|Label=sleep}}&lt;br /&gt;
*{{Link2CmdRef|Anker=cancel|Lang=en|Label=cancel}}&lt;br /&gt;
*{{Link2CmdRef|Anker=watchdog|Lang=en|Label=watchdog}} - ([[watchdog|Wiki]])&lt;br /&gt;
&lt;br /&gt;
==FHEM (TM) is a GPL&#039;d perl server...==&lt;br /&gt;
As FHEM is written in perl, most users will be reminded of it&#039;s perl nature at some point in time. Though it may not be mandatory for FHEM users to learn perl, it&#039;s highly recommended to also have a look at this programming language for getting deeper insights in what is going on in your home automation system. As often [[Regulärer Ausdruck|regular expressions (german)]] are used within the perl code, getting familiar with this toolset is also a good idea. To solve some problems you may encounter using perl and regex is the most efficient way to go. &lt;br /&gt;
For first insight see {{Link2CmdRef|Anker=command|Lang=en|Label=FHEM command types}}, {{Link2CmdRef|Anker=perl|Lang=en|Label=Perl specials}} and the article [[99 myUtils anlegen|99 myUtils anlegen (german)]]. Despite beeing marked as outdated, [[DevelopmentIntroduction|this article]] and others in this sections still privide usefull futher info in English to more experienced users and experts.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:FHEM]]&lt;br /&gt;
[[Kategorie:FHEM-Verwendung]]&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Quick-Start&amp;diff=38693</id>
		<title>Quick-Start</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Quick-Start&amp;diff=38693"/>
		<updated>2023-11-09T10:50:22Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: veraltete &amp;quot;source&amp;quot;-Angaben in &amp;quot;syntaxhighlight&amp;quot; geändert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|An english version of this document is available [[Quick-Start/en|here]]}}&lt;br /&gt;
==Installation==&lt;br /&gt;
Zunächst installieren Sie FHEM auf der von Ihnen bevorzugten Hardware (oder virtuellen Maschine). Sie finden dazu Erklärungen für die unterschiedlichsten Betriebssysteme [https://fhem.de/#Installation hier].&lt;br /&gt;
&lt;br /&gt;
{{Randnotiz|RNTyp=b|RNText=Bei einer Standard-Installation unter Linux befinden sich - mit Ausnahme des für den automatischen Start erforderlichen Scripts - alle Dateien, die FHEM für den Betrieb benötigt oder anlegt im Verzeichnis &amp;lt;code&amp;gt;/opt/fhem&amp;lt;/code&amp;gt; sowie den darin befindlichen Unterverzeichnissen. Denken Sie daher rechtzeitig daran, Sicherheitskopien des Verzeichnisses anzufertigen.}}Nach dem ersten Start von FHEM sehen die Einträge im FHEM-Logfile des Log-Verzeichnisses&amp;lt;ref&amp;gt;Dieses befindet sich häufig unter /opt/fhem/log&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Hier wie im Folgenden wird davon ausgegangen, dass Sie FHEM auf einem Server mit einem Linux-Betriebssystem betreiben, sofern nicht ausdrücklich etwas anderes angegeben ist&amp;lt;/ref&amp;gt; zum Beispiel wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
2018.03.09 09:17:51 1: Including fhem.cfg&lt;br /&gt;
2018.03.09 09:17:51 3: telnetPort: port 7072 opened&lt;br /&gt;
2018.03.09 09:17:51 3: WEB: port 8083 opened&lt;br /&gt;
2018.03.09 09:17:51 3: WEBphone: port 8084 opened&lt;br /&gt;
2018.03.09 09:17:51 3: WEBtablet: port 8085 opened&lt;br /&gt;
2018.03.09 09:17:51 2: eventTypes: loaded 0 events from ./log/eventTypes.txt&lt;br /&gt;
2018.03.09 09:17:51 1: usb create starting&lt;br /&gt;
2018.03.09 09:17:51 3: [...]&lt;br /&gt;
2018.03.09 09:17:51 1: usb create end&lt;br /&gt;
2018.03.09 09:17:51 0: Featurelevel: 5.8&lt;br /&gt;
2018.03.09 09:17:51 0: Server started with 9 defined entities (fhem.pl:16349/2018-03-07 perl:5.024001 os:linux user:fhem pid:9341)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Erster Aufruf von FHEM==&lt;br /&gt;
Beim ersten Start ist FHEM über ein Webinterface ({{Link2CmdRef|Anker=FHEMWEB|Lang=de|Label=FHEMWEB}}) erreichbar. Die URL hierfür lautet &#039;&#039;&#039;http://&amp;lt;fhem-server&amp;gt;:8083/fhem&#039;&#039;&#039;. &lt;br /&gt;
{{Hinweis|Für spezielle Zwecke oder Nutzergruppen können weitere FHEMWEB-Geräte definiert werden. Dies bietet sich an, wenn man einen anderen Style als den Standard-Style f18 zusammen mit kleineren Bildschirmgrößen verwendet oder Zugänge für bestimmte Nutzergruppen mit reduziertem Funktionsumfang bereitstellen will. Daneben kann man eine [[Telnet|telnet]]-Schnittstelle&amp;lt;ref&amp;gt;Da diese das System nur gering belastet, kann darüber FHEM auch noch in Situationen erreicht und gesteuert werden, in denen FHEMWEB nicht mehr funktioniert.&amp;lt;/ref&amp;gt; definieren.}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
datei:ErsteSchritteInFhem01.png|Die Startseite direkt nach der Installation auf einem Desktop&lt;br /&gt;
datei:erster_aufruf_smartphone.png|Der erste Aufruf von FHEM auf einem Smartphone&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Das Web-Interface kurz erklärt:&lt;br /&gt;
*Am oberen Bildschirmrand befindet sich ein Kommandofeld. In diesem können Befehle eingegeben werden, die FHEM nach Eingabe der {{Taste|Enter}}-Taste ausführt&lt;br /&gt;
*Links daneben befindet sich ein Symbol (+), über das Sie ein Eingabefeld für den [[Import von Code Snippets|Import von RAW-Code]] erreichen können&lt;br /&gt;
*Mit dem ersten Menüpunkt links - &#039;&#039;Save config&#039;&#039; - können Änderungen gespeichert werden. Erst dann werden werden diese in die Konfigurationsdatei geschrieben und sind somit auch noch nach einem Neustart von FHEM vorhanden. Ungespeicherte Änderungen signalisiert FHEM durch ein &#039;&#039;?&#039;&#039; neben dem Menüpunkt&lt;br /&gt;
*Im nächsten Abschnitt links werden alle vorhandenen Räume aufgelistet. Zu Beginn sind das nur die Räume &#039;&#039;Unsorted&#039;&#039; und &#039;&#039;Everything&#039;&#039;. Weitere Räume können natürlich später angelegt werden&lt;br /&gt;
*Im - vorläufig - letzten Abschnitt auf der linken Seite sind einige nützliche Links untergebracht&lt;br /&gt;
&lt;br /&gt;
==Absicherung der FHEM-Serverkomponente==&lt;br /&gt;
In der Grundkonfiguration kann jeder, der sich in dem selben Netzwerk wie der FHEM-Server befindet, unverschlüsselt und ohne der Eingabe von Benutzerdaten auf FHEM zugreifen. FHEM weist mit einer Sicherheitswarnung auf diesen Umstand hin.&lt;br /&gt;
Um die Installation abzusichern, bieten sich mehrere empfohlene Optionen an.&lt;br /&gt;
&lt;br /&gt;
===allowed und SSL===&lt;br /&gt;
Mit diesen Einstellungen können beide Konfigurations-Möglichkeiten in FHEM (telnet und Webinterface) mit einem Passwort und einer Transport-Verschlüsselung (HTTPS/SSL) abgesichert werden.&lt;br /&gt;
&lt;br /&gt;
{{Randnotiz|RNTyp=b|RNText=Sie erhalten für alle FHEM-Befehle die jeweilige Syntax und weitere Informationen, wenn Sie &amp;lt;code&amp;gt;help &amp;lt;Befehl&amp;gt;&amp;lt;/code&amp;gt; in der Kommandozeile eingeben.}}&lt;br /&gt;
Dazu müssen zunächst ein oder mehrere &#039;&#039;allowed&#039;&#039;-&#039;&#039;&#039;[[Gerät|Geräte]]&#039;&#039;&#039;&amp;lt;ref&amp;gt;Geräte werden in FHEM oft als &amp;quot;&#039;&#039;&#039;Device&#039;&#039;&#039;&amp;quot; bezeichnet. Allerdings wird der Begriff &amp;quot;[[Device]]&amp;quot; oder &amp;quot;[[Gerät]]&amp;quot; im FHEM-Kontext etwas weiter verstanden. Dies kann, muß aber nicht zwingend ein physisches Gerät sein. Als &amp;quot;Device&amp;quot; wird schlicht alles bezeichnet, für das eine &amp;quot;define ...&amp;quot;-Anweisung existiert bzw. eingegeben wurde/wird/werden kann.&amp;lt;/ref&amp;gt; definiert werden. Die Anleitung dazu findet sich in der {{Link2CmdRef|Anker=allowed|Lang=de|Label=CommandRef}} oder indem in der FHEM-Kommandozeile der Web-Schnittstelle &amp;lt;code&amp;gt;help allowed&amp;lt;/code&amp;gt; eingeben wird.&lt;br /&gt;
&lt;br /&gt;
Ist keine allowed-Instanz definiert, sind Zugriffe auf FHEM nur innerhalb desselben Netzwerks möglich.&lt;br /&gt;
{{Randnotiz|RNTyp=b|RNText=Hier wie im Folgenden und in vielen Beispielen, die in der Dokumentation zu finden sind, findet sich die Schreibweise &amp;lt;code&amp;gt;&amp;lt;Befehl&amp;gt; &amp;lt;Parameter&amp;gt;&amp;lt;/code&amp;gt;. Dies ist so zu verstehen, dass die Angaben in der Klammer jeweils einschließlich der &amp;lt;&amp;gt;-Zeichen durch eine sinnvolle eigene Angabe zu ersetzen sind.}}&lt;br /&gt;
&lt;br /&gt;
Zusätzlich kann für [[FHEMWEB]] mithilfe des [[Attribut|Attributes]] {{Link2CmdRef|Anker=HTTPS|Lang=de|Label=HTTPS}} eine HTTPS-Verbindung aktiviert werden. Für telnet (welches mehr oder weniger ein TCP/IP Port ist) wird das [[Attribut]]&amp;lt;ref&amp;gt;Weitere Informationen zu den hier verwendeten FHEM-spezifischen Begriffen finden Sie im [[:Kategorie:Glossary|Glossar]]&amp;lt;/ref&amp;gt; {{Link2CmdRef|Anker=SSL|Lang=de|Label=SSL}} verwendet. &lt;br /&gt;
&lt;br /&gt;
Standardmäßig ist keine dieser Einstellungen gesetzt. Um die deshalb erscheinenden Sicherheitswarnungen zu deaktivieren, kann das globale Attribut {{Link2CmdRef|Anker=motd|Lang=de|Label=motd}} verwendet werden.&lt;br /&gt;
&lt;br /&gt;
===FHEM und das Internet===&lt;br /&gt;
Sofern FHEM nicht nur aus dem lokalen Netz erreichbar sein soll, sollten zusätzliche Sicherheitsmaßnahmen ergriffen werden. Mögliche Optionen dafür sind die Verwendung eines VPNs (Virtual Private Network) und/oder eines Reverse-Proxy-Servers mit z.B. [[Apache_Authentication_Proxy|Apache]] oder [[HTTPS-Absicherung_%26_Authentifizierung_via_nginx_Webserver|nginx]].&lt;br /&gt;
&lt;br /&gt;
===Weitere Sicherheitshinweise===&lt;br /&gt;
Beachten Sie, dass nicht nur die Software auf Ihrem Server stets aktuell gehalten werden muss, sondern auch die von Ihnen verwendeten Komponenten maßgeblich dazu beitragen, wie sicher Ihre Hausautomatisierung insgesamt ist.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Schnittstellen zur realen Welt==&lt;br /&gt;
{{Randnotiz|RNTyp=b|RNText=Sofern Sie an dieser Stelle keine konkreten Geräte haben, die Sie in Ihr FHEM einbinden wollen, können Sie mit Hilfe der [[Erste Schritte in FHEM|ersten Schritte in FHEM]] einen Eindruck gewinnen, wie Geräte in FHEM eingerichtet werden.}}Um Informationen über Ereignisse oder Zustände in der realen Welt zu erhalten, muss FHEM mit der Außenwelt verbunden werden. &lt;br /&gt;
&lt;br /&gt;
Dies geschieht in vielen FHEM-Installationen durch die Verwendung eines oder mehrerer USB-Geräte (z.B. [[CUL]], [[FHZ nn00|FHZ1x00]], TCM, ZWave, etc.) welche mit dem FHEM-Server verbunden sind. Dazu werden die Perl &#039;&#039;serial&#039;&#039;-Module&amp;lt;ref&amp;gt;Wenn das &#039;&#039;serial&#039;&#039;-Modul benötigt wird, kann es mit dem Kommando &amp;lt;code&amp;gt;sudo cpan Device::SerialPort &amp;lt;/code&amp;gt; nachträglich installiert werden. Es gibt aber auch schon bereits vorkompilierte Debian-Pakete (&#039;&#039;libdevice-serialport-perl&#039;&#039;). In OSX 10.5 ist das Paket ebenfalls bereits enthalten. Kann das Paket nicht installiert werden, bietet sich die &#039;&#039;@directio&#039;&#039;-Option in der commandref als mögliche Informationsquelle an.&amp;lt;/ref&amp;gt; benötigt. Im commandref-Abschnitt zum jeweiligen USB-Gerät ist ersichtlich, welche Module genau benötigt werden. &amp;lt;ref&amp;gt;Das gilt entsprechend, wenn Geräte über die serielle Schnittstellen eingebunden werden sollen, die an den GPIO-Schnittstellen eines Raspberry Pi verfügbar sind.&amp;lt;/ref&amp;gt; Sie benötigen dieses Modul nicht, wenn das Gerät über Ethernet angeschlossen wird (z.B. [[HMLAN|HM-LAN]] oder [[CUNO]]). &lt;br /&gt;
&lt;br /&gt;
===Automatische Konfiguration===&lt;br /&gt;
In der Standard-Konfiguration sucht FHEM beim Start automatisch nach USB-Geräten wie z.B. FHZ, [[CUL]]&amp;lt;ref&amp;gt;Unter einem Linux-Betriebssystem wird FHEM gegebenenfalls versuchen, einen bereits angesteckten aber noch unprogrammierten [[CUL]] zu programmieren. Details dazu entnehmen Sie bitte den Beschreibungen der Befehle usb und CUL flash in der commandref.&amp;lt;/ref&amp;gt; &lt;br /&gt;
, [[COC]], ZWave oder TCM und erstellt die entsprechenden Einträge in seiner Konfigurationsdatei. Wird ein Gerät im laufenden FHEM-Betrieb angeschlossen, muss FHEM durch die Eingabe von &amp;lt;code&amp;gt;shutdown restart&amp;lt;/code&amp;gt; in der Befehlszeile neu gestartet werden, bevor das Gerät verwendet werden kann.&lt;br /&gt;
&lt;br /&gt;
Für automatisch eingebundene Geräte müssen in der Regel noch weitere Einstellungen vorgenommen werden. Dies erfolgt durch das Setzen entsprechender Attribute. Die verfügbaren Attribute sowie teilweise auch konkret einstellbare Werte für die Attribute können aufgerufen werden, indem auf auf das entsprechende Gerät im jeweiligen Raum geklickt wird. Neu angelegte Geräte werden im Raum &#039;&#039;Unsorted&#039;&#039; angezeigt. &lt;br /&gt;
&lt;br /&gt;
Sobald die automatische Konfiguration aller zu verwendenden USB-Geräte abgeschlossen ist, sollte die automatische Erkennung durch Eingabe von &amp;lt;code&amp;gt;attr initialUsbCheck disable 1&amp;lt;/code&amp;gt; in der Befehlszeile deaktiviert werden.&lt;br /&gt;
	&lt;br /&gt;
===Manuelle Konfiguration===&lt;br /&gt;
{{Randnotiz|RNTyp=g|RNText=In der Commandref findet sich in der Regel eine Darstellung in der folgenden Form: &amp;lt;code&amp;gt;define &amp;lt;name&amp;gt; CUL &amp;lt;device&amp;gt; &amp;lt;FHTID&amp;gt;&amp;lt;/code&amp;gt;. Dabei sind alle Angaben mit Klammern dazu gedacht, durch eigene Werte (ohne Klammern) ersetzt zu werden.}}&lt;br /&gt;
Um Geräte mit USB-Anschluss manuell zu definieren (oder falls FHEM diese nicht automatisch erkennt), kann - nach Anschluss des Gerätes - im Verzeichnis /dev nach der dort entsprechend eingetragenen Gerätebezeichnung gesucht werden. Für einen [[CUL]] zum Beispiel wird unter einem Linux-Betriebssystem eine Datei mit der Bezeichnung &#039;&#039;/dev/ttyACM*&#039;&#039; angelegt. Auf OS X &#039;&#039;/dev/cu.usbmodem*&#039;&#039;. Mit dieser Gerätebezeichnung (also des Dateinamens) kann das Gerät manuell in der Befehlszeile angelegt werden.&lt;br /&gt;
&lt;br /&gt;
*Am Beispiel eines CUL-Sticks: &amp;lt;code&amp;gt;define CUL1 CUL /dev/ttyACM0@9600 1234&amp;lt;/code&amp;gt;&amp;lt;ref&amp;gt;Auch hier ist die Angabe &amp;quot;1234&amp;quot; lediglich beispielhaft und durch einen eigenen Parameter zu ersetzen&amp;lt;/ref&amp;gt;&lt;br /&gt;
*Oder eines Z-Wave-Controllers: &amp;lt;code&amp;gt;define ZWDongle ZWDongle /dev/serial/by-id/usb-0658_0200-if00@115200&amp;lt;/code&amp;gt;&amp;lt;ref&amp;gt;Die für diese Art der Einbindung erforderlichen Informationen erhalten Sie, indem Sie auf Betriebssystemebene &amp;lt;code&amp;gt;ls -l /dev/serial/by-id&amp;lt;/code&amp;gt; eingeben&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Informationen, wie genau das jeweilige Gerät angelernt wird, finden sich im zugehörigen Abschnitt der {{Link2CmdRef|Lang=de|Label=commandref}}&lt;br /&gt;
&lt;br /&gt;
==Einbinden und Konfiguration von Sensoren und Aktoren==&lt;br /&gt;
&lt;br /&gt;
===autocreate===&lt;br /&gt;
Viele funkgesteuerte [[Gerät|Geräte]] werden in der default-Konfiguration wegen der voreingestellten {{Link2CmdRef|Anker=autocreate|Lang=de|Label=autocreate}}-Funktion automatisch erstellt, sobald diese Werte senden.&lt;br /&gt;
&lt;br /&gt;
Diese Funktion erzeugt automatisch beim Empfang einer Nachricht von einem Geräten (z.B. eines Sensors wie dem S300 oder FHT) ein neues [[Device]] in FHEM. Bitte warten Sie eine gewisse Zeit, beobachten Sie die Logeinträge oder den [[Event monitor|Eventmonitor]] und aktualisieren Sie Ihren Browser um neu erstellte [[Gerät|Geräte]] angezeigt zu bekommen. Die automatisch vergebenen Namen orientieren sich dabei an technischen Parametern.&lt;br /&gt;
&lt;br /&gt;
===Umbenennen===&lt;br /&gt;
{{Randnotiz|RNTyp=g|RNText=Wenn Sie das Gerät selbst umbenennen, werden auch die zugehörigen Logfiles und Weblinks automatisch mit umbenannt. Wenn Sie dagegen die Weblinks oder Logfiles umbenennen, werden die zugehörigen Geräte nicht mit umbenannt.}}Um automatisch erstellte Geräteeinträge umzubenennen, kann der Befehl {{Link2CmdRef|Anker=rename|Lang=de|Label=rename}} verwendet werden. Geben Sie den Befehl mit den entsprechenden Parametern in der Befehlszeile der Webseite ein. Z.B.:&lt;br /&gt;
&lt;br /&gt;
    rename FHT_1234 fht.kitchen &lt;br /&gt;
&lt;br /&gt;
===Manuelles Anlegen===&lt;br /&gt;
Wenn Sie das [[Gerät]] manuell anlegen wollen oder müssen, weil autocreate diese nicht anlegen kann, dann gehen Sie folgendermaßen vor:&lt;br /&gt;
&lt;br /&gt;
Warten Sie eine Weile bis Daten übertragen werden. Im Logfile (zu erreichen unter Webseite Menüpunkt Unsorted-&amp;gt; [[FileLog]] -&amp;gt; Logfile -&amp;gt; text) erscheint z.B. folgende Textzeile:&lt;br /&gt;
    FS20 Unknown device &amp;lt;HOUSECODE&amp;gt;, Button &amp;lt;BTN&amp;gt; Code &amp;lt;CDE&amp;gt;, please define it  &lt;br /&gt;
&lt;br /&gt;
Definieren Sie dieses neue Gerät mittels folgendem Eintrag:&lt;br /&gt;
    define piri1 FS20 &amp;lt;HOUSECODE&amp;gt; &amp;lt;BTN&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
Setzen sie das model-Attribut des Gerätes:&lt;br /&gt;
    attr piri1 model fs20piri  &lt;br /&gt;
&lt;br /&gt;
Anschließend erhalten Sie nur noch die für dieses Gerät verfügbaren Attribute angezeigt. Hier sehen Sie eine komplette Liste der [[FS20]] Modelle.&lt;br /&gt;
Bei einem anderen neuen Gerät sollte eine ähnliche Nachricht im Logfile erscheinen.&lt;br /&gt;
&lt;br /&gt;
Um [[HomeMatic]]- oder zWave-Geräte anzulernen, muss FHEM zuerst mit dem Befehl &amp;lt;code&amp;gt;set CUL hmPairForSec 600&amp;lt;/code&amp;gt; in Empfangsbereitschaft versetzt werden und anschließend der Anlernknopf auf dem Gerät gedrückt werden.&lt;br /&gt;
&lt;br /&gt;
===Einbinden von Geräten, die Anlernbefehle benötigen===&lt;br /&gt;
&lt;br /&gt;
Manche Geräte benötigen Anlernsignale, um eine Koppelung mit anderen Geräten bzw. einer Zentrale wie FHEM herzustellen. Für solche Geräte muss zunächst manuell eine Konfiguration in FHEM vorgenommen werden, um solche Anlernsignale generieren zu können.&lt;br /&gt;
&lt;br /&gt;
Definieren Sie z.B. ein [[FS20]] Gerät mit z.B. folgendem Befehl in der Befehlszeile:&lt;br /&gt;
&lt;br /&gt;
    define lamp1 FS20 1234 56&lt;br /&gt;
&lt;br /&gt;
Dann drücken Sie den Anmeldeknopf an dem Gerät solange, bis die LED blinkt. Anschließend klicken sie auf den &#039;&#039;on&#039;&#039; Link auf der FHEM Webseite um das Einschalt-Kommando zu senden. Die LED sollte aufhören zu blinken. Das Gerät ist nun auf den Hauscode 1234 Gerätecode 56 programmiert. Sie können alternativ die 4-base ELV-Notation benutzen. Anschließend können Sie wieder modellspezifische [[Attribut|Attribute]] für das [[Gerät]] setzen. Z.B.:&lt;br /&gt;
&lt;br /&gt;
    attr lamp1 model fs20st&lt;br /&gt;
&lt;br /&gt;
Mit diesem Eintrag bekommen Sie nunmehr wieder nur die für dieses [[Gerät]] relevanten Kommandos angezeigt.&lt;br /&gt;
&lt;br /&gt;
{{Randnotiz|RNTyp=b|RNText=Das automatische oder manuelle Eintragen von FHT/HomeMatic/EnOcean-Geräten in FHEM bedeutet nicht automatisch, dass das betreffende Gerät mit FHEM gepairt ist bzw. das pairing erfolgreich abgeschlossen wurde!}}Andere Systeme (EnOcean/HomeMatic/ZWave) brauchen eine umfangreichere Prozedur und das entsprechende Gerät muss zuerst in den pairing mode versetzt werden. Bitte sehen Sie sich den entsprechenden Eintrag auf der commandref.html-Seite für Ihr [[Gerät]] zur Information an.&lt;br /&gt;
&lt;br /&gt;
==Grundlegendes zum Steuern Ihrer Geräte==&lt;br /&gt;
Sobald Sensoren und Aktoren in FHEM eingebunden sind, können diese bereits über telnet oder die WEB-Schnittstelle gesteuert werden. &lt;br /&gt;
{{Randnotiz|RNTyp=b|RNText=Für Einsteiger empfiehlt sich die Lektüre der [[http://fhem.de/Heimautomatisierung-mit-fhem.pdf! Einführung in die Automatisierung mit FHEM]]. Zwar sind dort Neuerungen wie der Style [[FHEMWEB|f18]], [[set magic]], Module wie [[allowed]] oder [[DOIF]] nicht behandelt und die Auswahl an verfügbaren Hardwaresystemen hat sich seit dessen letzter Aktualisierung weiter erhöht. Dennoch bietet diese Einführung nach wie vor einen recht umfassenden Überblick in die allgemeinen Vorgehensweisen und Möglichkeiten mit FHEM.}}&lt;br /&gt;
Für den Aufbau einer zeit- und ereignisorientierten Steuerung werden jedoch weitere Steuerungselemente - sogenannte &amp;quot;&#039;&#039;&#039;[[Modul|Module]]&#039;&#039;&#039;&amp;quot; - benötigt. Nachfolgend sollen kurz einige der wichtigsten Module vorgestellt werden.&lt;br /&gt;
&lt;br /&gt;
Unter &#039;&#039;&#039;[[Automatisierung]]&#039;&#039;&#039; stehen weitere Informationen zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
===Zeitabhängige Kommandos===&lt;br /&gt;
Zur Zeitsteuerung benötigt man einen [[Timehandler]].&lt;br /&gt;
&lt;br /&gt;
===Reaktion auf Ereignisse===&lt;br /&gt;
[[Gerät|Geräte]] teilen bestimmte Aktualisierungen ihres Zustandes über [[Event|Events]] mit, z.B. die Änderung eines Messwertes oder eines Schaltzustandes. Die Events werden von [[Eventhandler|Eventhandlern]] empfangen und verarbeitet. Als Ergebnis der Verarbeitung werden Befehle ausgeführt.  &lt;br /&gt;
&lt;br /&gt;
Die einfachste Form eines [[Eventhandler|Eventhandlers]] ist ein {{Link2CmdRef|Anker=notify|Lang=de|Label=notify}} oder {{Link2CmdRef|Anker=DOIF|Lang=de|Label=DOIF}}.&lt;br /&gt;
&lt;br /&gt;
Die in FHEM auftretenden Ereignisse können mit dem [[Event monitor|Eventmonitor]] angezeigt werden oder in einem mit FHEM verbundenen [[Telnet]]-Client durch den Befehl &amp;lt;code&amp;gt;inform timer&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Die angezeigten [[Event|Events]] sind die wichtigste Grundlage, um einen Ereignisfilter, Suchmuster oder Auslöser zu formulieren.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das [[Event]] wird auf die nachstehende Weise dargestellt:&lt;br /&gt;
&lt;br /&gt;
    2011-12-16 21:51:55 FS20 myPiri on-for-timer 120 &lt;br /&gt;
&lt;br /&gt;
Gemäß dieser Eventzeile können Sie eine Aktion wie folgt definieren:&lt;br /&gt;
&lt;br /&gt;
    define lampNotify notify myPiri set myLamp on &lt;br /&gt;
	&lt;br /&gt;
oder&lt;br /&gt;
&lt;br /&gt;
    define lampNotify notify myPiri:on.* set myLamp on &lt;br /&gt;
&lt;br /&gt;
Um dieses [[notify]] zu testen können Sie die Ereignisse unter Verwendung des Befehls [[trigger]]&amp;lt;ref&amp;gt;{{Link2CmdRef|Anker=trigger|Lang=de}}&amp;lt;/ref&amp;gt; simulieren. Z.B.:&lt;br /&gt;
&lt;br /&gt;
    trigger myPiri on-for-timer 120 &lt;br /&gt;
     &lt;br /&gt;
[[at]], [[notify]] und andere [[Eventhandler]], wie z.B. {{Link2CmdRef|Anker=DOIF|Lang=de|Label=DOIF}}&amp;lt;ref&amp;gt;[[DOIF]] vereint Ereignissteuerung, Zeitsteuerung, Zustandsautomaten und Frontend in einem Modul&amp;lt;/ref&amp;gt;, {{Link2CmdRef|Anker=sequence|Lang=de|Label=sequence}}&amp;lt;ref&amp;gt;[[sequence]] verknüpft eine Folge von [[Ereignis|Ereignissen]]&amp;lt;/ref&amp;gt;, {{Link2CmdRef|Anker=watchdog|Lang=de|Label=watchdog}}&amp;lt;ref&amp;gt;[[watchdog]] reagiert auf ausbleibende [[Ereignis|Ereignisse]]&amp;lt;/ref&amp;gt; usw. verwenden entweder vordefinierte FHEM-Kommandos, SHELL-Scripte oder Perl-Ausdrücke als Argumente. Für Details und Tipps zu Perl-Ausdrücken lesen Sie bitte den Abschnitt zu {{Link2CmdRef|Anker=perl|Lang=de|Label=Perl Besonderheiten}} in der commandref.&lt;br /&gt;
Sowohl bei der Auswertung von [[Ereignis|Ereignissen]], als auch bei den FHEM-Kommandos können Sie [[Regulärer_Ausdruck|reguläre Ausdrücke]] verwenden, sogenannte regex. Eine kurze Einführung zu regex finden Sie z.B. hier: https://regex101.com/.&lt;br /&gt;
&lt;br /&gt;
=== Kombinierte Zeit- und Ereignissteuerung ===&lt;br /&gt;
&lt;br /&gt;
Auch eine kombinierte Zeit- und Ereignissteuerung ist mit [[Timehandler|Timehandlern]] und [[Eventhandler|Eventhandlern]] möglich.&lt;br /&gt;
&lt;br /&gt;
==== [[DOIF]]: Kombination einer Zeitspanne mit der Abfrage eines Readings ====&lt;br /&gt;
&lt;br /&gt;
Zwischen 6 Uhr und 19 Uhr soll eine Lampe eingeschaltet werden, wenn die Helligkeit unter 40 gemessen wird. Sonst, wenn die Bedingung nicht zutrifft, soll die Lampe ausgeschaltet werden.&lt;br /&gt;
Liegt die Helligkeit zum Beginn der Zeitspanne (6 Uhr) bereits unter 40, soll die Lampe zu diesem Zeitpunkt eingeschaltet werden.&lt;br /&gt;
Liegt die Helligkeit zum Ende der Zeitspanne (19 Uhr) noch unter 40, soll die Lampe zu diesem Zeitpunkt ausgeschaltet werden.&lt;br /&gt;
&lt;br /&gt;
Im [[Event monitor]] erscheint folgendes [[Event]], der hervorgehobene Teil des [[Event|Events]] löst die Bedingungsprüfung in [[DOIF]] aus.&lt;br /&gt;
 2018-08-07 15:46:33.887 CUL_HM &#039;&#039;&#039;sensor brightness&#039;&#039;&#039;: 39.41&lt;br /&gt;
Im DOIF wird der [[DOIF/Einsteigerleitfaden,_Grundfunktionen_und_Erl%C3%A4uterungen#Ausl.C3.B6ser|Auslöser]] immer in eckigen Klammern angegeben, wie hier die Zeitspanne und das [[Ereignis]]; in der Definition fett hervorgehoben. Der [[DOIF/Einsteigerleitfaden,_Grundfunktionen_und_Erl%C3%A4uterungen#Ausl.C3.B6ser|Auslöser]] für das [[Ereignis]] kann über die Kombination von [[Gerätename]] (sensor) und [[Gerätevariable]] (brightness) angegeben werden, dabei wird der Wert des [[Readings]] zurückgegeben, vergleichbar mit [[set magic]]. Die Verknüpfung von Zeitspanne und Readingsvergleich erfolgt über einen logischen Operator, dem Perl-Operator &amp;lt;code&amp;gt;and&amp;lt;/code&amp;gt;. Der Wert des Readings wird mit einem Vergleichswert (40) über einen vergleichenden Operator verglichen, dem Perl-Operator &amp;lt;code&amp;gt;&amp;lt;&amp;lt;/code&amp;gt; mit der Bedeutung &#039;&#039;kleiner als&#039;&#039;.&lt;br /&gt;
 define di_lamp DOIF (&#039;&#039;&#039;[06:00-19:00]&#039;&#039;&#039; and &#039;&#039;&#039;[sensor:brightness]&#039;&#039;&#039; &amp;lt; 40) (set lamp on) DOELSE (set lamp off)&lt;br /&gt;
&lt;br /&gt;
Das [[DOIF]] kann mit dem FHEM-Befehl setreading&amp;lt;ref&amp;gt;{{Link2CmdRef|Anker=setreading|Lang=de}}&amp;lt;/ref&amp;gt; getestet werden.&lt;br /&gt;
  setreading sensor brightness 39&lt;br /&gt;
Lässt das [[DOIF]] innerhalb der Zeitspanne die Lampe einschalten.&lt;br /&gt;
  setreading sensor brightness 40&lt;br /&gt;
Lässt das [[DOIF]] innerhalb der Zeitspanne die Lampe ausschalten.&lt;br /&gt;
&lt;br /&gt;
==Daten aufzeichnen und darstellen==&lt;br /&gt;
[[Datei:SolarthermiePlot.png|350px|thumb|right|Beispiel für Solarthermie]]	&lt;br /&gt;
&lt;br /&gt;
===Daten aufzeichnen: Loggen===&lt;br /&gt;
Um Daten/Nachrichten/Ereignisse für eine spätere Analyse oder grafische Darstellung aufzuzeichnen, können Sie ein oder mehrere Device/s vom Typ {{Link2CmdRef|Anker=FileLog|Lang=de|Label=FileLog}} anlegen. Die Funktion &amp;lt;code&amp;gt;autocreate&amp;lt;/code&amp;gt; erstellt für neu erkannte [[Gerät|Geräte]] automatisch jeweils eine Logdatei. Sie können jedoch die Funktion {{Link2CmdRef|Anker=createlog|Lang=de|Label=createlog}} nutzen, um später eine weitere Logdatei hinzuzufügen. Wenn Sie die Daten von mehreren Geräten in einem [[FileLog]] zusammenfassen wollen, passen Sie den regulären Ausdruck (regex) entsprechend an.&lt;br /&gt;
&lt;br /&gt;
[[FHEMWEB]] hat eine vordefinierte Funktionen zur Erstellung von Grafiken aus den aufgezeichneten Daten, näheres dazu im folgenden Abschnitt.&lt;br /&gt;
&lt;br /&gt;
Bei [[FileLog]] können Sie die Aufzeichnungsdauer sowie Archivierungsfunktionen selbst bestimmen. Setzen Sie dazu entsprechende Logkriterien (z.B. Jahr/Monat/Woche/Tag) bzw. die Attribute &#039;&#039;nrarchive&#039;&#039; und/oder &#039;&#039;archivecmd&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie statt [[FileLog]] lieber eine Datenbank nutzen wollen, können Sie {{Link2CmdRef|Anker=dblog|Lang=de|Label=dblog}} verwenden.&lt;br /&gt;
&lt;br /&gt;
===Grafische Aufarbeitung aufgezeichneter Daten: plotten===&lt;br /&gt;
&lt;br /&gt;
Um die aufgezeichneten Daten grafisch darzustellen, kann man in die Detailansicht eines FileLogs wechseln und dort auf &amp;quot;Create SVG instance&amp;quot; klicken. Damit gelangen Sie zum gplot-Editor.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Gplot-Editor1.png]]&lt;br /&gt;
&lt;br /&gt;
In diesem können Sie nun alle Daten wählen, die grafisch dargestellt werden sollen und dabei auch Daten aus unterschiedlichen Quellen gemeinsam darstellen. Beachten Sie, dass Sie dazu ggf. Zwischenstände durch Drücken der Taste {{Taste|write .gplot file }} speichern müssen, um Daten aus anderen als der zuletzt genutzten Quelle auswählen zu können. &lt;br /&gt;
&lt;br /&gt;
Im Beitrag [[Plots_erzeugen|Plots erzeugen]] sowie im Abschnitt {{Link2CmdRef|Anker=SVG|Lang=de|Label=SVG}} der commandref erhalten Sie hierzu weitere Informationen.&lt;br /&gt;
&lt;br /&gt;
Um fremde (nicht unter FHEM erfasste) Daten als Plot oder als normalen Text anzuzeigen, spezifizieren Sie bitte den &#039;&#039;readonly&#039;&#039; Parameter bei der Definition des FileLog zusätzlich zu dem korrekten Dateinamen; der &amp;lt;regexp&amp;gt; Parameter sollte identisch dem Devicenamen sein (im folgenden Beispiel also &#039;&#039;&#039;&#039;&#039;messages&#039;&#039;&#039;&#039;&#039;):&lt;br /&gt;
:&amp;lt;code&amp;gt;define messages FileLog /var/log/messages &amp;lt;regexp&amp;gt; readonly &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Das Web-Interface anpassen==&lt;br /&gt;
In der Darstellung bis hier war [[FHEMWEB]] für das Erscheinungsbild von FHEM im Browser verantwortlich, wobei der voreingestellte Style &amp;quot;f18&amp;quot; für eine dynamische Darstellung für verschiedene Bildschirmgeräte und -größen sorgt. &lt;br /&gt;
=== Styles ===&lt;br /&gt;
Sie können das Erscheinungsbild von FHEMWEB ändern, indem Sie andere Farbschemata oder andere Styles festlegen. Dabei können Sie für verschiedene Instanzen&amp;lt;ref&amp;gt;Dabei ist jeweils nur die Verwendung eines anderen Ports erforderlich&amp;lt;/ref&amp;gt; auch unterschiedliche Styes verwenden und so z.B. das Aussehen/und oder die Funktionalität von FHEM verändern, je nachdem, ob FHEM zu Administrationszwecken&amp;lt;ref&amp;gt;In FHEMWEB-Instanzen, in denen code eingegeben werden soll, kann zur Unterstützung [[codemirror]] aktiviert werden.&amp;lt;/ref&amp;gt; oder in der regulären Anwendung aufgerufen wird&amp;lt;ref&amp;gt;Weitere Hinweise hierzu finden Sie in der commandref zu {{Link2CmdRef|Anker=FHEMWEB|Lang=de|Label=FHEMWEB}} bzw. {{Link2CmdRef|Anker=allowed|Lang=de|Label=allowed}}&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Räume und Gruppen===&lt;br /&gt;
Um die Geräte zu ordnen, bietet FHEMWEB eine Reihe von Möglichkeiten an. Es ist in der Regel zu empfehlen, alle Geräte in Räumen&amp;lt;ref&amp;gt;Um gegliederte Räume zu erzeugen, nutzen Sie den Trenner &amp;quot;-&amp;gt;&amp;quot;. Beispiel: &amp;lt;code&amp;gt;attr &amp;lt;device&amp;gt; room Steuerung-&amp;gt;Logik&amp;lt;/code&amp;gt;.&amp;lt;/ref&amp;gt; zu gruppieren und auch innerhalb der Räume sinnvoll anzuordnen, indem Sie das &#039;&#039;group&#039;&#039;-Attribut setzen&amp;lt;ref&amp;gt;Für die Sortierung innerhalb einer Gruppe kann das Attribut &#039;&#039;sortby&#039;&#039; genutzt werden.&amp;lt;/ref&amp;gt;, mit &#039;&#039;defaultRoom&#039;&#039; läßt sich eine Startseite festlegen. FHEMWEB zeigt Geräte ohne Raum-Attribut im Raum (Menüpunkt) &#039;&#039;Unsorted&#039;&#039;. Fügen Sie Geräten das &#039;&#039;hidden&#039;&#039;-Raumattribut hinzu, so werden diese Geräte nicht auf der Webseite angezeigt. &lt;br /&gt;
&lt;br /&gt;
Sie können ein kürzeres Menü auf der Webseite erzeugen, indem Sie Menüpunkte (bzw. Räume), die nicht angezeigt werden sollen mit dem Attribut &#039;&#039;hiddenroom&#039;&#039; versehen&amp;lt;ref&amp;gt;Darüber lassen sich auch die Anzeige von links zum  Zugriff auf die Detailansichten ausschalten&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Farben und Schriften können Sie durch Anpassung der Datei style.css ändern (Edit files -&amp;gt; style.css) oder Sie erstellen Ihren eigenen Stil (siehe auch stylesheetPrefix) dann wird Ihr neuer Stil auch nicht beim nächsten Ausführen des update-Kommandos überschrieben.&lt;br /&gt;
===Andere Frontends===&lt;br /&gt;
Neben [[FHEMWEB]] können auch andere Frontends an FHEM angebunden werden, um darüber Ihre Geräte zu steuern und darzustellen. Weiterführende Hinweise finden Sie hier im Wiki und im Forum unter &#039;&#039;FHEM » Frontends&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==Komplexe Strukturen==&lt;br /&gt;
Um gleichzeitig verschiedene Geräte auf einmal anzusprechen, kann mit Filtern und Abfragen gearbeitet werden. Details entnehmen sie bitten dem {{Link2CmdRef|Anker=devspec|Lang=de|Label=devspec}}-Abschnitt der commandref.&lt;br /&gt;
Z.B. können Sie die &#039;&#039;room=&amp;lt;roomname&amp;gt;&#039;&#039; Spezifikation verwenden, um gleichzeitig alle diesem Raum zugeordneten Geräte auf einmal anzusprechen. &lt;br /&gt;
&lt;br /&gt;
Für noch komplexere Szenarien informieren sie sich bitte über das {{Link2CmdRef|Anker=structure|Lang=de|Label=structure}}-Modul. Sie können verschiedene Ebenen wie Flure, Gebäude usw. definieren und alle Geräte einer definierten Struktur auf einmal ansprechen.&lt;br /&gt;
&lt;br /&gt;
==Wichtige Befehle und Module für die erste Zeit==&lt;br /&gt;
*{{Link2CmdRef|Anker=list|Lang=de|Label=list}} - ([[list|Wiki]])&lt;br /&gt;
*{{Link2CmdRef|Anker=define|Lang=de|Label=define}}&lt;br /&gt;
*{{Link2CmdRef|Anker=defmod|Lang=de|Label=defmod}}&lt;br /&gt;
*{{Link2CmdRef|Anker=version|Lang=de|Label=version}} - ([[version|Wiki]])&lt;br /&gt;
*{{Link2CmdRef|Anker=update|Lang=de|Label=update}} - ([[update|Wiki]])&lt;br /&gt;
*{{Link2CmdRef|Anker=shutdown|Lang=de|Label=shutdown}}&lt;br /&gt;
*{{Link2CmdRef|Anker=DOIF|Lang=de|Label=DOIF}} - ([[DOIF|Wiki]])&lt;br /&gt;
*{{Link2CmdRef|Anker=notify|Lang=de|Label=notify}} - ([[notify|Wiki]])&lt;br /&gt;
*{{Link2CmdRef|Anker=at|Lang=de|Label=at}} - ([[at|Wiki]])&lt;br /&gt;
*{{Link2CmdRef|Anker=sleep|Lang=de|Label=sleep}}&lt;br /&gt;
*{{Link2CmdRef|Anker=cancel|Lang=de|Label=cancel}}&lt;br /&gt;
*{{Link2CmdRef|Anker=watchdog|Lang=de|Label=watchdog}} - ([[watchdog|Wiki]])&lt;br /&gt;
&lt;br /&gt;
==FHEM ist ein Perl Server...==&lt;br /&gt;
&lt;br /&gt;
Die meisten FHEM-Nutzer werden früher oder später daran erinnert, dass FHEM in Perl programmiert ist. Auch wenn es in vielen Fällen nicht zwingend erforderlich ist, diese Programmiersprache zu erlernen, ist es für ein vertieftes Verständnis der Funktionsweise Ihrer Hausautomatisierung hilfreich, wenn Sie sich auch mit den Grundlagen zu Perl sowie der häufig vorkommenden [[Regulärer Ausdruck|regex-Ausdrücken]] vertraut machen. Manche Problemstellungen lassen sich nach wie vor am effektivsten unmittelbar mit diesen Werkzeugen lösen.&lt;br /&gt;
Einen ersten Einblick in diese Themen finden Sie in den {{Link2CmdRef|Anker=command|Lang=de|Label=FHEM Befehls-Typen}}, {{Link2CmdRef|Anker=perl|Lang=de|Label=PERL Besonderheiten}} und dem Artikel zu [[99 myUtils anlegen]]. [[DevelopmentModuleIntro|In dieser Artikelserie]] sind weitere Informationen für  Fortgeschrittene und Experten zu finden.&lt;br /&gt;
&lt;br /&gt;
==Hinweise==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:FHEM]]&lt;br /&gt;
[[Kategorie:FHEM-Verwendung]]&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=HTTPMOD&amp;diff=38692</id>
		<title>HTTPMOD</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=HTTPMOD&amp;diff=38692"/>
		<updated>2023-11-09T10:49:22Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: veraltete &amp;quot;source&amp;quot;-Angaben in &amp;quot;syntaxhighlight&amp;quot; geändert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=Extract information from devices with an HTTP interface (or, more generic, from any URL) or send information to such devices &lt;br /&gt;
|ModType=d&lt;br /&gt;
|ModCmdRef=HTTPMOD&lt;br /&gt;
|ModForumArea=Sonstiges&lt;br /&gt;
|ModTechName=98_HTTPMOD.pm&lt;br /&gt;
|ModOwner=StefanStrobel ({{Link2FU|3960|Forum}} / [[Benutzer:StefanStrobel|Wiki]])&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
HTTPMOD provides a generic way to retrieve information from devices with an HTTP Interface and store them in Readings or send information to such devices. It queries a given URL with Headers and data defined by attributes. &lt;br /&gt;
&lt;br /&gt;
From the HTTP response it extracts readings named in attributes using Regexes, JSON or XPath parsing also defined by attributes.&lt;br /&gt;
&lt;br /&gt;
In an advanced [[Konfiguration|configuration]] the module can also send information to devices. To do this, a generic &amp;lt;code&amp;gt;set&amp;lt;/code&amp;gt; option can be configured using attributes. &lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
With the help of HTTPMOD you can automatically access websites, retrieve information and send data. In the simplest case, an http call is started regularly and the content of a page, for example, is read and processed further. The URL and the time interval in which the call is to be made must then be specified when the call is made. In order to read information from the called web pages, readings are required. In this readings one specifies Regex, which reads the necessary information. Here is an example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
define PM HTTPMOD  http://www.klack.de/fernsehprogramm/was-laeuft-gerade/0/-1/free.html 20000&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This creates a device that accesses the http://www.klack.de/fernsehprogramm/was-laeuft-gerade/0/-1/free.html website with the TV program every 20000 seconds. If neither readings nor other attributes are defined, then only the call of the website takes place and FHEM receives no further data from the web access.&lt;br /&gt;
&lt;br /&gt;
But now a television program is returned when you call the website, which you might want to read out. In order to save the contents in FHEM, which are related to the ARD, you need a reading. This reading must contain a name (so that FHEM knows under which name the information is stored) and a regex (so that you know where the information is stored on the website). Since usually not one, but many readings are defined, these readings are numbered consecutively. This is done by numbers that are given immediately after the word reading. In our example this would be for example&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr PM reading1Name ARD &lt;br /&gt;
attr PM reading1Regex &amp;lt;span class=&amp;quot;stationName&amp;quot;&amp;gt;ARD&amp;lt;\/span&amp;gt;[\w\W]*?&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;\s*&amp;lt;a[\w\W]*?&amp;gt;\s*(.*?)\s*&amp;lt;\/a&amp;gt; &lt;br /&gt;
attr PM reading2Name ARD_time &lt;br /&gt;
attr PM reading2Regex &amp;lt;span class=&amp;quot;stationName&amp;quot;&amp;gt;ARD&amp;lt;\/span&amp;gt;[\w\W]*?&amp;lt;td class=&amp;quot;time&amp;quot;&amp;gt;\s*(.*?)\s*&amp;lt; &lt;br /&gt;
attr PM reading3Name ARD_details &lt;br /&gt;
attr PM reading3Regex &amp;lt;span class=&amp;quot;stationName&amp;quot;&amp;gt;ARD&amp;lt;\/span&amp;gt;[\w\W]*?&amp;lt;div class=&amp;quot;content&amp;quot;&amp;gt;\s*&amp;lt;a[\w\W]*?&amp;gt;[\w\W]*?&amp;lt;\/a&amp;gt;\s*&amp;lt;br\/&amp;gt;\s*(.*?)(&amp;lt;img|&amp;lt;\/div) &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reading1 contains the programme, reading2 the time and reading3 further details.  The Regex result from the structure of the website and may have to be designed in painstaking detail.&lt;br /&gt;
&lt;br /&gt;
There are cases where this is not enough. For example, it could be the case that the information from the web access is not automated, but manually received. Then a 0 must first be entered at the top of the duration. But how does HTTPMOD then know when the data should be retrieved? This is done with get-commands. If a get-command is executed, HTTPMOD accesses the website, fetches the information and fills the corresponding readings. &lt;br /&gt;
&lt;br /&gt;
Again, it is possible to create not one but several get-commands. Therefore, get is always followed by (at least) one number with which the get commands are numbered.  Here is another example. The TV program should be called manually and not time-controlled. To do this we first change the definition to &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
define PM HTTPMOD  http://www.klack.de/fernsehprogramm/was-laeuft-gerade/0/-1/free.html 0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
and add the following to the attributes&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr PM get1Name ARDHolen &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
With the command &amp;quot;get PM ARDHolen&amp;quot; the above readings are filled. In order for FHEM to know that the other reading2, reading3, etc. are to be read as well as reading1, the (user) attribute  &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr PM get1CheckAllReadings 1 &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
needs to be defined.&lt;br /&gt;
&lt;br /&gt;
If the URL is not sufficient when the web page is called, but a special header is to be sent with it, this can be done with the get1Header attribute. If the header is multiline, the individual lines can be entered with get1Header1, get1Header2, and so on.    &lt;br /&gt;
&lt;br /&gt;
If you want to evaluate or control different URLs, you can define several get commands (get1, get2, etc.) and provide them with your own URLs. get1 usually reads only the reading1, get2 reads only the reading2 and so on. With CheckAllReadings all readings are evaluated simultaneously.&lt;br /&gt;
&lt;br /&gt;
If only data is to be sent on the web page, but not read, the set command is recommended. It has the same structure as the get-command.&lt;br /&gt;
&lt;br /&gt;
It becomes a bit more complex if the website requires a login check. The sid attributes are used for this purpose.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Availability, prerequisites and definition ==&lt;br /&gt;
This module is part of the regular FHEM distribution and uses the non blocking HTTP function &amp;lt;code&amp;gt;HttpUtils_NonblockingGet&amp;lt;/code&amp;gt; provided by FHEM&#039;s [[HttpUtils]] in a new version published in December 2013.&lt;br /&gt;
If not already installed in your environment, please [[update]] FHEM or install it manually using appropriate commands from your environment.&lt;br /&gt;
Please also note that FHEM HttpUtils need the global attribute dnsServer to be set in order to work really non blocking even when dns requests can not be answered.&lt;br /&gt;
&lt;br /&gt;
The device is defined as follows&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
define &amp;lt;name&amp;gt; HTTPMOD &amp;lt;URL&amp;gt; &amp;lt;Interval&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The module connects to the given &amp;lt;code&amp;gt;URL&amp;lt;/code&amp;gt; every &amp;lt;code&amp;gt;Interval&amp;lt;/code&amp;gt; seconds, sends optional headers and data and then parses the response with regular expressions, xpath or json to set readings.&lt;br /&gt;
&lt;br /&gt;
URL can be &amp;quot;none&amp;quot; and Interval can be 0 if you prefer to only query data with a get command and not in a defined interval.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
define PM HTTPMOD http://MyPoolManager/cgi-bin/webgui.fcgi 60&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Set-Commands ==&lt;br /&gt;
can be defined using attributes, see advanced configuration&lt;br /&gt;
&lt;br /&gt;
If you set the attribute enableControlSet to 1, the following additional built in set commands are available:&lt;br /&gt;
;interval&lt;br /&gt;
:set new interval time in seconds and restart the timer&lt;br /&gt;
;reread&lt;br /&gt;
:request the defined URL and try to parse it just like the automatic update would do it every Interval seconds without modifying the running timer.&lt;br /&gt;
;stop&lt;br /&gt;
:stop interval timer.&lt;br /&gt;
;start&lt;br /&gt;
:restart interval timer to call GetUpdate after interval seconds&lt;br /&gt;
;upgradeAttributes&lt;br /&gt;
:convert outdated attributes for older HTTPMOD-Versions that are still defined for this device from the old syntax to the new one.&lt;br /&gt;
:attributes with the description &amp;quot;this attribute should not be used anymore&amp;quot; or similar will be translated to the new syntax, e.g. readingsName1 to reading01Name.&lt;br /&gt;
;storeKeyValue&lt;br /&gt;
:stores a key value pair in an obfuscated form in the file system. Such values can then be used in replacements where the mode is &amp;quot;key&amp;quot; e.g. to avoid storing passwords in the configuration in clear text&lt;br /&gt;
&lt;br /&gt;
== Get-Commands ==&lt;br /&gt;
can be defined using attributes, see advanced configuration&lt;br /&gt;
&lt;br /&gt;
== simple Attributes ==&lt;br /&gt;
;enableControlSet&lt;br /&gt;
:enables the built in set commands &#039;&#039;interval&#039;&#039;, &#039;&#039;stop&#039;&#039;, &#039;&#039;start&#039;&#039;, &#039;&#039;reread&#039;&#039;, &#039;&#039;upgradeAttributes&#039;&#039;, &#039;&#039;storeKeyValue&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
;enableCookies&lt;br /&gt;
:enables the cookie handling inside HTTPMOD. It is advisable to always set this attribute and allow HTTPMOD to track the state of cookies and set them for following HTTP-requests&lt;br /&gt;
&lt;br /&gt;
;enforceGoodReadingNames&lt;br /&gt;
:makes sure that HTTPMOD only creates readings that are allowd for Fhem (especially if reading names are dynamically created from JSON object names with extractAllJSON. It is advisable to always set this attribute.&lt;br /&gt;
&lt;br /&gt;
;handleRedirects&lt;br /&gt;
:enables the redirect handling inside HTTPMOD which should be used together with the cookie handling of HTTPMOD. HTTPMOD will then automatically follow redirects from a web server and keep track of cookies at the same time. It is advisable to always set this attribute.&lt;br /&gt;
&lt;br /&gt;
;requestHeader.* &lt;br /&gt;
:Define an additional HTTP Header to set in the HTTP request&lt;br /&gt;
&lt;br /&gt;
;requestData&lt;br /&gt;
:POST Data to be sent in the request. If not defined, it will be a GET request as defined in HttpUtils used by this module&lt;br /&gt;
&lt;br /&gt;
;reading[0-9]+(-[0-9]+)?Name&lt;br /&gt;
:the name of a reading to extract with the corresponding readingRegex&lt;br /&gt;
&lt;br /&gt;
;reading[0-9]*(-[0-9]+)?OExpr&lt;br /&gt;
:defines an expression that is used in an eval to compute the readings value. The raw value will be in the variable $val.&lt;br /&gt;
&lt;br /&gt;
;reading[0-9]*(-[0-9]+)?OMap&lt;br /&gt;
:Output Map. Defines a mapping from raw to visible values like &amp;quot;0:mittig, 1:oberhalb, 2:unterhalb&amp;quot;. If specified as readingOMap then the attribute value is a default for all other readings that don&#039;t specify an explicit reading[0-9]*OMap.&lt;br /&gt;
&lt;br /&gt;
;reading[0-9]*(-[0-9]+)?Format&lt;br /&gt;
:Defines a format string that will be used in sprintf to format a reading value. If specified as readingFormat then the attribute value is a default for all other readings that don&#039;t specify an explicit reading[0-9]*Format.&lt;br /&gt;
&lt;br /&gt;
;reading[0-9]*(-[0-9]+)?Decode&lt;br /&gt;
:defines an encoding to be used in a call to the perl function decode to convert the raw data string read from the device to a reading. This can be used if the device delivers strings in an encoding like cp850 instead of utf8.&lt;br /&gt;
&lt;br /&gt;
;reading[0-9]*(-[0-9]+)?Encode&lt;br /&gt;
:defines an encoding to be used in a call to the perl function encode to convert the raw data string read from the device to a reading. This can be used if the device delivers strings in an encoding like cp850 and after decoding it you want to reencode it to e.g. utf8.&lt;br /&gt;
&lt;br /&gt;
;reading[0-9]+Regex&lt;br /&gt;
:defines the regex to be used for extracting the reading. The value to extract should be in a capture group / sub expression &lt;br /&gt;
:e.g. ([\d\.]+) in the above example. Multiple capture groups will create multiple readings (see explanation above)&lt;br /&gt;
&lt;br /&gt;
;reading[0-9]+XPath&lt;br /&gt;
:defines an xpath to one or more readings when parsing HTML data (see examples below)&lt;br /&gt;
&lt;br /&gt;
;reading[0-9]+XPath-Strict&lt;br /&gt;
:defines an xpath to one or more readings when parsing XML data (see examples below)&lt;br /&gt;
&lt;br /&gt;
;reading[0-9]+JSON&lt;br /&gt;
:defines a path to the JSON object wanted by concatenating the object names with an underscore as delimiter (see the example below)&lt;br /&gt;
&lt;br /&gt;
;noShutdown&lt;br /&gt;
:pass the noshutdown flag to HTTPUtils for webservers that need it (some embedded webservers only deliver empty pages otherwise)&lt;br /&gt;
&lt;br /&gt;
;disable&lt;br /&gt;
:stop doing automatic HTTP requests while this attribute is set to 1&lt;br /&gt;
&lt;br /&gt;
;timeout&lt;br /&gt;
:time in seconds to wait for an answer. Default value is 2&lt;br /&gt;
&lt;br /&gt;
;do_not_notify&lt;br /&gt;
&lt;br /&gt;
;readingFnAttributes&lt;br /&gt;
&lt;br /&gt;
== Simple Configuration of HTTP Devices ==&lt;br /&gt;
If your device expects special HTTP-headers then specify them as &amp;lt;code&amp;gt;attr requestHeader1&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;attr requestHeaderX&amp;lt;/code&amp;gt;.&lt;br /&gt;
If your Device expects an HTTP POST instead of HTTP GET then the POST-data can be specified as &amp;lt;code&amp;gt;attr requestData&amp;lt;/code&amp;gt;.&lt;br /&gt;
To get the readings, specify pairs of &amp;lt;code&amp;gt;attr readingXName&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;attr readingXRegex&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;attr readingXXPath&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;attr readingXXPath-Strict&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;attr readingXJSON&amp;lt;/code&amp;gt; to define which readings you want to extract from the HTTP response and how to extract them. (The old syntax &amp;lt;code&amp;gt;attr readingsNameX&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;attr readingsRegexX&amp;lt;/code&amp;gt; is still supported but the new one with &amp;lt;code&amp;gt;attr readingXName&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;attr readingXRegex&amp;lt;/code&amp;gt; should be preferred. The actual values to be extracted have to be sub expressions within () in the regex (see example below)&lt;br /&gt;
&lt;br /&gt;
=== Example for a PoolManager 5: ===&lt;br /&gt;
The PoolManager Web GUI can be queried with HTTP POST Requests like this one:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
POST /cgi-bin/webgui.fcgi HTTP/1.1&lt;br /&gt;
Host: 192.168.70.90&lt;br /&gt;
Accept: */*&lt;br /&gt;
Content-Type: application/json;charset=UTF-8&lt;br /&gt;
Content-Length: 60&lt;br /&gt;
&lt;br /&gt;
{&amp;quot;get&amp;quot; :[&amp;quot;34.4001.value&amp;quot; ,&amp;quot;34.4008.value&amp;quot; ,&amp;quot;34.4033.value&amp;quot;]}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The resulting HTTP Response would look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
HTTP/1.1 200 OK&lt;br /&gt;
Content-type: application/json; charset=UTF-8&lt;br /&gt;
Expires: 0&lt;br /&gt;
Cache-Control: no-cache&lt;br /&gt;
Date: Sun, 12 Jan 2014 12:23:11 GMT&lt;br /&gt;
Server: lighttpd/1.4.26&lt;br /&gt;
Content-Length: 179&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;data&amp;quot;:	{&lt;br /&gt;
		&amp;quot;34.4001.value&amp;quot;:	&amp;quot;7.00&amp;quot;,&lt;br /&gt;
		&amp;quot;34.4008.value&amp;quot;:	&amp;quot;0.52&amp;quot;,&lt;br /&gt;
		&amp;quot;34.4033.value&amp;quot;:	&amp;quot;24.8&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	&amp;quot;status&amp;quot;:	{&lt;br /&gt;
		&amp;quot;code&amp;quot;:	0&lt;br /&gt;
	},&lt;br /&gt;
	&amp;quot;event&amp;quot;:	{&lt;br /&gt;
		&amp;quot;type&amp;quot;:	1,&lt;br /&gt;
		&amp;quot;data&amp;quot;:	&amp;quot;48.30000.0&amp;quot;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To configure HTTPMOD for a PoolManager one would first define a PoolManager device with e.g. the name PM, the URL and an interval of e.g. 60 seconds. &lt;br /&gt;
&lt;br /&gt;
Then the data to be sent in the request needs to be defined because in this example the device expects a POST request so the query is not contained in the URL but in the request data.&lt;br /&gt;
&lt;br /&gt;
Also as seen above the device expects special HTTP headers in the request so these headers also need to be defined as &amp;lt;code&amp;gt;attr PM requestHeader1&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;attr PM requestHeader2&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then the names of the readings to be extracted would be set with attributes&lt;br /&gt;
&lt;br /&gt;
Then for each reading value to be extracted a regular expression needs to be set that will match the value in question within ().&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
define PM HTTPMOD http://MyPoolManager/cgi-bin/webgui.fcgi 60&lt;br /&gt;
&lt;br /&gt;
attr PM enableControlSet 1&lt;br /&gt;
attr PM enableCookies 1&lt;br /&gt;
attr PM enforceGoodReadingNames 1&lt;br /&gt;
attr PM handleRedirects 1&lt;br /&gt;
&lt;br /&gt;
attr PM reading01Name PH&lt;br /&gt;
attr PM reading01Regex 34.4001.value&amp;quot;:[ \t]+&amp;quot;([\d\.]+)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
attr PM reading02Name CL&lt;br /&gt;
attr PM reading02Regex 34.4008.value&amp;quot;:[ \t]+&amp;quot;([\d\.]+)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
attr PM reading03Name3TEMP&lt;br /&gt;
attr PM reading03Regex 34.4033.value&amp;quot;:[ \t]+&amp;quot;([\d\.]+)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
attr PM requestData {&amp;quot;get&amp;quot; :[&amp;quot;34.4001.value&amp;quot; ,&amp;quot;34.4008.value&amp;quot; ,&amp;quot;34.4033.value&amp;quot;, &amp;quot;14.16601.value&amp;quot;, &amp;quot;14.16602.value&amp;quot;]}&lt;br /&gt;
attr PM requestHeader1 Content-Type: application/json&lt;br /&gt;
attr PM requestHeader2 Accept: */*&lt;br /&gt;
attr PM stateFormat {sprintf(&amp;quot;%.1f Grad, PH %.1f, %.1f mg/l Chlor&amp;quot;, ReadingsVal($name,&amp;quot;TEMP&amp;quot;,0), ReadingsVal($name,&amp;quot;PH&amp;quot;,0), ReadingsVal($name,&amp;quot;CL&amp;quot;,0))}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Example for AmbientMonitor ===&lt;br /&gt;
AmbientMonitor is a webbased visualisation for sensors connected to an Arduino device. Its web interface can also be queried with HTTMOD to grab the data into readings.&lt;br /&gt;
&lt;br /&gt;
This example was provided by locutus. The hardware configuration is an Arduino + Ethercard with ENC28J60 Controller + DHT22 Sensor and software can be downloaded from https://github.com/lucadentella/AmbientMonitor&lt;br /&gt;
&lt;br /&gt;
In this example an HTTP GET is sufficent, so no &amp;lt;code&amp;gt;requestData&amp;lt;/code&amp;gt; is needed. The device provides temperature and humidity readings in an HTTP response that looks like:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
HTTP/1.0 200 OK &lt;br /&gt;
Content-Type: text/html &lt;br /&gt;
&lt;br /&gt;
myCB({&#039;temperature&#039;:22.00,&#039;humidity&#039;:46.00})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the definition could be:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
define AmbientMonitor HTTPMOD http://192.168.1.221/?callback=? 300&lt;br /&gt;
&lt;br /&gt;
attr AmbientMonitor enableControlSet 1&lt;br /&gt;
attr AmbientMonitor enableCookies 1&lt;br /&gt;
attr AmbientMonitor enforceGoodReadingNames 1&lt;br /&gt;
attr AmbientMonitor handleRedirects 1&lt;br /&gt;
&lt;br /&gt;
attr AmbientMonitor requestHeader Content-Type: application/json&lt;br /&gt;
attr AmbientMonitor reading1Name Temperatur&lt;br /&gt;
attr AmbientMonitor reading1Regex temperature&#039;:([\d\.]+)&lt;br /&gt;
attr AmbientMonitor reading2Name Feuchtigkeit&lt;br /&gt;
attr AmbientMonitor reading2Regex humidity&#039;:([\d\.]+)&lt;br /&gt;
attr AmbientMonitor stateFormat {sprintf(&amp;quot;Temperatur %.1f C, Feuchtigkeit %.1f %&amp;quot;, ReadingsVal($name,&amp;quot;Temperatur&amp;quot;,0), ReadingsVal($name,&amp;quot;Feuchtigkeit&amp;quot;,0))}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== formatting and manipulating values / readings ==&lt;br /&gt;
Values that are parsed from an HTTP response can be further treated or formatted with the following attributes:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;(reading|get)[0-9]*(-[0-9]+)?OExpr&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;(reading|get)[0-9]*(-[0-9]+)?OMap&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;(reading|get)[0-9]*(-[0-9]+)?Format&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;(reading|get)[0-9]*(-[0-9]+)?Decode&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;(reading|get)[0-9]*(-[0-9]+)?Encode&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
They can all be specified for an individual reading, for all readings in one match (e.g. if a regular expression has several capture groups) or for all readings in a get command (defined by getXX) or for all readings in the main reading list (defined by readingXX):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
reading01Format %.1f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will format the reading with the name specified by the attribute reading01Name to be numerical with one digit after the decimal point.&lt;br /&gt;
If the attribute reading01Regex is used and contains several capture groups then the format will be applied to all readings parsed by this regex unless these readings have their own format specified by reading01-1Format, reading01-2Format and so on.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
reading01-2Format %.1f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Can be used in cases where a regular expression specified as reading01regex contains several capture groups or an xpath specified as reading01XPath creates several readings. &lt;br /&gt;
In this case reading01-2Format specifies the format to be applied to the second match.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
readingFormat %.1f&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
applies to all readings defined by a reading-Attribute that have no more specific format.&lt;br /&gt;
&lt;br /&gt;
If you need to do some calculation on a raw value before it is used as a reading, you can define the attribute &amp;lt;code&amp;gt;readingOExpr&amp;lt;/code&amp;gt;.&lt;br /&gt;
It defines a Perl expression that is used in an eval to compute the readings value. The raw value will be in the variable $val.&lt;br /&gt;
&lt;br /&gt;
Example for an expression:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr PM reading03OExpr $val * 10&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Just like in the above example of the readingFormat attributes, readingOExpr and the other following attributes can be applied on several levels.&lt;br /&gt;
&lt;br /&gt;
To map a numerical value to a name, you can use the readingOMap attribute. &lt;br /&gt;
It defines a mapping from raw to visible values like &amp;quot;0:mittig, 1:oberhalb, 2:unterhalb&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Example for a map:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr PM reading02-3OMap 0:kalt, 1:warm, 2:sehr warm&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To convert character sets, the module can first decode a string read from the device and then encode it again. For example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr PM getDecode UTF-8&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This applies to all readings defined for Get-Commands.&lt;br /&gt;
&lt;br /&gt;
== Some help with Regular Expressions ==&lt;br /&gt;
{{Randnotiz|RNTyp=y|RNText=Starting with version &#039;&#039;2018-02-10&#039;&#039; the internal that holds the HTTP response is no longer called &#039;&#039;&#039;&#039;&#039;buf&#039;&#039;&#039;&#039;&#039; but rather &#039;&#039;&#039;&#039;&#039;httpbody&#039;&#039;&#039;&#039;&#039;, and it is only displayed when attribute &#039;&#039;&#039;&#039;&#039;showBody&#039;&#039;&#039;&#039;&#039; is set to &amp;quot;1&amp;quot;.}}&lt;br /&gt;
If HTTPMOD seems not to work and the FHEM Logfile contains a message like  &lt;br /&gt;
:&amp;lt;code&amp;gt;HTTPMOD: Response didn&#039;t match Reading ...&amp;lt;/code&amp;gt;&lt;br /&gt;
then you should check if the value you want to extract is read into the internal with the name buf. Internals are visible when you click on the defined HTTPMOD Device. buf is an internal variable that contains the HTTP Response read. If the value is there and you get the mentioned message then probably something is wrong with your regular expression. Please note that buf might contain special characters like newlines but they are not shown in fhemweb. If you are new to regular expressions then the introduction at http://perldoc.perl.org/perlretut.html might be helpful. &lt;br /&gt;
&lt;br /&gt;
For a typical HTTPMOD use case where you want to extract a number out of a HTTP-Response you can use something like &amp;lt;code&amp;gt;[\d\.]+&amp;lt;/code&amp;gt; to match the number itself. The expression matches the number characters (&amp;lt;code&amp;gt;\d&amp;lt;/code&amp;gt;) or a &amp;lt;code&amp;gt;.&amp;lt;/code&amp;gt; if one of these characters occurs at least once. &lt;br /&gt;
&lt;br /&gt;
To tell HTTPMOD that the number is what you want to use for the reading, you have to put the expression in between &amp;lt;code&amp;gt;()&amp;lt;/code&amp;gt;. A &amp;lt;code&amp;gt;([\d\.]+)&amp;lt;/code&amp;gt; alone would match the longest number in the HTTP Response which is very likely not the number you are looking for so you need to add something to the expression to give it a context and define how to find the number that you are looking for.&lt;br /&gt;
&lt;br /&gt;
If there is a title text before the number or a special text after the number you can put this in the regex. In one of the examples above &amp;lt;code&amp;gt;humidity&#039;:([\d\.]+)&amp;lt;/code&amp;gt; is looking for the number that immediately follows the text &amp;lt;code&amp;gt;humidity&#039;:&amp;lt;/code&amp;gt; without any blanks in between.&lt;br /&gt;
Be careful if the text you are getting from your device contains special characters like newline. You don&#039;t see such special characters in the fhem webinterface as contents of the internal buf but they might cause your regular expression to fail. &lt;br /&gt;
&lt;br /&gt;
If you have trouble defining a regular expression that matches a certain name, then many complicated characters and then a number, it might be helpful to use a negation in matching like &amp;lt;code&amp;gt;temp[^\d]+([\d\.]).*&amp;lt;/code&amp;gt;. In this examle &amp;lt;code&amp;gt;[^\d]+&amp;lt;/code&amp;gt; means any character that is not a numerical digit, more than once.&lt;br /&gt;
&lt;br /&gt;
=== Regular Expressions with multiple capture Groups ===&lt;br /&gt;
The regular expressions used in the above example for a Poolmanager will take the value that matches one capture group. This is the part of the regular expression inside (). In the above example &amp;quot;([\d\.]+)&amp;quot; refers to numerical digits or points between double quotation marks. Only the string consiting of digits and points will match inside (). This piece is assigned to the reading.&lt;br /&gt;
        &lt;br /&gt;
You can also use regular expressions that have several capture groups which might be helpful when parsing tables. In this case an attribute like &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
reading02Regex something[ \t]+([\d\.]+)[ \t]+([\d\.]+)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
could match two numbers. When you specify only one reading02Name like &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
reading02Name Temp&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the name Temp will be used with the extension -1 and -2 thus giving a reading Temp-1 for the first number and Temp-2 for the second. You can also specify individual names for several readings that get parsed from one regular expression with several capture groups by defining attributes &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
reading02-1Name&lt;br /&gt;
reading02-2Name&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The same notation can be used for formatting attributes like readingXOMap, readingXFormat and so on.&lt;br /&gt;
&lt;br /&gt;
The usual way to define readings is however to have an individual regular expression with just one capture group per reading as shown in the above example.&lt;br /&gt;
&lt;br /&gt;
== Parsing JSON ==&lt;br /&gt;
    &lt;br /&gt;
If a webservice delivers data in JSON format, HTTPMOD can directly parse JSON which might be easier in this case than definig regular expressions.&lt;br /&gt;
The next example shows the data that can be requested from a Poolmanager with the following partial configuration:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
define test2 HTTPMOD none 0&lt;br /&gt;
attr test2 get01Name Chlor&lt;br /&gt;
attr test2 getURL http://192.168.70.90/cgi-bin/webgui.fcgi&lt;br /&gt;
attr test2 getHeader1 Content-Type: application/json&lt;br /&gt;
attr test2 getHeader2 Accept: */*&lt;br /&gt;
attr test2 getData {&amp;quot;get&amp;quot; :[&amp;quot;34.4008.value&amp;quot;]}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The data in the HTTP response looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;data&amp;quot;: {&lt;br /&gt;
			&amp;quot;34.4008.value&amp;quot;: &amp;quot;0.25&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	&amp;quot;status&amp;quot;:       {&lt;br /&gt;
			&amp;quot;code&amp;quot;: 0&lt;br /&gt;
	},&lt;br /&gt;
	&amp;quot;event&amp;quot;:        {&lt;br /&gt;
			&amp;quot;type&amp;quot;: 1,&lt;br /&gt;
			&amp;quot;data&amp;quot;: &amp;quot;48.30000.0&amp;quot;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the classic way to extract the value 0.25 into a reading with the name Chlor with a regex would have been&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr test2 get01Regex 34.4008.value&amp;quot;:[ \t]+&amp;quot;([\d\.]+)&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with JSON you can write &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr test2 get01JSON data_34.4008.value &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
which will create a reading with the Name &amp;quot;Chlor&amp;quot; (as shown above) and take the value 0.25 from the JSON string.&lt;br /&gt;
&lt;br /&gt;
or if you don&#039;t care about the naming of your readings, you can simply extract all JSON data with &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr test2 extractAllJSON&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which would apply to all data read from this device and create the following readings out of the HTTP response shown above:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| data_34.4008.value || 0.25&lt;br /&gt;
|-&lt;br /&gt;
| event_data || 48.30000.0&lt;br /&gt;
|-&lt;br /&gt;
| event_type || 1&lt;br /&gt;
|-&lt;br /&gt;
| status_code || 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
or you can specify&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr test2 get01ExtractAllJSON&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
which would only apply to all data read as response to the get command defined as get01.        &lt;br /&gt;
&lt;br /&gt;
It might seem very simple at first sight to use extractAllJSON but if you prefer readings with a meaningful name you should instead define these readings with readingXXName and readingXXJSON or getXXName and getXXJSON individually. Of Course it would be possible to create additional user readings outside HTTPMOD but doing calculations, naming and formatting inside HTTPMOD is more efficient.&lt;br /&gt;
&lt;br /&gt;
=== JSON Lists ===&lt;br /&gt;
&lt;br /&gt;
imagine the HTTP Response contains:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
{ &amp;quot;power&amp;quot;:&amp;quot;0&amp;quot;,&lt;br /&gt;
  &amp;quot;modes&amp;quot;:[&amp;quot;Off&amp;quot;,&amp;quot;SimpleColor&amp;quot;,&amp;quot;RainbowChase&amp;quot;],&lt;br /&gt;
  &amp;quot;code1&amp;quot;:3,&lt;br /&gt;
  &amp;quot;code2&amp;quot;:4&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
then a configuration like &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr device reading01JSON modes &lt;br /&gt;
attr device reading01Name Mode &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will create a list of Subreadings just like a regex with multiple matches can create multiple subreadings:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Mode-1 || Off&lt;br /&gt;
|-&lt;br /&gt;
| Mode-2  || SimpleColor&lt;br /&gt;
|-&lt;br /&gt;
| Mode-3 || RainbowChase &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
if you don&#039;t want several subreadings but one reading that contains the list of modes, you can specify a recombine expression:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr device reading01Name Modes &lt;br /&gt;
attr device reading01RecombineExpr join &amp;quot;,&amp;quot;, @matchlist &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which will create one reading containing a list:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Modes || Off,SimpleColor,RainbowChase&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
JSON parsing specifications also don&#039;t Need to match exactly. If there is no exact match for a defined reading, the HTTPMOD will try to Interpret the specification as a regex and look for json object paths that match the specification as a regex. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr device reading01Name CodeElem&lt;br /&gt;
attr device reading01JSON code&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which will create a list of readings:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| CodeElem-1|| 3&lt;br /&gt;
|-&lt;br /&gt;
| CodeElem-2  || 4&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
and of course they could also be recombined into one reading with a RecombineExpr Attribute.&lt;br /&gt;
&lt;br /&gt;
== Parsing http / XML using xpath ==&lt;br /&gt;
Another alternative to regex parsing is the use of XPath to extract values from HTTP responses.&lt;br /&gt;
The following example shows how XML data can be parsed with XPath-Strict or HTML Data can be parsed with XPath.&lt;br /&gt;
Both work similar and the example uses XML Data parsed with the XPath-Strict option:&lt;br /&gt;
&lt;br /&gt;
If The XML data in the HTTP response looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;xml&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;root xmlns:foo=&amp;quot;http://www.foo.org/&amp;quot; xmlns:bar=&amp;quot;http://www.bar.org&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;actors&amp;gt;&lt;br /&gt;
		&amp;lt;actor id=&amp;quot;1&amp;quot;&amp;gt;Peter X&amp;lt;/actor&amp;gt;&lt;br /&gt;
		&amp;lt;actor id=&amp;quot;2&amp;quot;&amp;gt;Charles Y&amp;lt;/actor&amp;gt;&lt;br /&gt;
		&amp;lt;actor id=&amp;quot;3&amp;quot;&amp;gt;John Doe&amp;lt;/actor&amp;gt;&lt;br /&gt;
	&amp;lt;/actor&amp;gt;&lt;br /&gt;
&amp;lt;/root&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
with XPath you can write        &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr htest reading01Name Actor&lt;br /&gt;
attr htest reading01XPath-Strict //actor[2]/text()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will create a reading with the Name &amp;quot;Actor&amp;quot; and the value &amp;quot;Charles Y&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Since XPath specifications can define several values / matches, HTTPMOD can also interpret these and store them in multiple readings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr htest reading01Name Actor&lt;br /&gt;
attr htest reading01XPath-Strict //actor/text()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will create the readings &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Actor-1 || Peter X&lt;br /&gt;
|-&lt;br /&gt;
| Actor-2 || Charles Y&lt;br /&gt;
|-&lt;br /&gt;
| Actor-3 || John Doe&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Further replacements of URL, header or post data ==&lt;br /&gt;
sometimes it might be helpful to dynamically change parts of a URL, HTTP header or post data depending on existing readings, internals or &lt;br /&gt;
perl expressions at runtime. This might be needed to pass further variables to a server, a current date or other things. &lt;br /&gt;
&lt;br /&gt;
To support this HTTPMOD offers generic replacements that are applied to a request before it is sent to the server. A replacement can be defined with the attributes &lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;replacement[0-9]*Regex&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;replacement[0-9]*Mode&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;replacement[0-9]*Value&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;[gs]et[0-9]*Replacement[0-9]*Value&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
a replacement always replaces a match of a regular expression. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;replacement[0-9]*Mode:&#039;&#039;&#039;&lt;br /&gt;
The way the replacement value is defined can be specified with the replacement mode.&lt;br /&gt;
* If the &amp;lt;code&amp;gt;replacement[0-9]*Mode&amp;lt;/code&amp;gt; is &amp;lt;code&amp;gt;reading&amp;lt;/code&amp;gt;, then the corresponding &amp;lt;code&amp;gt;replacement[0-9]*Value&amp;lt;/code&amp;gt; is interpreted as the name of a &#039;&#039;reading&#039;&#039; of the same device or as &#039;&#039;device:reading&#039;&#039; to refer to another device.&lt;br /&gt;
* If the &amp;lt;code&amp;gt;replacement[0-9]*Mode&amp;lt;/code&amp;gt; is &amp;lt;code&amp;gt;internal&amp;lt;/code&amp;gt;, then the corresponding &amp;lt;code&amp;gt;replacement[0-9]*Value&amp;lt;/code&amp;gt; is interpreted as the name of an &#039;&#039;internal&#039;&#039; of the same device or as &#039;&#039;device:internal&#039;&#039; to refer to another device.&lt;br /&gt;
* If the &amp;lt;code&amp;gt;replacement[0-9]*Mode&amp;lt;/code&amp;gt; is &amp;lt;code&amp;gt;text&amp;lt;/code&amp;gt;, then the corresponding &amp;lt;code&amp;gt;replacement[0-9]*Value&amp;lt;/code&amp;gt; is interpreted as a static text&lt;br /&gt;
* If the &amp;lt;code&amp;gt;replacement[0-9]*Mode&amp;lt;/code&amp;gt; is &amp;lt;code&amp;gt;expression&amp;lt;/code&amp;gt;, then the corresponding &amp;lt;code&amp;gt;replacement[0-9]*Value&amp;lt;/code&amp;gt; is evaluated as a perl expression to compute the replacement. Inside such a replacement expression it is possible to refer to capture groups of the replacement regex.&lt;br /&gt;
* If the &amp;lt;code&amp;gt;replacement[0-9]*Mode&amp;lt;/code&amp;gt; is &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt;, then the module will use a value from a key / value pair that is stored in an obfuscated form in the file system with the set storeKeyValue command. This might be useful for storing passwords.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot; line=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
attr mydevice getData {&amp;quot;get&amp;quot; :[&amp;quot;%%value%%.value&amp;quot;]}&lt;br /&gt;
attr mydevice replacement01Mode text&lt;br /&gt;
attr mydevice replacement01Regex %%value%%&lt;br /&gt;
&lt;br /&gt;
attr mydevice get01Name Chlor&lt;br /&gt;
attr mydevice get01Replacement01Value 34.4008&lt;br /&gt;
&lt;br /&gt;
attr mydevice get02Name Something&lt;br /&gt;
attr mydevice get02Replacement01Value 31.4024&lt;br /&gt;
&lt;br /&gt;
attr mydevice get05Name profile&lt;br /&gt;
attr mydevice get05URL http://www.mydevice.local/getprofile?password=%%password%%&lt;br /&gt;
attr mydevice replacement02Mode key&lt;br /&gt;
attr mydevice replacement02Regex %%password%%&lt;br /&gt;
attr mydevice replacement02Value password&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;        &lt;br /&gt;
&lt;br /&gt;
defines that &amp;lt;code&amp;gt;%%value%%&amp;lt;/code&amp;gt; will be replaced by a static text.&lt;br /&gt;
&lt;br /&gt;
All Get commands will be HTTP post requests of a similar form. Only the &amp;lt;code&amp;gt;%%value%%&amp;lt;/code&amp;gt; will be different from get to get.&lt;br /&gt;
The first get will set the reading named Chlor and for the request it will take the generic getData and replace %%value%% with 34.4008.&lt;br /&gt;
&lt;br /&gt;
A second get will look the same except a different name and replacement value.&lt;br /&gt;
&lt;br /&gt;
With the command &amp;lt;code&amp;gt;set mydevice storeKeyValue password geheim&amp;lt;/code&amp;gt; you can store the password geheim in an obfuscated form in the file system. &lt;br /&gt;
To use this password and send it in a request you can use the above replacement with mode key. The value password will then refer to the ofuscated string stored with the key password.&lt;br /&gt;
&lt;br /&gt;
The mode &amp;lt;code&amp;gt;expression&amp;lt;/code&amp;gt; allows you to define your own replacement syntax:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;        &lt;br /&gt;
attr mydevice replacement01Mode expression&lt;br /&gt;
attr mydevice replacement01Regex {{([^}]+)}}&lt;br /&gt;
attr mydevice replacement01Value ReadingsVal(&amp;quot;mydevice&amp;quot;, $1, &amp;quot;&amp;quot;)&lt;br /&gt;
attr mydevice getData {&amp;quot;get&amp;quot; :[&amp;quot;{{temp}}.value&amp;quot;]}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;      &lt;br /&gt;
&lt;br /&gt;
In this example any &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;{{name}}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; in a URL, header or post data will be passed on to the perl function ReadingsVal &lt;br /&gt;
which uses the string between &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;{{}}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; as second parameter. This way one defined replacement can be used for many different&lt;br /&gt;
readings.&lt;br /&gt;
&lt;br /&gt;
HTTPMOD has two built in replacements: One for session Ids and another one for the input value in a set command.&lt;br /&gt;
The placeholder $sid is always replaced with the internal &amp;lt;code&amp;gt;$hash-&amp;gt;{sid}&amp;lt;/code&amp;gt; which contains the session id after it is extracted from a previous HTTP response. &lt;br /&gt;
If you don&#039;t like to use the placeholder $sid then you can define your own replacement for example like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr mydevice replacement01Mode internal&lt;br /&gt;
attr mydevice replacement01Regex %session%&lt;br /&gt;
attr mydevice replacement01Value sid&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;      &lt;br /&gt;
&lt;br /&gt;
Now the internal &amp;lt;code&amp;gt;$hash-&amp;gt;{sid}&amp;lt;/code&amp;gt; will be used as a replacement for the placeholder %session%.&lt;br /&gt;
&lt;br /&gt;
In the same way a value that is passed to a set-command can be put into a request with a user defined replacement. &lt;br /&gt;
In this case the internal &amp;lt;code&amp;gt;$hash-&amp;gt;{value}&amp;lt;/code&amp;gt; will contain the value passed to the set command. &lt;br /&gt;
&amp;lt;code&amp;gt;$hash-&amp;gt;{value}&amp;lt;/code&amp;gt; might even be a string containing several values that could be put into several different positions in a request by using user defined replacements.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Other example : steering a pellet stove from Rika&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The stove API of Rika on https://www.rika-firenet.com/web/ delivers a JSON string with all settings and values, and can be piloted with a data string containing all the &amp;quot;set&amp;quot; values at once.&lt;br /&gt;
&lt;br /&gt;
Delivered JSON on get https://www.rika-firenet.com/api/client/xxxxxxxx/status : (xxxxxxxx must be replaced with the unique stove ID)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Vorzimmer&amp;quot;,&lt;br /&gt;
    &amp;quot;stoveID&amp;quot;: &amp;quot;xxxxxxxxx&amp;quot;,&lt;br /&gt;
    &amp;quot;lastSeenMinutes&amp;quot;: 1,&lt;br /&gt;
    &amp;quot;lastConfirmedRevision&amp;quot;: 1504385700,&lt;br /&gt;
    &amp;quot;controls&amp;quot;: {&lt;br /&gt;
        &amp;quot;revision&amp;quot;: 1504385700,&lt;br /&gt;
        &amp;quot;onOff&amp;quot;: true,&lt;br /&gt;
        &amp;quot;operatingMode&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;heatingPower&amp;quot;: 65,&lt;br /&gt;
        &amp;quot;targetTemperature&amp;quot;: 24,&lt;br /&gt;
        &amp;quot;heatingTimesActive&amp;quot;: false,&lt;br /&gt;
        &amp;quot;heatingTimesActiveForComfort&amp;quot;: true,&lt;br /&gt;
        &amp;quot;setBackTemperature&amp;quot;: 18,&lt;br /&gt;
        &amp;quot;convectionFan1Active&amp;quot;: false,&lt;br /&gt;
        &amp;quot;convectionFan1Level&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;convectionFan1Area&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;convectionFan2Active&amp;quot;: false,&lt;br /&gt;
        &amp;quot;convectionFan2Level&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;convectionFan2Area&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;frostProtectionActive&amp;quot;: false,&lt;br /&gt;
        &amp;quot;frostProtectionTemperature&amp;quot;: 5&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;sensors&amp;quot;: {&lt;br /&gt;
        &amp;quot;statusError&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;statusWarning&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;statusService&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;statusMainState&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;statusSubState&amp;quot;: 3,&lt;br /&gt;
        &amp;quot;statusFrostStarted&amp;quot;: false,&lt;br /&gt;
        &amp;quot;inputFlameTemperature&amp;quot;: 21,&lt;br /&gt;
        &amp;quot;inputRoomTemperature&amp;quot;: 21,&lt;br /&gt;
        &amp;quot;inputExternalRequest&amp;quot;: true,&lt;br /&gt;
        &amp;quot;outputDischargeMotor&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;outputInsertionMotor&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;outputIDFan&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;outputAirFlaps&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;outputIgnition&amp;quot;: false,&lt;br /&gt;
        &amp;quot;parameterStoveTypeNumber&amp;quot;: 13,&lt;br /&gt;
        &amp;quot;parameterVersionMainBoard&amp;quot;: 223,&lt;br /&gt;
        &amp;quot;parameterVersionTFT&amp;quot;: 223,&lt;br /&gt;
        &amp;quot;parameterRuntimePellets&amp;quot;: 11,&lt;br /&gt;
        &amp;quot;parameterRuntimeLogs&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;parameterFeedRateTotal&amp;quot;: 17,&lt;br /&gt;
        &amp;quot;parameterFeedRateService&amp;quot;: 683,&lt;br /&gt;
        &amp;quot;parameterOnOffCycles&amp;quot;: 2&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;stoveType&amp;quot;: &amp;quot;DOMO MultiAir&amp;quot;,&lt;br /&gt;
    &amp;quot;stoveFeatures&amp;quot;: {&lt;br /&gt;
        &amp;quot;multiAir1&amp;quot;: true,&lt;br /&gt;
        &amp;quot;multiAir2&amp;quot;: true,&lt;br /&gt;
        &amp;quot;insertionMotor&amp;quot;: false,&lt;br /&gt;
        &amp;quot;airFlaps&amp;quot;: false,&lt;br /&gt;
        &amp;quot;logRuntime&amp;quot;: false&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Data string to send to https://www.rika-firenet.com/api/client/xxxxxxxx/controls in order to set values:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
heatingTimesActiveForComfort=true&amp;amp;frostProtectionTemperature=3&amp;amp;setBackTemperature=18&amp;amp;targetTemperature=24&amp;amp;convectionFan2Level=0&amp;amp;convectionFan2Active=false&amp;amp;convectionFan1Level=0&amp;amp;onOff=true&amp;amp;convectionFan1Active=false&amp;amp;convectionFan2Area=0&amp;amp;revision=1505550101&amp;amp;heatingTimesActive=false&amp;amp;convectionFan1Area=0&amp;amp;frostProtectionActive=false&amp;amp;operatingMode=2&amp;amp;heatingPower=65&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Code in 99_myUtils.pm:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
use JSON;&lt;br /&gt;
...&lt;br /&gt;
sub&lt;br /&gt;
replaceJSON ($$) {&lt;br /&gt;
   my ($valToReplace, $value) = @_;&lt;br /&gt;
&lt;br /&gt;
   #$value in the parameters is a default value&lt;br /&gt;
   #It has to be replaced through the real value nnn passed in the set command &amp;quot;set &amp;lt;device&amp;gt; valToset nnn&amp;quot;&lt;br /&gt;
   $value = InternalVal(&amp;quot;Ofen&amp;quot;, &amp;quot;value&amp;quot;, $value);&lt;br /&gt;
   Log3 (&amp;quot;Ofen&amp;quot;, 3, &amp;quot;replaceJSON Internalvalue: $value&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
   #Force an update to avoid outdated revision number&lt;br /&gt;
   fhem (&amp;quot;get Ofen revision&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
   #Get all the controls as json&lt;br /&gt;
   my $json = ReadingsVal(&amp;quot;Ofen&amp;quot;, &amp;quot;controlsJSON&amp;quot;,&amp;quot;&amp;quot;);&lt;br /&gt;
   Log3 (&amp;quot;Ofen&amp;quot;, 3, &amp;quot;replaceJSON configsJSON: $json&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
   # When starting FHEM or rereading config, the reading controlsJSON is empty&lt;br /&gt;
   return if ($json eq &amp;quot;&amp;quot;); &lt;br /&gt;
&lt;br /&gt;
   my $decoded = decode_json($json);&lt;br /&gt;
   my $result;&lt;br /&gt;
   for my $key ( keys %$decoded ) {&lt;br /&gt;
      $result .= &amp;quot;$key=&amp;quot;;&lt;br /&gt;
      if ($key eq $valToReplace) {&lt;br /&gt;
         $result .= $value.&amp;quot;&amp;amp;&amp;quot;;&lt;br /&gt;
      } else {&lt;br /&gt;
         $result .= $decoded-&amp;gt;{$key}.&amp;quot;&amp;amp;&amp;quot;;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
   chop($result); #remove last &amp;amp;&lt;br /&gt;
   Log3(&amp;quot;Ofen&amp;quot;, 3, &amp;quot;replaceJSON Result: $result&amp;quot;);&lt;br /&gt;
   return $result;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Define stove in fhem:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod Ofen HTTPMOD https://www.rika-firenet.com/api/client/xxxxxxxx/status 60&lt;br /&gt;
&lt;br /&gt;
attr Ofen enableCookies 1&lt;br /&gt;
attr Ofen reAuthRegex id=&amp;quot;login&amp;quot;|Unauthorized&lt;br /&gt;
attr Ofen sid01Data email=xx@xx&amp;amp;password=xx&lt;br /&gt;
attr Ofen sid01URL https://www.rika-firenet.com/web/login&lt;br /&gt;
&lt;br /&gt;
attr Ofen reading01JSON sensors_inputRoomTemperature&lt;br /&gt;
attr Ofen reading01Name RaumTemp&lt;br /&gt;
attr Ofen reading02JSON controls_setBackTemperature&lt;br /&gt;
attr Ofen reading02Name Absenkung&lt;br /&gt;
attr Ofen reading03JSON controls_frostProtectionTemperature&lt;br /&gt;
attr Ofen reading03Name Frostschutz&lt;br /&gt;
attr Ofen reading10Name controlsJSON&lt;br /&gt;
attr Ofen reading10Regex (?s)controls.*?({.*?})&lt;br /&gt;
&lt;br /&gt;
attr Ofen get09Name revision&lt;br /&gt;
attr Ofen get09URL https://www.rika-firenet.com/api/client/xxxxxxxx/status&lt;br /&gt;
&lt;br /&gt;
attr Ofen setURL https://www.rika-firenet.com/api/client/xxxxxxxx/controls&lt;br /&gt;
attr Ofen setData {{data}}&lt;br /&gt;
attr Ofen replacement01Mode expression&lt;br /&gt;
attr Ofen replacement01Regex {{data}}&lt;br /&gt;
&lt;br /&gt;
attr Ofen set11Name frostProtectionTemperature&lt;br /&gt;
attr Ofen set11Replacement01Value replaceJSON(&amp;quot;frostProtectionTemperature&amp;quot;, 2)&lt;br /&gt;
&lt;br /&gt;
attr Ofen set12Name targetTemperature&lt;br /&gt;
attr Ofen set12Replacement01Value replaceJSON(&amp;quot;targetTemperature&amp;quot;, 24)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A detailed explanation (in german) of the login process can be found here: [https://forum.fhem.de/index.php/topic,76220.msg682514.html#msg682514]&lt;br /&gt;
and the explanation of the other parameters here: [https://forum.fhem.de/index.php/topic,76220.msg685710.html#msg685710]&lt;br /&gt;
&lt;br /&gt;
== replacing reading values when they have not been updated / the device did not respond ==&lt;br /&gt;
If a device does not respond then the values stored in readings will keep the same and only their timestamp shows that they are outdated. &lt;br /&gt;
If you want to modify reading values that have not been updated for a number of seconds, you can use the attributes&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;(reading|get)[0-9]*(-[0-9]+)?MaxAge&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;(reading|get)[0-9]*(-[0-9]+)?MaxAgeReplacementMode&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;(reading|get)[0-9]*(-[0-9]+)?MaxAgeReplacement&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Every time the module tries to read from a device, it will also check if readings have not been updated &lt;br /&gt;
for longer than the &amp;lt;code&amp;gt;MaxAge&amp;lt;/code&amp;gt; attributes allow. If readings are outdated, the &amp;lt;code&amp;gt;MaxAgeReplacementMode&amp;lt;/code&amp;gt; defines how the affected&lt;br /&gt;
reading values should be replaced. &amp;lt;code&amp;gt;MaxAgeReplacementMode&amp;lt;/code&amp;gt; can be &amp;lt;code&amp;gt;text&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;reading&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;internal&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;expression&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;delete&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;MaxAge&amp;lt;/code&amp;gt; specifies the number of seconds that a reading should remain untouched before it is replaced. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;MaxAgeReplacement&amp;lt;/code&amp;gt; contains either a static text that is used as replacement value or a Perl expression that is evaluated to &lt;br /&gt;
give the replacement value. This can be used for example to replace a temperature that has not bee updated for more than 5 minutes &lt;br /&gt;
with the string &amp;quot;outdated - was 12&amp;quot;:        &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr PM readingMaxAge 300&lt;br /&gt;
attr PM readingMaxAgeReplacement &amp;quot;outdated - was &amp;quot; . $val&lt;br /&gt;
attr PM readingMaxAgeReplacementMode expression&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The variable &amp;lt;code&amp;gt;$val&amp;lt;/code&amp;gt; contains the value of the reading before it became outdated.&lt;br /&gt;
&lt;br /&gt;
Or to show that a device was offline:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr MyLight reading01Name color&lt;br /&gt;
attr MyLight reading01JSON result_02_color&lt;br /&gt;
attr MyLight reading01MaxAge 300&lt;br /&gt;
attr MyLight reading01MaxAgeReplacement &amp;quot;offline&amp;quot;&lt;br /&gt;
attr MyLight reading01MaxAgeReplacementMode text&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Note on determining how to send requests to a special device ==&lt;br /&gt;
If you don&#039;t know which URLs, headers or POST data your web GUI uses, you might try a local proxy like BurpSuite [http://portswigger.net/burp/ BurpSuite] to track requests and responses. This is a tedious task but probably the best way to achieve a successful result. &lt;br /&gt;
&lt;br /&gt;
Let us consider an example. The Telekom Speedport W724V has a login-site that is famous for being cumbersome. Burp allows to monitor each step in the login procedure. In the case of a speedport the following steps occur:&lt;br /&gt;
&lt;br /&gt;
First burp shows that a get command is issued&lt;br /&gt;
 ################################################################################################## &lt;br /&gt;
 GET / HTTP/1.1&lt;br /&gt;
 Host: speedport.ip&lt;br /&gt;
 Cache-Control: max-age=0&lt;br /&gt;
 Upgrade-Insecure-Requests: 1&lt;br /&gt;
 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36&lt;br /&gt;
 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8&lt;br /&gt;
 Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4&lt;br /&gt;
 Cookie: lang=de&lt;br /&gt;
 Connection: close  &lt;br /&gt;
In order to mimic the behavior of a real person calling the website HTTPMOD should copy all necessary steps. Host, Cookie and the GET-command are usually necessary. The same cannot be said of the User-Agent because the website can be called from any mobile or desktop computer. &lt;br /&gt;
&lt;br /&gt;
Then, the speedport will answer with a command that consists of several lines. By going through every line for every step in the login procedure one will finally arrive at the information that is necessary to successfully enter the login of the speedport (in case of the W724V, for example, it is necessary to copy a token called _httoken and to include the referer).&lt;br /&gt;
&lt;br /&gt;
== Advanced configuration to define a &amp;lt;code&amp;gt;set&amp;lt;/code&amp;gt; command and send data to a device ==&lt;br /&gt;
       &lt;br /&gt;
When a set option is defined by attributes, the module will use the value given to the set command and integrate it into an HTTP-Request that sends the value to the device. The definitions for URL, headers and post data can contain the placeholder $val which will be replaced by the (numerical) value given to the set command.&lt;br /&gt;
&lt;br /&gt;
This can be as simple as:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
# No cyclic requests and no main URL needed in this example&lt;br /&gt;
define MyDevice HTTPMOD none 0&lt;br /&gt;
&lt;br /&gt;
attr MyDevice set01Name Licht&lt;br /&gt;
attr MyDevice set01URL http://192.168.1.22/switch=$val&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A user command &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
set MyDevice Licht 1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
will be translated into the http GET request&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
http://192.168.1.22/switch=1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example a map would also be helpful, that translates on / off to 0 or 1 and allows the user to select on/of in fhemweb:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr MyDevive set01IMap 0:off, 1:on&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
This also provides input validation to make sure that only on and off can be used with the set command.&lt;br /&gt;
&lt;br /&gt;
In more complex Scenarios you might need to login before sending a command and the Login might create a session id that has to be part of further requests either in the URL, in headers or in the post data.&lt;br /&gt;
&lt;br /&gt;
Extension to the above example for a PoolManager 5 where a set needs a session id in the URL and the values have to be passed in JSON strings as post data:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr PM set01Name HeizungSoll&lt;br /&gt;
attr PM set01URL http://MyPoolManager/cgi-bin/webgui.fcgi?sid=$sid&lt;br /&gt;
attr PM set01Hint 6,10,20,30&lt;br /&gt;
attr PM set01Min 6&lt;br /&gt;
attr PM set01Max 30&lt;br /&gt;
attr PM setHeader1 Content-Type: application/json&lt;br /&gt;
attr PM set01Data {&amp;quot;set&amp;quot; :{&amp;quot;34.3118.value&amp;quot; :&amp;quot;$val&amp;quot; }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example defines a set option with the name HeizungSoll.&lt;br /&gt;
By issuing &amp;lt;code&amp;gt;set PM HeizungSoll 10&amp;lt;/code&amp;gt; in FHEM, the value 10 will be sent in the defined HTTP&lt;br /&gt;
Post to URL &amp;lt;code&amp;gt;http://MyPoolManager/cgi-bin/webgui.fcgi&amp;lt;/code&amp;gt; in the Post Data as&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
{&amp;quot;set&amp;quot; :{&amp;quot;34.3118.value&amp;quot; :&amp;quot;10&amp;quot; }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The optional attributes set01Min and set01Max define input validations that will be checked in the set function. &lt;br /&gt;
The optional attribute set01Hint will define a selection list for the FHEMweb GUI.&lt;br /&gt;
&lt;br /&gt;
The HTTP response to such a request will be ignored unless you specify the attribute &amp;lt;code&amp;gt;setParseResponse&amp;lt;/code&amp;gt; &lt;br /&gt;
for all set commands or &amp;lt;code&amp;gt;set01ParseResponse&amp;lt;/code&amp;gt; for the set command with number 01.&lt;br /&gt;
If the HTTP response to a set command is parsed then this is done like the parsing of responses to get commands and you can use the attributes ending e.g. on Format, Encode, Decode, OMap and OExpr to manipulate / format the values read.&lt;br /&gt;
&lt;br /&gt;
If a parameter to a set command is not numeric but should be passed on to the device as text, then you can specify the attribute setTextArg. For example: &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr PM set01TextArg&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If a set command should not require a parameter at all, then you can specify the attribute NoArg. For example: &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr PM set03Name On&lt;br /&gt;
attr PM set03NoArg&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Advanced configuration to create a valid session id that might be necessary ==&lt;br /&gt;
In simple cases logging in works with basic authentication. In the case HTTPMOD accepts a username and password as part of the URL in the form &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
http://User:Password@192.168.1.18/something&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
However basic auth is seldom used. If you need to fill in a username and password in a HTML form and the session is then managed by a session id, here is how to configure this:&lt;br /&gt;
&lt;br /&gt;
when sending data to an HTTP-Device in a set, HTTPMOD will replace any &amp;lt;code&amp;gt;$sid&amp;lt;/code&amp;gt; in the URL, Headers and Post data with the internal &amp;lt;code&amp;gt;$hash-&amp;gt;{sid}&amp;lt;/code&amp;gt;. To authenticate towards the device and give this internal a value, you can use an optional multi step login procedure defined by the following attributes: &lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;sid[0-9]*URL&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;sid[0-9]*Data.*&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;sid[0-9]*Header.*&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;sid[0-9]*IgnoreRedirects&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;idRegex&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;idJSON&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;idXPath&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;idXPath-Strict&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;(get|set|sid)[0-9]*IdRegex&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;(get|set|sid)[0-9]*IdJSON&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;(get|set|sid)[0-9]*IdXPath&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;(get|set|sid)[0-9]*IdXPath-Strict&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Each step can have a URL, Headers, Post Data pieces and a Regex to extract a resulting Session ID into &amp;lt;code&amp;gt;$hash-&amp;gt;{sid}&amp;lt;/code&amp;gt;.&lt;br /&gt;
HTTPMOD will create a sorted list of steps (the numbers between sid and URL / Data / Header) and the loop through these steps and send the corresponding requests to the device. For each step a $sid in a Header or Post Data will be replaced with the current content of &amp;lt;code&amp;gt;$hash-&amp;gt;{sid}&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Using this feature, HTTPMOD can perform a forms based authentication and send user name, password or other necessary data to the device and save the session id for further requests.&lt;br /&gt;
        &lt;br /&gt;
To determine when this login procedure is necessary, HTTPMOD will first try to send a request without &lt;br /&gt;
doing the login procedure. If the result contains an error that authentication is necessary, then a login is performed. &lt;br /&gt;
To detect such an error in the HTTP response, you can again use a regular expression, JSON or XPath, this time with the attributes &lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;reAuthRegex&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;reAuthJSON&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;reAuthXPath&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;reAuthXPath-Strict&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;(get|set)[0-9]*ReAuthRegex&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;(get|set)[0-9]*ReAuthJSON&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;(get|set)[0-9]*ReAuthXPath&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;(get|set)[0-9]*ReAuthXPath-Strict&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
reAuthJSON or reAuthXPath typically only extract one piece of data from a response. &lt;br /&gt;
If the existence of the specified piece of data is sufficent to start a login procedure, then nothing more needs to be defined to detect this situation. &lt;br /&gt;
If however the indicator is a status code that contains different values depending on a successful request and a failed request if a new authentication is needed, &lt;br /&gt;
then you can combine things like reAuthJSON with reAuthRegex. In this case the regex is only matched to the data extracted by JSON (or XPath). &lt;br /&gt;
This way you can easily extract the status code using JSON parsing and then specify the code that means &amp;quot;authentication needed&amp;quot; as a regular expression.&lt;br /&gt;
        &lt;br /&gt;
If for one step not all of the URL, Data or Header Attributes are set, then HTTPMOD tries to use a &lt;br /&gt;
&amp;lt;code&amp;gt;sidURL&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;sidData.*&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;sidHeader.*&amp;lt;/code&amp;gt; Attribute (without the step number after sid). This way parts that are the same for all steps don&#039;t need to be defined redundantly.&lt;br /&gt;
&lt;br /&gt;
=== Example for a multi step login procedure: ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr PM reAuthRegex /html/dummy_login.htm &lt;br /&gt;
attr PM sidURL http://192.168.70.90/cgi-bin/webgui.fcgi?sid=$sid&lt;br /&gt;
attr PM sidHeader1 Content-Type: application/json&lt;br /&gt;
attr PM sid1IDRegex wui.init\(&#039;([^&#039;]+)&#039;&lt;br /&gt;
attr PM sid2Data {&amp;quot;set&amp;quot; :{&amp;quot;9.17401.user&amp;quot; :&amp;quot;fhem&amp;quot; ,&amp;quot;9.17401.pass&amp;quot; :&amp;quot;password&amp;quot; }}&lt;br /&gt;
attr PM sid3Data {&amp;quot;set&amp;quot; :{&amp;quot;35.5062.value&amp;quot; :&amp;quot;128&amp;quot; }}&lt;br /&gt;
attr PM sid4Data {&amp;quot;set&amp;quot; :{&amp;quot;42.8026.code&amp;quot; :&amp;quot;pincode&amp;quot; }}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this case HTTPMOD detects that a login is necessary by looking for the pattern /html/dummy_login.htm in the HTTP response. &lt;br /&gt;
If it matches, it starts a login sequence. In the above example all steps request the same URL. In step 1 only the defined Header is sent in an HTTP get request. The response will contain a session id that is extraced with the regex wui.init\(&#039;([^&#039;]+)&#039;.&lt;br /&gt;
&lt;br /&gt;
In the next step this session id is sent in a post request to the same URL where tha post data contains a username and password. The a third and a fourth request follow that set a value and a code. The result will be a valid and authorized session id that can be used in other requests where $sid is part of a URL, header or post data and will be replaced with the session id extracted above.&lt;br /&gt;
&lt;br /&gt;
===Another Practical Example reading the SOC from a Renault Zoe===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
define myZoe HTTPMOD https://www.services.renault-ze.com/api/vehicle/VINVINVIN/battery 7000&lt;br /&gt;
attr myZoe userattr reading01JSON reading01Name reading02JSON reading02Name reading03JSON reading03Nam\&lt;br /&gt;
e reading04JSON reading04Name reading05JSON reading05Name requestHeader02 sid1Data sid1Header01 sid1Id\&lt;br /&gt;
JSON sid1IgnoreRedirects:0,1 sid1URL&lt;br /&gt;
attr myZoe reAuthJSON message&lt;br /&gt;
attr myZoe reading01JSON charge_level&lt;br /&gt;
attr myZoe reading01Name SOC&lt;br /&gt;
attr myZoe reading02JSON charging&lt;br /&gt;
attr myZoe reading02Name charging&lt;br /&gt;
attr myZoe reading03JSON plugged&lt;br /&gt;
attr myZoe reading03Name plugged&lt;br /&gt;
attr myZoe reading04JSON remaining_range&lt;br /&gt;
attr myZoe reading04Name remaining_range&lt;br /&gt;
attr myZoe reading05JSON last_update&lt;br /&gt;
attr myZoe reading05Name last_update&lt;br /&gt;
attr myZoe requestHeader02 Authorization: Bearer $sid&lt;br /&gt;
attr myZoe sid1Data {&amp;quot;username&amp;quot;:&amp;quot;ZEUSERNAME&amp;quot;,&amp;quot;password&amp;quot;:&amp;quot;ZEPASSWORD&amp;quot;}&lt;br /&gt;
attr myZoe sid1Header01 Content-Type: application/json&lt;br /&gt;
attr myZoe sid1IdJSON token&lt;br /&gt;
attr myZoe sid1IgnoreRedirects 1&lt;br /&gt;
attr myZoe sid1URL https://www.services.renault-ze.com/api/user/login&lt;br /&gt;
attr myZoe timeout 10&lt;br /&gt;
#attr myZoe verbose 7&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The $sid is read by logging in with username and password from JSON {&amp;quot;token&amp;quot;: ..} after detecting an error {&amp;quot;message&amp;quot;: ..}  from a failed request. This example offers no solution for the reading of the VIN from the login request, which in turn is part of the reading URL. It should be possible to read more than just the $sid from the login sequence.&lt;br /&gt;
&lt;br /&gt;
In the special case where a session id is set as a HTTP-Cookie (with the header Set-cookie: in the HTTP response) HTTPMOD offers an even simpler way. With the attribute enableCookies a very basic cookie handling mechanism is activated that stores all cookies that the server sends to the HTTPMOD device and puts them back as cookie headers in the following requests.&lt;br /&gt;
&lt;br /&gt;
For such cases no sidIdRegex and no $sid in a user defined header is necessary.&lt;br /&gt;
&lt;br /&gt;
== Advanced configuration to define a &amp;lt;code&amp;gt;get&amp;lt;/code&amp;gt; and request additional data with its own request from a device ==&lt;br /&gt;
&lt;br /&gt;
The normal automatic HTTP request that is done repeatedly after the defined interval has elapsed works well in cases where all required readings can be requested in one common HTTP request. If however a device needs individual requests with different URLs or different POST data for each value, then another method is necessary. &lt;br /&gt;
For such cases a &amp;lt;code&amp;gt;get&amp;lt;/code&amp;gt; option can be defined and the user can either issue FHEM &amp;lt;code&amp;gt;get&amp;lt;/code&amp;gt; commands each time he needs the reading or the user can set an attribute to request the reading automatically together with the normal iteration.&lt;br /&gt;
For each &amp;lt;code&amp;gt;get&amp;lt;/code&amp;gt; option attributes define an individual URL, optional headers, and post data as well as individual regular expressions and formatting options. &lt;br /&gt;
&lt;br /&gt;
When a get option is defined by attributes, the module allows querying additional values from the device that require individual HTTP-Requests or special parameters to be sent&lt;br /&gt;
&lt;br /&gt;
Extension to the above example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr PM get01Name MyGetValue &lt;br /&gt;
attr PM get01URL http://MyPoolManager/cgi-bin/directory/webgui.fcgi?special=1?sid=$sid &lt;br /&gt;
attr PM getHeader1 Content-Type: application/json &lt;br /&gt;
attr PM get01Data {&amp;quot;get&amp;quot; :{&amp;quot;30.1234.value&amp;quot;}} &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example defines a get option with the name MyGetValue.&lt;br /&gt;
By issuing &amp;lt;code&amp;gt;get PM MyGetValue&amp;lt;/code&amp;gt; in FHEM, the defined HTTP request is sent to the device.&lt;br /&gt;
The HTTP response is then parsed using the same readingXXName and readingXXRegex attributes as above so&lt;br /&gt;
additional pairs will probably be needed there for additional values.&lt;br /&gt;
&lt;br /&gt;
if you prefer to define the parsing and formatting of readings individually per get command, you can use &lt;br /&gt;
attributes like get01Regex, get01XPath, get01Format, get01OMap and so on just like for reading01...&lt;br /&gt;
&lt;br /&gt;
You can also include parameters / values that are passed to the get command in the request just like for set commands.&lt;br /&gt;
The placeholder $val will be replaced with the value given to the get command or you can specify your own replacement as described above.&lt;br /&gt;
&lt;br /&gt;
If the new get parameter should also be queried regularly, you can define the following optional attributes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr PM get01Poll 1&lt;br /&gt;
attr PM get01PollDelay 300&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first attribute includes this reading in the automatic update cycle and the second defines an alternative lower update frequency. When the interval defined initially in the define is over and the normal readings are read from the device, the update function will check for additional get parameters that should be included in the update cycle.&lt;br /&gt;
&lt;br /&gt;
If a PollDelay is specified for a get parameter, the update function also checks if the time passed since it has last read this value is more than the given PollDelay. If not, this reading is skipped and it will be rechecked in the next cycle when interval is over again. So the effective PollDelay will always be a multiple of the interval specified in the initial define.&lt;br /&gt;
&lt;br /&gt;
Please note that each defined get command that is included in the regular update cycle will create its own HTTP request. So if you want to extract several values from the same request, it is much more efficient to do this by defining readingXXName and readingXXRegex, XPath or JSON attributes and to specify an interval and a URL in the define of the HTTPMOD device. &lt;br /&gt;
&lt;br /&gt;
Example for a Siemens webserver provided by Lanhydrock:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
define ozw672 HTTPMOD https://192.168.178.8/api/auth/login.json?user=test&amp;amp;pwd=test 300&lt;br /&gt;
&lt;br /&gt;
attr ozw672 get1Name tempAussen&lt;br /&gt;
attr ozw672 get1URL https://192.168.178.8/api/menutree/read_datapoint.json?SessionId=$sid&amp;amp;Id=1960&lt;br /&gt;
attr ozw672 get1Poll 1&lt;br /&gt;
attr ozw672 get1PollDelay 1800&lt;br /&gt;
&lt;br /&gt;
attr ozw672 get2Name tempAussenGemischt&lt;br /&gt;
attr ozw672 get2URL https://192.168.178.8/api/menutree/read_datapoint.json?SessionId=$sid&amp;amp;Id=1964&lt;br /&gt;
attr ozw672 get2Poll 1&lt;br /&gt;
attr ozw672 get2PollDelay 1800&lt;br /&gt;
&lt;br /&gt;
attr ozw672 get3Name tempTWW&lt;br /&gt;
attr ozw672 get3URL https://192.168.178.8/api/menutree/read_datapoint.json?SessionId=$sid&amp;amp;Id=1996&lt;br /&gt;
attr ozw672 get3Poll 1&lt;br /&gt;
&lt;br /&gt;
attr ozw672 get4Name tempKesselSoll&lt;br /&gt;
attr ozw672 get4URL https://192.168.178.8/api/menutree/read_datapoint.json?SessionId=$sid&amp;amp;Id=1910&lt;br /&gt;
attr ozw672 get4Poll 1&lt;br /&gt;
&lt;br /&gt;
attr ozw672 get5Name tempKesselRuecklauf&lt;br /&gt;
attr ozw672 get5URL https://192.168.178.8/api/menutree/read_datapoint.json?SessionId=$sid&amp;amp;Id=1915&lt;br /&gt;
attr ozw672 get5Poll 1&lt;br /&gt;
&lt;br /&gt;
attr ozw672 get6Name tempKesselRuecklaufSoll&lt;br /&gt;
attr ozw672 get6URL https://192.168.178.8/api/menutree/read_datapoint.json?SessionId=$sid&amp;amp;Id=1916&lt;br /&gt;
attr ozw672 get6Poll 1&lt;br /&gt;
&lt;br /&gt;
attr ozw672 get7Name anzahlStartsBrenner&lt;br /&gt;
attr ozw672 get7URL https://192.168.178.8/api/menutree/read_datapoint.json?SessionId=$sid&amp;amp;Id=1927&lt;br /&gt;
attr ozw672 get7PollDelay 1800&lt;br /&gt;
attr ozw672 get7Poll 1&lt;br /&gt;
&lt;br /&gt;
attr ozw672 get8Name statusKessel&lt;br /&gt;
attr ozw672 get8URL https://192.168.178.8/api/menutree/read_datapoint.json?SessionId=$sid&amp;amp;Id=1898&lt;br /&gt;
attr ozw672 get8Poll 1&lt;br /&gt;
attr ozw672 get8Regex Value&amp;quot;: &amp;quot;([a-zA-Zü ]*)&amp;quot;&lt;br /&gt;
attr ozw672 get8OMap Aus:0, Nachlauf aktiv:5, Freigegeben für TWW:10, Freigegeben für HK:20, In Teillastbetrieb für TWW:40, In Teillastbetrieb für HK:50, In Betrieb für Trinkwasser:90, In Betrieb für Heizkreis:100&lt;br /&gt;
&lt;br /&gt;
attr ozw672 getRegex Value&amp;quot;: &amp;quot;[ ]*([-.0-9]*)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
attr ozw672 reAuthRegex .*session not valid.*&lt;br /&gt;
attr ozw672 sid1IDRegex .*&amp;quot;(.*-.*-.*-[0-9a-z]*).*&lt;br /&gt;
attr ozw672 sid1URL https://192.168.178.8/api/auth/login.json?user=test&amp;amp;pwd=test&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== All attributes ==&lt;br /&gt;
;reading[0-9]+Name&lt;br /&gt;
:the name of a reading to extract with the corresponding readingRegex, readingJSON, readingXPath or readingXPath-Strict&lt;br /&gt;
:Please note that the old syntax &amp;lt;b&amp;gt;readingsName.*&amp;lt;/b&amp;gt; does not work with all features of HTTPMOD and should be avoided. It might go away in a future version of HTTPMOD.&lt;br /&gt;
&lt;br /&gt;
;(get|set)[0-9]+Name&lt;br /&gt;
:Name of a get or set command&lt;br /&gt;
:If the HTTP response that is received after the command is parsed with an individual parse option then this name is also used as a reading name. Please note that no individual parsing needs to be defined for a get or set. If no regex, XPath or JSON is specified for the command, then HTTPMOD will try to parse the response using all the defined readingRegex, reading XPath or readingJSON attributes.&lt;br /&gt;
&lt;br /&gt;
;(get|set|reading)[0-9]+Regex&lt;br /&gt;
:If this attribute is specified, the Regex defined here is used to extract the value from the HTTP Response and assign it to a Reading with the name defined in the (get|set|reading)[0-9]+Name attribute.&lt;br /&gt;
:If this attribute is not specified for an individual Reading or get or set but without the numbers in the middle, e.g. as getRegex or readingRegex, then it applies to all the other readings / get / set commands where no specific Regex is defined.&amp;lt;br&amp;gt;&lt;br /&gt;
:The value to extract should be in a capture group / sub expression e.g. ([\d\.]+) in the above example. Multiple capture groups will create multiple readings (see explanation above)&lt;br /&gt;
:Using this attribute for a set command (setXXRegex) only makes sense if you want to parse the HTTP response to the HTTP request that the set command sent by defining the attribute setXXParseResponse.&lt;br /&gt;
:Please note that the old syntax &amp;lt;code&amp;gt;readingsRegex.*&amp;lt;/code&amp;gt; does not work with all features of HTTPMOD and should be avoided. It might go away in a future version of HTTPMOD.&lt;br /&gt;
:If for get or set commands neither a generic Regex attribute without numbers nor a specific (get|set)[0-9]+Regex attribute is specified and also no XPath or JSON parsing specification is given for the get or set command, then HTTPMOD tries to use the parsing definitions for general readings defined in reading[0-9]+Name, reading[0-9]+Regex or XPath or JSON attributes and assigns the Readings that match here.&lt;br /&gt;
&lt;br /&gt;
;(get|set|reading)[0-9]+RegOpt&lt;br /&gt;
:Lets the user specify regular expression modifiers. For example if the same regular expression should be matched as often as possible in the HTTP response, then you can specify RegOpt g which will case the matching to be done as /regex/g&lt;br /&gt;
:The results will be trated the same way as multiple capture groups so the reading name will be extended with -number. &lt;br /&gt;
:For other possible regular expression modifiers see http://perldoc.perl.org/perlre.html#Modifiers&lt;br /&gt;
&lt;br /&gt;
;(get|set|reading)[0-9]+XPath&lt;br /&gt;
:defines an xpath to one or more values when parsing HTML data (see examples above)&lt;br /&gt;
:Using this attribute for a set command only makes sense if you want to parse the HTTP response to the HTTP request that the set command sent by defining the attribute setXXParseResponse.&lt;br /&gt;
&lt;br /&gt;
;get|set|reading[0-9]+XPath-Strict&lt;br /&gt;
:defines an xpath to one or more values when parsing XML data (see examples above)&lt;br /&gt;
:Using this attribute for a set command only makes sense if you want to parse the HTTP response to the HTTP request that the set command sent by defining the attribute setXXParseResponse.&lt;br /&gt;
&lt;br /&gt;
;(get|set|reading)[0-9]+AutoNumLen&lt;br /&gt;
:In cases where a regular expression or an XPath results in multiple results and these results are stored in a common reading name with extension -number, then you can modify the format of this number to have a fixed length with leading zeros. AutoNumLen 3 for example will lead to reading names ending with -001 -002 and so on.&lt;br /&gt;
&lt;br /&gt;
;(get|set|reading)[0-9]+AlwaysNum&lt;br /&gt;
:if set to 1 this attributes forces reading names to end with a -1, -01 (depending on the above described AutoNumLen) even if just one value is parsed.&lt;br /&gt;
&lt;br /&gt;
;get|set|reading[0-9]+JSON&lt;br /&gt;
:defines a path to the JSON object wanted by concatenating the object names. See the above example.&lt;br /&gt;
:If you don&#039;t know the paths, then start by using extractAllJSON and the use the names of the readings as values for the JSON attribute.&amp;lt;br&amp;gt;&lt;br /&gt;
:Please don&#039;t forget to also specify a name for a reading, get or set. &lt;br /&gt;
:Using this attribute for a set command only makes sense if you want to parse the HTTP response to the HTTP request that the set command sent by defining the attribute setXXParseResponse.&lt;br /&gt;
&lt;br /&gt;
;(get|set|reading)[0-9]*RecombineExpr&lt;br /&gt;
:defines an expression that is used in an eval to compute one reading value out of the list of matches.&lt;br /&gt;
:This is supposed to be used for regexes or xpath specifications that produce multiple results if only one result that combines them is wanted. The list of matches will be in the variable @matchlist.&lt;br /&gt;
:Using this attribute for a set command only makes sense if you want to parse the HTTP response to the HTTP request that the set command sent by defining the attribute setXXParseResponse.&lt;br /&gt;
&lt;br /&gt;
;get[0-9]*CheckAllReadings&lt;br /&gt;
:this attribute modifies the behavior of HTTPMOD when the HTTP Response of a get command is parsed. &amp;lt;br&amp;gt;&lt;br /&gt;
:If this attribute is set to 1, then additionally to the matching of the corresponding get specific regex (get[0-9]*Regex), XPath or JSON attribute also all the reading names and parse definitions defined in Reading[0-9]+Name and Reading[0-9]+Regex, XPath or JSON attributes are checked and if they match, the coresponding Readings are assigned as well.&lt;br /&gt;
:Please note that this does not mean that get01CheckAllReadings will cause a get02Regex to be used. Only the corresponding get01Regex will be used but additionally all the readingXYRegex attributes.&lt;br /&gt;
:This is automatically done if a get or set command is defined without its own parse attributes.&lt;br /&gt;
&lt;br /&gt;
;(get|reading)[0-9]*OExpr&lt;br /&gt;
:defines an optional expression that is used in an eval to compute / format a readings value after parsing an HTTP response&lt;br /&gt;
:The raw value from the parsing will be in the variable $val.&lt;br /&gt;
:If specified as readingOExpr then the attribute value is a default for all other readings that don&#039;t specify an explicit reading[0-9]*Expr.&lt;br /&gt;
:Please note that the old syntax &amp;lt;b&amp;gt;readingsExpr.*&amp;lt;/b&amp;gt; does not work with all features of HTTPMOD and should be avoided. It might go away in a future version of HTTPMOD.&lt;br /&gt;
&lt;br /&gt;
;(get|reading)[0-9]*Expr&lt;br /&gt;
:This is the old syntax for (get|reading)[0-9]*OExpr. It should be replaced by (get|reading)[0-9]*OExpr. The set command upgradeAttributes which becomes visible when the attribute enableControlSet is set to 1, can do this renaming automatically.&lt;br /&gt;
&lt;br /&gt;
;(get|reading)[0-9]*OMap&lt;br /&gt;
:Map that defines a mapping from raw value parsed to visible values like &amp;quot;0:mittig, 1:oberhalb, 2:unterhalb&amp;quot;.&lt;br /&gt;
:If specified as readingOMap then the attribute value is a default for all other readings that don&#039;t specify an explicit reading[0-9]*Map.&amp;lt;br&amp;gt;&lt;br /&gt;
:The individual options in a map are separated by a komma and an optional space. Spaces are allowed to appear in a visible value however kommas are not possible.&lt;br /&gt;
&lt;br /&gt;
;(get|reading)[0-9]*Map&lt;br /&gt;
:This is the old syntax for (get|reading)[0-9]*OMap. It should be replaced by (get|reading)[0-9]*OMap. The set command upgradeAttributes which becomes visible when the attribute enableControlSet is set to 1, can do this renaming automatically.&lt;br /&gt;
&lt;br /&gt;
;(get|set|reading)[0-9]*Format&lt;br /&gt;
:Defines a format string that will be used in sprintf to format a reading value.&lt;br /&gt;
:If specified without the numbers in the middle e.g. as readingFormat then the attribute value is a default for all other readings that don&#039;t specify an explicit reading[0-9]*Format.&lt;br /&gt;
:Using this attribute for a set command only makes sense if you want to parse the HTTP response to the HTTP request that the set command sent by defining the attribute setXXParseResponse.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;(get|set|reading)[0-9]*Decode&lt;br /&gt;
:defines an encoding to be used in a call to the perl function decode to convert the raw data string read from the device to a reading. &lt;br /&gt;
:This can be used if the device delivers strings in an encoding like cp850 instead of utf8.&lt;br /&gt;
:If your reading values contain Umlauts and they are shown as strange looking icons then you probably need to use this feature.&lt;br /&gt;
:Using this attribute for a set command only makes sense if you want to parse the HTTP response to the HTTP request that the set command sent by defining the attribute setXXParseResponse.&lt;br /&gt;
&lt;br /&gt;
;(get|set|reading)[0-9]*Encode&lt;br /&gt;
:defines an encoding to be used in a call to the perl function encode to convert the raw data string read from the device to a reading. &lt;br /&gt;
:This can be used if the device delivers strings in an encoding like cp850 and after decoding it you want to reencode it to e.g. utf8.&lt;br /&gt;
:If your reading values contain Umlauts and they are shown as strange looking icons then you probably need to use this feature.&lt;br /&gt;
:Using this attribute for a set command only makes sense if you want to parse the HTTP response to the HTTP request that the set command sent by defining the attribute setXXParseResponse.&lt;br /&gt;
&lt;br /&gt;
;(get|set)[0-9]*URL&lt;br /&gt;
:URL to be requested for the set or get command. If this option is missing, the URL specified during define will be used.&lt;br /&gt;
&lt;br /&gt;
;(get|set)[0-9]*Data&lt;br /&gt;
:Data to be sent to the device as POST data when the get or set command is executed. if this attribute is not specified, an HTTP GET method will be used instead of an HTTP POST&lt;br /&gt;
&lt;br /&gt;
;(get|set)[0-9]*NoData&lt;br /&gt;
:can be used to override a more generic attribute that specifies POST data for all get or set commands. With NoData no data is sent and therefor the request will be an HTTP GET.&lt;br /&gt;
&lt;br /&gt;
;(get|set)[0-9]*Header.*&lt;br /&gt;
:HTTP Headers to be sent to the device when the set is executed&lt;br /&gt;
&lt;br /&gt;
;requestHeader.*&lt;br /&gt;
:Define an optional additional HTTP Header to set in the HTTP request of the main loop&lt;br /&gt;
&lt;br /&gt;
;requestData&lt;br /&gt;
:optional POST Data to be sent in the request of the main loop. If not defined, it will be an HTTP GET request as defined in HttpUtils which is used by this module&lt;br /&gt;
&lt;br /&gt;
;get[0-9]+Poll&lt;br /&gt;
:if set to 1 the get is executed automatically during the normal update cycle (after the interval provided in the define command has elapsed)&lt;br /&gt;
&lt;br /&gt;
;get[0-9]+PollDelay&lt;br /&gt;
:if the value should not be read in each iteration (after the interval given to the define command), then a minimum delay can be specified with this attribute. This has only an effect if the above Poll attribute has also been set. Every time the update function is called, it checks if since this get has been read the last time, the defined delay has elapsed. If not, then it is skipped this time.&lt;br /&gt;
:PollDelay can be specified as seconds or as x[0-9]+ which means a multiple of the interval in the define command.&lt;br /&gt;
&lt;br /&gt;
;(get|set)[0-9]*TextArg&lt;br /&gt;
:For a get command this defines that the command accepts a text value after the option name. By default a get command doesn&#039;t accept optional values after the command name. &lt;br /&gt;
:If TextArg is specified and a value is passed after the get name then this value can then be used in a request URL, header or data as replacement for $val or in a user defined replacement that uses the internal &amp;quot;value&amp;quot; ($hash-&amp;gt;{value}).&lt;br /&gt;
:If used for a set command then it defines that the value to be set doesn&#039;t require any validation / conversion. &lt;br /&gt;
:The raw value is passed on as text to the device. By default a set command expects a numerical value or a text value that is converted to a numeric value using a map.&lt;br /&gt;
&lt;br /&gt;
;set[0-9]+Min&lt;br /&gt;
:Minimum value for input validation. &lt;br /&gt;
&lt;br /&gt;
;set[0-9]+Max&lt;br /&gt;
:Maximum value for input validation. &lt;br /&gt;
&lt;br /&gt;
;set[0-9]+IExpr&lt;br /&gt;
:Perl Expression to compute the raw value to be sent to the device from the input value passed to the set.&lt;br /&gt;
&lt;br /&gt;
;set[0-9]+Expr&lt;br /&gt;
:This is the old syntax for (get|reading)[0-9]*IExpr. It should be replaced by (get|reading)[0-9]*IExpr. The set command upgradeAttributes which becomes visible when the attribute enableControlSet is set to 1, can do this renaming automatically.&lt;br /&gt;
&lt;br /&gt;
;set[0-9]+IMap&lt;br /&gt;
:Map that defines a mapping from raw to input values like &amp;quot;0:mittig, 1:oberhalb, 2:unterhalb&amp;quot;. This attribute atomatically creates a hint for FHEMWEB so the user can choose one of the input values.&lt;br /&gt;
&lt;br /&gt;
;set[0-9]+Map&lt;br /&gt;
:This is the old syntax for (get|reading)[0-9]*IMap. It should be replaced by (get|reading)[0-9]*IMap. The set command upgradeAttributes which becomes visible when the attribute enableControlSet is set to 1, can do this renaming automatically.&lt;br /&gt;
&lt;br /&gt;
;set[0-9]+Hint&lt;br /&gt;
:Explicit hint for fhemWEB that will be returned when set ? is seen. Can be used to get a slider or a list of values to choose from.&lt;br /&gt;
&lt;br /&gt;
;set[0-9]*NoArg&lt;br /&gt;
:Defines that this set option doesn&#039;t require arguments. It allows sets like &amp;quot;on&amp;quot; or &amp;quot;off&amp;quot; without further values.&lt;br /&gt;
&lt;br /&gt;
;set[0-9]*ParseResponse&lt;br /&gt;
:defines that the HTTP response to the set will be parsed as if it was the response to a get command.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;(get|set)[0-9]*URLExpr&lt;br /&gt;
:Defines a Perl expression to specify the HTTP Headers for this request. This overwrites any other header specification and should be used carefully only if needed. The original Header is availabe as $old. Typically this feature is not needed and it might go away in future versions of HTTPMOD. Please use the &amp;quot;replacement&amp;quot; attributes if you want to pass additional variable data to a web service. &lt;br /&gt;
&lt;br /&gt;
;(get|set)[0-9]*DatExpr&lt;br /&gt;
:Defines a Perl expression to specify the HTTP Post data for this request. This overwrites any other post data specification and should be used carefully only if needed. The original Data is availabe as $old. Typically this feature is not needed and it might go away in future versions of HTTPMOD. Please use the &amp;quot;replacement&amp;quot; attributes if you want to pass additional variable data to a web service. &lt;br /&gt;
&lt;br /&gt;
;(get|set)[0-9]*HdrExpr&lt;br /&gt;
:Defines a Perl expression to specify the URL for this request. This overwrites any other URL specification and should be used carefully only if needed. The original URL is availabe as $old. Typically this feature is not needed and it might go away in future versions of HTTPMOD. Please use the &amp;quot;replacement&amp;quot; attributes if you want to pass additional variable data to a web service.           &lt;br /&gt;
&lt;br /&gt;
;ReAuthRegex&lt;br /&gt;
:regular Expression to match an error page indicating that a session has expired and a new authentication for read access needs to be done. &lt;br /&gt;
:This attribute only makes sense if you need a forms based authentication for reading data and if you specify a multi step login procedure based on the sid.. attributes.&lt;br /&gt;
:This attribute is used for all requests. For set and get operations you can however specify individual reAuthRegexes with the (get|set)[0-9]*ReAuthRegex attributes.&lt;br /&gt;
&lt;br /&gt;
;(get|set)[0-9]*ReAuthRegex&lt;br /&gt;
:Regex that will detect when a session has expired during a set operation and a new login needs to be performed.&lt;br /&gt;
:It works like the global reAuthRegex but is used for set operations.&lt;br /&gt;
&lt;br /&gt;
;sid[0-9]*URL&lt;br /&gt;
:different URLs or one common URL to be used for each step of an optional login procedure. &lt;br /&gt;
&lt;br /&gt;
;sid[0-9]*IDRegex&lt;br /&gt;
:different Regexes per login procedure step or one common Regex for all steps to extract the session ID from the HTTP response&lt;br /&gt;
&lt;br /&gt;
;sid[0-9]*Data.*&lt;br /&gt;
:data part for each step to be sent as POST data to the corresponding URL&lt;br /&gt;
&lt;br /&gt;
;sid[0-9]*Header.*&lt;br /&gt;
:HTTP Headers to be sent to the URL for the corresponding step&lt;br /&gt;
&lt;br /&gt;
;sid[0-9]*IgnoreRedirects&lt;br /&gt;
:Tells the HttpUtils to not follow HTTP Redirects for this Request. Might be needed for some devices that set a session cookie within a 303 Redirect.&lt;br /&gt;
&lt;br /&gt;
;clearSIdBeforeAuth&lt;br /&gt;
:will set the session id to &amp;quot;&amp;quot; before doing the authentication steps&lt;br /&gt;
&lt;br /&gt;
;authRetries&lt;br /&gt;
:number of retries for authentication procedure - defaults to 1&lt;br /&gt;
&lt;br /&gt;
;replacement[0-9]*Regex&lt;br /&gt;
:Defines a replacement to be applied to an HTTP request header, data or URL before it is sent. This allows any part of the request to be modified based on a reading, an internal or an expression.&lt;br /&gt;
:The regex defines which part of a header, data or URL should be replaced. The replacement is defined with the following attributes:&lt;br /&gt;
&lt;br /&gt;
;replacement[0-9]*Mode&lt;br /&gt;
:Defines how the replacement should be done and what replacementValue means. Valid options are text, reading, internal and expression.&lt;br /&gt;
&lt;br /&gt;
;replacement[0-9]*Value&lt;br /&gt;
:Defines the replacement. If the corresponding replacementMode is &amp;lt;code&amp;gt;text&amp;lt;/code&amp;gt;, then value is a static text that is used as the replacement.&lt;br /&gt;
:If replacementMode is &amp;lt;code&amp;gt;reading&amp;lt;/code&amp;gt; then Value can be the name of a reading of this device or it can be a reading of a different device referred to by devicename:reading.&lt;br /&gt;
:If replacementMode is &amp;lt;code&amp;gt;internal&amp;lt;/code&amp;gt; the Value can be the name of an internal of this device or it can be an internal of a different device referred to by devicename:internal.&lt;br /&gt;
:If replacementMode is &amp;lt;code&amp;gt;expression&amp;lt;/code&amp;gt; the the Value is treated as a Perl expression that computes the replacement value. The expression can use $1, $2 and so on to refer to capture groups of the corresponding regex that is matched against the original URL, header or post data.&lt;br /&gt;
:If replacementMode is &amp;lt;code&amp;gt;key&amp;lt;/code&amp;gt; then the module will use a value from a key / value pair that is stored in an obfuscated form in the file system with the set storeKeyValue command. This might be useful for storing passwords.&lt;br /&gt;
&lt;br /&gt;
;[gs]et[0-9]*Replacement[0-9]*Value&lt;br /&gt;
:This attribute can be used to override the replacement value for a specific get or set.&lt;br /&gt;
&lt;br /&gt;
;get|reading[0-9]*MaxAge&lt;br /&gt;
:Defines how long a reading is valid before it is automatically overwritten with a replacement when the read function is called the next time.&lt;br /&gt;
&lt;br /&gt;
;get|reading[0-9]*MaxAgeReplacement&lt;br /&gt;
:specifies the replacement for MaxAge - either as a static text or as a perl expression.&lt;br /&gt;
&lt;br /&gt;
;get|reading[0-9]*MaxAgeReplacementMode&lt;br /&gt;
:specifies how the replacement is interpreted: can be text, expression and delete.&lt;br /&gt;
&lt;br /&gt;
;get|reading[0-9]*DeleteIfUnmatched&lt;br /&gt;
:If set to 1 this attribute causes certain readings to be deleted when the parsing of the website does not match the specified reading. Internally HTTPMOD remembers which kind of operation created a reading (update, Get01, Get02 and so on). Specified readings will only be deleted if the same operation does not parse this reading again. This is especially useful for parsing that creates several matches / readings and the number of matches can vary from request to request. For example if reading01Regex creates 4 readings in one update cycle and in the next cycle it only matches two times then the readings containing the remaining values from the last round will be deleted.&lt;br /&gt;
:Please note that this mechanism will not work in all cases after a restart. Especially when a get definition does not contain its own parsing definition but ExtractAllJSON or relies on HTTPMOD to use all defined reading.* attributes to parse the responsee to a get command, old readings might not be deleted after a restart of fhem.&lt;br /&gt;
;get|reading[0-9]*DeleteOnError&lt;br /&gt;
:If set to 1 this attribute causes certain readings to be deleted when the website can not be reached and the HTTP request returns an error. Internally HTTPMOD remembers which kind of operation created a reading (update, Get01, Get02 and so on). Specified readings will only be deleted if the same operation returns an error.&lt;br /&gt;
The same restrictions as for DeleteIfUnmatched apply regarding a fhem restart.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;httpVersion&lt;br /&gt;
:defines the HTTP-Version to be sent to the server. This defaults to 1.0.&lt;br /&gt;
&lt;br /&gt;
;sslVersion&lt;br /&gt;
:defines the SSL Version for the negotiation with the server. The attribute is evaluated by HttpUtils. If it is not specified, HttpUtils assumes SSLv23:!SSLv3:!SSLv2&lt;br /&gt;
&lt;br /&gt;
;sslArgs&lt;br /&gt;
:defines a list that is converted to a key / value hash and gets passed to HttpUtils. To avoid certificate validation for broken servers you can for example specify &lt;br /&gt;
:&amp;lt;code&amp;gt;attr myDevice sslArgs SSL_verify_mode,SSL_VERIFY_NONE&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;alignTime&lt;br /&gt;
:Aligns each periodic read request for the defined interval to this base time. This is typcally something like 00:00 (see the FHEM at command)&lt;br /&gt;
&lt;br /&gt;
;noShutdown&lt;br /&gt;
:pass the noshutdown flag to HTTPUtils for webservers that need it (some embedded webservers only deliver empty pages otherwise)&lt;br /&gt;
&lt;br /&gt;
;disable&lt;br /&gt;
:stop doing automatic HTTP requests while this attribute is set to 1&lt;br /&gt;
&lt;br /&gt;
;enableControlSet&lt;br /&gt;
:enables the built in set commands interval, stop, start, reread, upgradeAttributes, storeKeyValue.&lt;br /&gt;
&lt;br /&gt;
;enableCookies&lt;br /&gt;
:enables the built in cookie handling if set to 1. With cookie handling each HTTPMOD device will remember cookies that the server sets and send them back to the server in the following requests. &lt;br /&gt;
:This simplifies session magamenet in cases where the server uses a session ID in a cookie. In such cases enabling cookies should be sufficient and no sidRegex and no manual definition of a cookie header should be necessary.&lt;br /&gt;
&lt;br /&gt;
;showMatched&lt;br /&gt;
:if set to 1 then HTTPMOD will create a reading with the name MATCHED_READINGS that contains the names of all readings that could be matched in the last request as well as UNMATCHED_READINGS and LAST_REQUEST.&lt;br /&gt;
&lt;br /&gt;
;showError&lt;br /&gt;
:if set to 1 then HTTPMOD will create a reading and event with the Name LAST_ERROR that contains the error message of the last error returned from HttpUtils. &lt;br /&gt;
&lt;br /&gt;
;removeBuf&lt;br /&gt;
:if set to 1 then HTTPMOD removes the internal named buf when a HTTP-response has been received. &lt;br /&gt;
:$hash-&amp;gt;{buf} is used internally be Fhem httpUtils and in some use cases it is desireable to remove this internal after reception &lt;br /&gt;
:because it contains a very long response which looks ugly in Fhemweb.&lt;br /&gt;
&lt;br /&gt;
;timeout&lt;br /&gt;
:time in seconds to wait for an answer. Default value is 2&lt;br /&gt;
&lt;br /&gt;
;queueDelay&lt;br /&gt;
:HTTP Requests will be sent from a queue in order to avoid blocking when several Requests have to be sent in sequence. This attribute defines the delay between calls to the function that handles the send queue. It defaults to one second.&lt;br /&gt;
&lt;br /&gt;
;queueMax&lt;br /&gt;
:Defines the maximum size of the send queue. If it is reached then further HTTP Requests will be dropped and not be added to the queue&lt;br /&gt;
&lt;br /&gt;
;minSendDelay&lt;br /&gt;
:Defines the minimum time between two HTTP Requests.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Example: [https://www.goingelectric.de/forum/viewtopic.php?f=57&amp;amp;t=21462|Abfrage Akkustand einer Zoe und mehr von Renault ZE Services]&lt;br /&gt;
* Example: [[Wetter_und_Wettervorhersagen#Wetter_von_Weather_Underground|Extract weather information from WeatherUnderground]]&lt;br /&gt;
* Example: [[Pollenflug|Pollen count]]&lt;br /&gt;
* Example: [[HTTPMOD Beispielkonfiguration zur Anbindung einer Daikin Klimaanlage mit WLAN-Modul|Connect Daikin aircondition to FHEM]]&lt;br /&gt;
* Example: [[Go-eCharger|Extract information from go-eCharger]]&lt;br /&gt;
* Example: [[Sonnenspeicher|Integration of energy supplies from sonnen (https://sonnenbatterie.de/en/start)]]&lt;br /&gt;
* Example: [https://forum.fhem.de/index.php/topic,95989.msg915870.html#msg915870 Miele 3rd party API für Miele Smarthome Geräte]&lt;br /&gt;
* Example: [https://forum.fhem.de/index.php/topic,84215.msg918662.html#msg918662 Honeywell Evohome Totalconnect]&lt;br /&gt;
* Example: [https://forum.fhem.de/index.php/topic,78613.msg889015.html#msg889015 Tigo Energy Integration]&lt;br /&gt;
* Example: [https://forum.fhem.de/index.php/topic,78613.msg708518.html#msg708518 Ecowater]&lt;br /&gt;
* {{Link2Forum|Topic=17804|LinkText=Thread}} in FHEM Forum that discusses the first version of this module &lt;br /&gt;
* {{Link2Forum|Topic=29471|LinkText=Thread}} in FHEM Forum that discusses the second major version of this module &lt;br /&gt;
* {{Link2Forum|Topic=45176|LinkText=Thread}} in FHEM Forum that discusses the third major version of this module &lt;br /&gt;
* [http://perldoc.perl.org/perlretut.html Introduction to regular expressions]&lt;br /&gt;
* [http://portswigger.net/burp/ BurpSuite]: Tool (local proxy) to help analyze http traffic&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:IP Components]]&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Svgplot&amp;diff=38691</id>
		<title>FTUI Widget Svgplot</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FTUI_Widget_Svgplot&amp;diff=38691"/>
		<updated>2023-11-09T10:47:32Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: veraltete &amp;quot;source&amp;quot;-Angaben in &amp;quot;syntaxhighlight&amp;quot; geändert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=SVG-Diagramme in FTUI anzeigen&lt;br /&gt;
|ModType=x&lt;br /&gt;
|ModFTopic=u/i&lt;br /&gt;
|ModForumArea=TabletUI&lt;br /&gt;
|ModTechName=svgplot&lt;br /&gt;
|ModOwner=u/i ({{Link2FU|7023|Forum}})&lt;br /&gt;
}}&lt;br /&gt;
Das [[{{PAGENAME}}|Widget svgplot]] ist ein Widget für [[FHEM Tablet UI]] zur Anzeige bereits selbst erstellter [[SVG]]-Diagramme. 2019-01 wurde es geprüft und war funktional.&lt;br /&gt;
&lt;br /&gt;
==Funktionalität==&lt;br /&gt;
Innerhalb einer FTUI-Oberfläche wird ein bereits verfügbares, also selbst für FHEM erstelltes [[SVG]]-Diagramm angezeigt. Das Diagramm wird aktualisiert. Weitere Funktionen (Navigation nach vergangener Zeit usw.) sind nicht vorhanden.&lt;br /&gt;
&lt;br /&gt;
==Attribute==&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Attribut&lt;br /&gt;
!Beschreibung&lt;br /&gt;
!Standard-Wert&lt;br /&gt;
!Beispiel&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-device&#039;&#039;&#039;||zu Grunde liegendes Device||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-gplotfile&#039;&#039;&#039;||Name des vorhandenen (!) gplot-Files|||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-logdevice&#039;&#039;&#039;||Name des Logfiles||||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-logfile&#039;&#039;&#039;||||CURRENT||&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;data-refresh&#039;&#039;&#039;||Aktualisierung in Sekunden||||300&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Beispiel==&lt;br /&gt;
Ein svgplot soll in der 3. Zeile, 1. Spalte beginnen und 7 Kacheln breit sowie 3 Kacheln hoch sein:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;li data-row=&amp;quot;3&amp;quot; data-col=&amp;quot;1&amp;quot; data-sizex=&amp;quot;7&amp;quot; data-sizey=&amp;quot;3&amp;quot;&amp;gt;|&lt;br /&gt;
 &amp;lt;div data-type=&amp;quot;svgplot&amp;quot;&lt;br /&gt;
      data-device=&amp;quot;SVG_Movie&amp;quot;&lt;br /&gt;
      data-gplotfile=&amp;quot;SVG_Movie&amp;quot;&lt;br /&gt;
      data-logdevice=&amp;quot;FileLog_Movie&amp;quot;&lt;br /&gt;
      data-logfile=&amp;quot;CURRENT&amp;quot;&lt;br /&gt;
      data-refresh=&amp;quot;300&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Alternatives Widget==&lt;br /&gt;
[[FTUI Widget Chart]] visualisiert Verläufe durch Auswertung von FHEM-Logdateien. Die Navigation über den Zeitstrahl ist gegeben.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:FHEM Tablet UI|Svgplot]]&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=DWD_OpenData&amp;diff=38690</id>
		<title>DWD OpenData</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=DWD_OpenData&amp;diff=38690"/>
		<updated>2023-11-09T10:47:02Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: veraltete &amp;quot;source&amp;quot;-Angaben in &amp;quot;syntaxhighlight&amp;quot; geändert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Hinweis|Versionsänderung: Die Vorhersagedaten wurden Mitte September 2018 von CSV auf KML umgestellt. Diese Umstellung ist inkompatibel: das DWD_OpenData-Modul muss aktualisiert werden, einige Reading-Namen haben sich geändert und der Weblink muss deinstalliert und neu installiert werden (siehe diesen {{Link2Forum|Topic=83097|Message=840270|Linktext=Beitrag im Forum}}).}}&lt;br /&gt;
&lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=Daten vom DWD OpenData Server abrufen&lt;br /&gt;
|ModType=d&lt;br /&gt;
|ModCmdRef=DWD_OpenData&lt;br /&gt;
|ModForumArea=Unterstützende Dienste/Wettermodule&lt;br /&gt;
|ModTechName=55_DWD_OpenData.pm&lt;br /&gt;
|ModOwner=JensB ({{Link2FU|14024|Forum}}/[[Benutzer Diskussion:JensB|Wiki]])&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Der Deutsche Wetterdienst (DWD) stellt Wetterdaten über den [https://www.dwd.de/DE/leistungen/opendata/opendata.html Open Data Server] zur Verfügung. Die Verwendung dieses Dienstes und der vom DWD zur Verfügung gestellten Daten unterliegt den auf der OpenData Webseite beschriebenen Bedingungen. Einen Überblick über die verfügbaren Daten findet man in der Tabelle [https://www.dwd.de/DE/leistungen/opendata/help/inhalt_allgemein/opendata_content_de_en_xls.xls OpenData_weather_content.xls] oder hier: https://opendata.dwd.de/weather/lib/MetElementDefinition.xml.&lt;br /&gt;
&lt;br /&gt;
== Anwendung ==&lt;br /&gt;
Aufgrund der unterschiedlichen vom DWD bereitgestellten Datenformate benötigt das Modul zur Dekodierung je nach gewünschtem Funktionsumfang zusätzliche Perl-Module, die nicht standardmäßig vorinstalliert sind und je nach Systemkonfiguration nachinstalliert werden müssen. Außerdem unterstützt das Modul Zeitzonen, um z.B. die Wettervorhersage internationaler Stationen in Ortszeit darstellen zu können. Hierfür sind je nach Systemkonfiguration weitere Einstellungen erforderlich. Auch die Sprache der Wochentage für die Wettervorhersage ist frei wählbar. Je nach Systemkonfiguration ist aber die Standardsprache u.U. auf Englisch eingestellt, was weitere Anpassungen der Systemkonfiguration erforderlich macht.&lt;br /&gt;
&lt;br /&gt;
=== Vorbereitung ===&lt;br /&gt;
Im folgenden wird z.T. von einem System mit Rasbian oder Debian mit System-V Startsystem ausgegangen. Auf anderen Betriebssystemen und auf Systemen mit System-D müssen die Installationsschritte ggf. angepasst werden.&lt;br /&gt;
&lt;br /&gt;
1. Für die Wettervorhersage und die Wetterwarnungen:&lt;br /&gt;
Installation des Perl-Moduls &#039;&#039;XML::LibXML&#039;&#039; über die System-Kommandozeile mit&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo apt-get install libxml-libxml-perl&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; &lt;br /&gt;
oder mit CPAN.&lt;br /&gt;
&lt;br /&gt;
2. Weiterhin ist das Perl-Modul &#039;&#039; DateTime&#039;&#039; erforderlich. Dieses lässt sich mit &amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;sudo apt-get install libdatetime-perl&amp;lt;/source&amp;gt; installieren.&lt;br /&gt;
&lt;br /&gt;
3. Falls man einen eigenen Internet-Proxy nutzt:&lt;br /&gt;
Die Konfiguration des Proxies für FHEM erfolgt z.B. durch Eintrag von&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr global proxy &amp;lt;myProxyHost&amp;gt;:&amp;lt;myProxyPort&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
in die [[Konfiguration]], wobei &#039;&#039;myProxyHost&#039;&#039; durch den Namen oder die IP-Adresse des Proxy-Servers ersetzt werden muss und für &#039;&#039;myProxyPort&#039;&#039; der Port des Proxy-Servers eingetragen werden muss (oft 3128).&lt;br /&gt;
&lt;br /&gt;
3. FHEM Uhrzeit und Zeitzone:&lt;br /&gt;
Durch Eingabe von &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 {localtime()}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
in die FHEM-Kommandozeile überprüfen, ob die FHEM-Uhrzeit plausibel ist. Ist dies nicht der Fall sollten die Uhrzeit auf Systemebene überprüft werden und ggf. die Systemeinstellungen angepasst werden.&lt;br /&gt;
Ermitteln der Bezeichnung der eigenen Zeitzone über die System-Kommandozeile mit&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
  tzselect&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
und diese Bezeichnung in die Datei &#039;&#039;/etc/timezone&#039;&#039; eintragen und &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 export TZ=`cat /etc/timezone`&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
der Datei &#039;&#039;/etc/profile&#039;&#039; hinzufügen und dann das System neu starten. Nun muss die Zeitanzeige in FHEM korrekt sein.&lt;br /&gt;
&lt;br /&gt;
4. FHEM Sprache:&lt;br /&gt;
Durch Eingabe von &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 {$ENV{LANG}}&lt;br /&gt;
&amp;lt;/pre&amp;gt; in die FHEM-Kommandozeile überprüfen, in welcher Sprache der Wochentag angezeigt wird. Stimmt die Sprache nicht, dann auf der System-Kommandozeile&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 dpkg-reconfigure locales&lt;br /&gt;
&amp;lt;/pre&amp;gt; eingeben und aus der Liste z.B. &#039;&#039;de_DE.UTF-8&#039;&#039; zusätzlich auswählen. Dieser Befehl gilt für Debian-basierte Betriebssysteme - für andere Betriebssysteme ist eine analoge Funktion zu verwenden. Mit Eingabe von &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 locale -a&lt;br /&gt;
&amp;lt;/pre&amp;gt; auf der System-Kommandozeile überprüfen, ob die ausgewählte Sprache nun zur Verfügung steht. Sollte FHEM nach einem Neustart noch immer nicht die gewünschte Sprache verwenden, kann man auf einem System V Linux durch Hinzufügen von z.B.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 export LANG=de_DE.UTF-8&lt;br /&gt;
&amp;lt;/pre&amp;gt; in die Datei &#039;&#039;/etc/init.d/fhem&#039;&#039; (irgendwo zwischen &#039;&#039;start&#039;&#039; und &#039;&#039;perl&#039;&#039;) und erneutem Neustart von FHEM die Sprache für FHEM erzwingen. Bei einem Systemd Linux kann man die Einstellungen mit &#039;&#039;systemctl edit --full fhem.service&#039;&#039; bearbeiten. Spätestes jetzt muss die Wochentagsanzeige in FHEM korrekt sein.&lt;br /&gt;
&lt;br /&gt;
5. Nur für den Weblink erforderlich:&lt;br /&gt;
Installation des Perl-Moduls &#039;&#039;DateTime&#039;&#039; über die System-Kommandozeile mit&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 sudo apt-get install libdatetime-perl&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
oder mit CPAN.&lt;br /&gt;
&lt;br /&gt;
=== Define ===&lt;br /&gt;
Siehe {{Link2CmdRef|Anker=DWD_OpenDatadefine|Label=Commandref}}.&lt;br /&gt;
&lt;br /&gt;
=== Attributes ===&lt;br /&gt;
Siehe {{Link2CmdRef|Anker=DWD_OpenDataattr|Label=Commandref}}.&lt;br /&gt;
&lt;br /&gt;
== Anwendungsbeispiele ==&lt;br /&gt;
=== Beispiel zur Modul-Einrichtung ===&lt;br /&gt;
&lt;br /&gt;
* Wettervorhersage&lt;br /&gt;
Für die Wettervorhersage muss der Stationscode ermittelt werden. Dazu den [https://www.dwd.de/DE/leistungen/met_verfahren_mosmix/mosmix_stationskatalog.pdf MOSMIX Stationskatalog] herunterladen, öffnen und die gewünschte Station heraussuchen (Spalte &#039;&#039;id&#039;&#039;). Einen Teil der deutschen Stationen kann man auch der [https://www.dwd.de/DE/derdwd/messnetz/bodenbeobachtung/messnetzkarte_boden.pdf Bodenmessnetzkarte] entnehmen. Den ermittelten Stationscode kann man dann entweder für eine Einzelabfrage als Parameter für das Kommando &#039;&#039;get forecast&#039;&#039; verwenden oder für die automatische Aktualisierung als Attribut &#039;&#039;forecastStation&#039;&#039; hinterlegen. Insgesamt werden vom DWD mehr als 70 Merkmale zur Verfügung gestellt. Eine Auflistung findet sich im Dokument [https://opendata.dwd.de/weather/lib/MetElementDefinition.xml MetElementDefinition]. Nur ein kleiner Teil der Merkmale wird in der Standardeinstellung des Moduls als Reading zur Verfügung gestellt. Wer andere Merkmale benötigt muss sie mit Komma getrennt dem Attribut &#039;&#039;forecastProperties&#039;&#039; zuweisen. Es empfiehlt sich zur Performance-Optimierung sowohl das Attribut &#039;&#039;forecastDays&#039;&#039; als auch das Attribut &#039;&#039;forecastProperties&#039;&#039; auf den tatsächlichen Bedarf einzustellen.&lt;br /&gt;
&lt;br /&gt;
* Wetterwarnungen&lt;br /&gt;
Für die Wetterwarnungen muss die Warnzelle ermittelt werden. Dazu [https://www.dwd.de/DE/leistungen/opendata/help/warnungen/cap_warncellids_csv.csv Warnzellen-ID Katalog] herunterladen, öffnen und die gewünschte Warnzelle heraussuchen. Unterstützt werden Gemeinden (beginnen mit 8), Landkreise (beginnen mit 1 oder 9) oder Küste (beginnen mit 5). Die Warnzellen-ID kann man dann entweder für eine Einzelabfrage als Parameter für das Kommando &#039;&#039;get alerts&#039;&#039; verwenden oder für die automatische Aktualisierung als Attribut &#039;&#039;alertArea&#039;&#039; hinterlegen. Die Warnzellen-ID ist ab der 2. Stelle identisch mit den ersten Ziffern des amtlichen Gemeindeschlüssels. Man kann z.B. den Namen von Gemeinde oder Landkreis bei den [https://www.statistik-bw.de/Statistik-Portal/gemeindeverz.asp Statistischen Ämtern des Bundes und der Länder] eingeben, den amtlichen Gemeindeschlüssel ermitteln und dann mit vorangestellter 1, 8 oder 9 im Warnzellen-ID Katalog des DWD nach einem Eintrag mit exakter oder weitgehender Übereinstimmung suchen. Wem das zu kompliziert vorkommt, der kann bei mehrdeutigen Gemeinde- bzw. Landkreisbezeichnungen auch versuchen auszuprobieren, welche die richtige Warnzellen-ID ist.&lt;br /&gt;
&lt;br /&gt;
Um das Modul mit automatisch Aktualisierung von Vorhersage und Wetterwarnungen zu nutzen, kann z.B. folgendes in die [[Konfiguration]] eingetragen werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 define DWD DWD_OpenData&lt;br /&gt;
 attr DWD alertArea 111000000&lt;br /&gt;
 attr DWD forecastStation 99810&lt;br /&gt;
 attr DWD forecastDays 3&lt;br /&gt;
 attr DWD forecastWW2Text 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Performance&lt;br /&gt;
Das DWD_OpenData-Modul ist ein Datenmodul mit relativ vielen Readings. In der Standardkonfiguration wird, wie bei jedem anderen FHEM Modul, bei jeder Änderung jedes Readings ein FHEM internes Ereignis erzeugt, damit andere FHEM Devices auf diese Änderungen reagieren können. Diese Ereignisse sorgen auch dafür, dass man Änderungen in der Weboberfläche sofort angezeigt bekommt, ohne die Webseite neu aufzurufen. Interessiert sich aber kein FHEM Device für die Änderungsbenachrichtigung bestimmter Readings, entsteht unnötiger Verarbeitungs-Overhead, der je nach FHEM Konfiguration und verfügbarer CPU-Leistung auch mehrere Sekunden benötigen kann und in dieser Zeit andere Abläufe blockiert. Um die Performance zu optimieren, empfiehlt es sich,  mit [[event-on-update-reading]] für eine angepasste und dadurch effizientere Verarbeitung zu sorgen, indem man nur für jene Readings Ereignisse zulässt, welche man für die Weiterverarbeitung braucht. Der DWD_OpenData_Weblink braucht z.B. gar keine Ereignisse, um zu funktionieren. Hier eine minimalistische Beispielkonfiguration:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 attr DWD event-on-update-reading state,fc_state,a_state&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Weitere Details zur Installation und Konfiguration des Moduls finden sich in der&lt;br /&gt;
{{Link2CmdRef|Anker=DWD_OpenData|Label=Commandref}}.&lt;br /&gt;
&lt;br /&gt;
=== Beispiel für die Einrichtung eines Meteogramms ===&lt;br /&gt;
Um den vorhergesagten Wetterverlauf als Meteogramm in Kurvenform mit [[SVG]] darzustellen, kann man wie folgt vorgehen:&lt;br /&gt;
&lt;br /&gt;
1. 99_myUtils.pm&lt;br /&gt;
&lt;br /&gt;
Für die Bestimmung der Werte für den SVG-Plot wird eine Perl-Funktion benötigt, die in die Datei 99_myUtils.pm vor dem Ende eingefügt wird. Wer diese FHEM-Datei noch nicht nutzt, legt sie einfach an (siehe [[99_myUtils_anlegen]]).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
package main;&lt;br /&gt;
&lt;br /&gt;
use strict;&lt;br /&gt;
use warnings;&lt;br /&gt;
 &lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
#&lt;br /&gt;
# (c) mumpitzstuff 19.12.2018&lt;br /&gt;
#&lt;br /&gt;
# see https://forum.fhem.de/index.php/topic,83097.msg874150.html#msg874150&lt;br /&gt;
#&lt;br /&gt;
sub logProxy_dwd2Plot($$$$;$$$)&lt;br /&gt;
{&lt;br /&gt;
  my ($device, $fcValue, $from, $to, $fcHour, $expMode, $shiftTime) = @_;&lt;br /&gt;
  my $regex;&lt;br /&gt;
  my @rl;&lt;br /&gt;
&lt;br /&gt;
  return undef if(!$device);&lt;br /&gt;
&lt;br /&gt;
  if ($fcValue =~ s/_$//)&lt;br /&gt;
  {&lt;br /&gt;
    $regex = &amp;quot;^fc[\\d]+_[\\d]+_&amp;quot;.$fcValue.&amp;quot;\$&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    $regex = &amp;quot;^fc[\\d]+_&amp;quot;.$fcValue.&amp;quot;\$&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  $fcHour = 12 if(!defined($fcHour));&lt;br /&gt;
  $expMode = &amp;quot;point&amp;quot; if(!defined($expMode));&lt;br /&gt;
  #Log3 undef,2, &amp;quot;Regex: &amp;quot;.$regex;&lt;br /&gt;
&lt;br /&gt;
  # ermitteln aller relevanten Readings&lt;br /&gt;
  if ( defined($defs{$device}) )&lt;br /&gt;
  {&lt;br /&gt;
    if ( $defs{$device}{TYPE} eq &amp;quot;DWD_OpenData&amp;quot; )&lt;br /&gt;
    {&lt;br /&gt;
      @rl = sort&lt;br /&gt;
      {&lt;br /&gt;
        my ($an) = ($a =~ m/fc(\d+)_.*/);&lt;br /&gt;
        my ($bn) = ($b =~ m/fc(\d+)_.*/);&lt;br /&gt;
        my ($ao) = ($a =~ m/fc\d+_(\d+).*/);&lt;br /&gt;
        my ($bo) = ($b =~ m/fc\d+_(\d+).*/);&lt;br /&gt;
        $an &amp;lt;=&amp;gt; $bn or $ao &amp;lt;=&amp;gt; $bo or $a cmp $b;&lt;br /&gt;
      } ( grep /${regex}/,keys %{$defs{$device}{READINGS}} );&lt;br /&gt;
      return undef if ( !@rl );&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
      Log3 undef, 2, &amp;quot;logProxy_dwd2Plot: $device is not a DWD_OpenData device&amp;quot;;&lt;br /&gt;
      return undef;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  my $fromsec = SVG_time_to_sec($from);&lt;br /&gt;
  my $tosec   = SVG_time_to_sec($to);&lt;br /&gt;
  my $sec = $fromsec;&lt;br /&gt;
  my ($h, $hp, $fcDay, $mday, $mon, $year);&lt;br /&gt;
  my $timestamp;&lt;br /&gt;
&lt;br /&gt;
  my $reading;&lt;br /&gt;
  my $value;&lt;br /&gt;
  my $prev_value;&lt;br /&gt;
  my $min = 999999;&lt;br /&gt;
  my $max = -999999;&lt;br /&gt;
  my $ret = &amp;quot;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  # while not end of plot range reached&lt;br /&gt;
  while (($sec &amp;lt; $tosec) &amp;amp;&amp;amp; @rl)&lt;br /&gt;
  {&lt;br /&gt;
    #remember previous value for start of plot range&lt;br /&gt;
    $prev_value = $value;&lt;br /&gt;
&lt;br /&gt;
    $reading = shift @rl;&lt;br /&gt;
    ($fcDay) = $reading =~ m/^fc(\d+).*/;&lt;br /&gt;
    ($hp) = $reading =~ m/^fc\d+_(\d+).*/;&lt;br /&gt;
    #Log 1, &amp;quot;hp: &amp;quot;.$hp;&lt;br /&gt;
&lt;br /&gt;
    if ($hp)&lt;br /&gt;
    {&lt;br /&gt;
      $h = ReadingsVal($device, &amp;quot;fc&amp;quot;.$fcDay.&amp;quot;_&amp;quot;.$hp.&amp;quot;_time&amp;quot;, $fcHour);&lt;br /&gt;
      if ($h =~ m/^(\d+):\d+/)&lt;br /&gt;
      {&lt;br /&gt;
        $h = $1;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
      $h = $fcHour;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    $value = ReadingsVal($device, $reading, undef);&lt;br /&gt;
&lt;br /&gt;
    # calculate minutes of sunshine per hour&lt;br /&gt;
    if ($fcValue =~ /^SunD(\d+)/)&lt;br /&gt;
    {&lt;br /&gt;
      if (defined($1))&lt;br /&gt;
      {&lt;br /&gt;
        $value = $value / ($1 * 36);&lt;br /&gt;
      }&lt;br /&gt;
      else&lt;br /&gt;
      {&lt;br /&gt;
        $value = $value / (12 * 36);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    # calculate amount of rain per hour&lt;br /&gt;
    if ($fcValue =~ /^RR(\d+)c$/)&lt;br /&gt;
    {&lt;br /&gt;
      if (defined($1))&lt;br /&gt;
      {&lt;br /&gt;
        $value /= $1;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    ($year, $mon, $mday) = split(&#039;\-&#039;,ReadingsVal($device, &amp;quot;fc&amp;quot;.$fcDay.&amp;quot;_date&amp;quot;,undef));&lt;br /&gt;
    $timestamp = sprintf(&amp;quot;%04d-%02d-%02d_%02d:%02d:%02d&amp;quot;, $year, $mon, $mday, $h, 0, 0);&lt;br /&gt;
    $sec = SVG_time_to_sec($timestamp);&lt;br /&gt;
    if (defined($shiftTime))&lt;br /&gt;
    {&lt;br /&gt;
      $sec += $shiftTime;&lt;br /&gt;
      $timestamp = logProxy_shiftTime($timestamp, $shiftTime);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    # skip all values before start of plot range&lt;br /&gt;
    next if ( $sec &amp;lt; $fromsec );&lt;br /&gt;
&lt;br /&gt;
    # add first value at start of plot range&lt;br /&gt;
    if ( !$ret &amp;amp;&amp;amp; $prev_value )&lt;br /&gt;
    {&lt;br /&gt;
      $min = $prev_value if ( $prev_value &amp;lt; $min );&lt;br /&gt;
      $max = $prev_value if ( $prev_value &amp;gt; $max );&lt;br /&gt;
      $ret .= &amp;quot;$from $prev_value\n&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    # done if after end of plot range&lt;br /&gt;
    last if ($sec &amp;gt; $tosec);&lt;br /&gt;
&lt;br /&gt;
    $min = $value if ( $value &amp;lt; $min );&lt;br /&gt;
    $max = $value if ( $value &amp;gt; $max );&lt;br /&gt;
&lt;br /&gt;
    # add actual control point&lt;br /&gt;
    $ret .= &amp;quot;$timestamp $value\n&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if (($sec &amp;lt; $tosec) &amp;amp;&amp;amp; !@rl &amp;amp;&amp;amp; ($expMode eq &amp;quot;day&amp;quot;))&lt;br /&gt;
  {&lt;br /&gt;
    $timestamp = sprintf(&amp;quot;%04d-%02d-%02d_%02d:%02d:%02d&amp;quot;, $year, $mon, $mday, 23, 59, 59);&lt;br /&gt;
    $_ = SVG_time_to_sec($timestamp);&lt;br /&gt;
    if (defined($shiftTime))&lt;br /&gt;
    {&lt;br /&gt;
      $_ += $shiftTime;&lt;br /&gt;
      $timestamp = logProxy_shiftTime($timestamp, $shiftTime);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    if ($_ &amp;lt; $tosec)&lt;br /&gt;
    {&lt;br /&gt;
      $ret .= &amp;quot;$timestamp $value\n&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
      $ret .= &amp;quot;$to $value\n&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  elsif (($sec &amp;gt; $tosec) &amp;amp;&amp;amp; ($expMode eq &amp;quot;day&amp;quot;))&lt;br /&gt;
  {&lt;br /&gt;
    $value = $prev_value + ($value - $prev_value) * (86400 + ($tosec - $sec)) / 86400;&lt;br /&gt;
    $ret .= &amp;quot;$to $value\n&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return ($ret, $min, $max, $prev_value);&lt;br /&gt;
} &lt;br /&gt;
&lt;br /&gt;
1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. LogProxy&lt;br /&gt;
&lt;br /&gt;
Wer bereits ein [[logProxy]]-Device hat, muss den Namen seines logProxy-Devices in die weiter unter aufgeführte GPlot-Konfiguration eintragen. Ansonsten wird es wie folgt neu erstellt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define LogProxy logProxy&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3. FileLog&lt;br /&gt;
&lt;br /&gt;
Das Meteogramm kennt anders als andere FHEM-Plots keine Vergangenheit außer heute. Trotzdem wird aus formalen Gründen ein [[FileLog]]-Device benötigt. Dazu kann ein beliebiges vorhandenes FileLog-Device verwendet werden. Wer will, kann hierfür aber auch ein neues FileLog Device für das DWD_OpenData-Device anlegen (Achtung: wird schnell umfangreich):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define FileLog_DWD FileLog ./log/DWD-%Y-%m.log DWD&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im folgenden wird für das FileLog-Device der Platzhalter &#039;&#039;FileLog_Dummy&#039;&#039; verwendet, der mit dem Namen des gewählten FileLog-Devices zu ersetzen ist.&lt;br /&gt;
&lt;br /&gt;
4. SVG Plot&lt;br /&gt;
&lt;br /&gt;
Das eigentliche Meteogramm ist ein SVG-Device. Will man mehrere Tage darstellen bietet sich die folgende Definition an:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define SVG_DWD SVG FileLog_Dummy:SVG_DWD:CURRENT&lt;br /&gt;
attr SVG_DWD fixedoffset 6&lt;br /&gt;
attr SVG_DWD fixedrange 7days&lt;br /&gt;
attr SVG_DWD nrAxis 1,2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dabei muss das SVG-Attribut &#039;&#039;fixedoffset&#039;&#039; entweder gleich oder kleiner als die Einstellung des DWD_OpenData-Attributs &#039;&#039;forecastDays&#039;&#039; (Standardwert: 6 Tage) gewählt werden und das SVG-Attribut &#039;&#039;fixedrange&#039;&#039; um eins größer als &#039;&#039;fixedoffset&#039;&#039; eingestellt werden.&lt;br /&gt;
&lt;br /&gt;
Will man stattdessen nur die nächsten 24 Stunden anzeigen, nimmt man folgende Einstellungen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define SVG_DWD SVG FileLog_Dummy:SVG_DWD:CURRENT&lt;br /&gt;
attr SVG_DWD endPlotNow 1&lt;br /&gt;
attr SVG_DWD fixedoffset 1&lt;br /&gt;
attr SVG_FileLog_WETTER_DWD_3 label &amp;quot;Tmin: $data{max1} °C, Tmax: $data{min1} °C&amp;quot;&lt;br /&gt;
attr SVG_DWD nrAxis 1,2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Um die DWD_OpenData-Readings mit dem Plot zu verknüpfen, muss man nun die GPlot-Konfigurationsdatei des SVG-Plots manuell bearbeiten. Dazu auf den Link klicken, der im SVG_DWD-Device am Internal &#039;&#039;GPLOTFILE&#039;&#039; steht. Die y-Wertebereiche für die Regenmenge und die Temperaturen sind im Beispiel auskommentiert (Autorange). Das kann man so lassen oder man stellt sie nach den eigenen Wetter-Gegebenheiten ein. Je nach Konfiguration des DWD_OpenData-Attributs &#039;&#039;forecastResolution&#039;&#039; sind aber noch einige weitere Einstellungen anzupassen. Das folgende Beispiel ist für die 3h-Auflösung:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set terminal png transparent size &amp;lt;SIZE&amp;gt; crop&lt;br /&gt;
set output &#039;&amp;lt;OUT&amp;gt;.png&#039;&lt;br /&gt;
set xdata time&lt;br /&gt;
set timefmt &amp;quot;%Y-%m-%d_%H:%M:%S&amp;quot;&lt;br /&gt;
set xlabel &amp;quot; &amp;quot;&lt;br /&gt;
set title &#039;Wettervorhersage&#039;&lt;br /&gt;
set ytics &lt;br /&gt;
set y2tics &lt;br /&gt;
set grid ytics&lt;br /&gt;
set ylabel &amp;quot;Regen [mm]&amp;quot;&lt;br /&gt;
#set yrange [0:4]&lt;br /&gt;
set y2label &amp;quot;Temperatur [°C]&amp;quot;&lt;br /&gt;
#set y2range [-5:35]&lt;br /&gt;
set y3label &amp;quot;Wolken/Regen/Sonne [%]&amp;quot;&lt;br /&gt;
set y3range [0:100]&lt;br /&gt;
&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;TTT_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;Tx&amp;quot;,$from,$to,18,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;Tn&amp;quot;,$from,$to,6,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;SunD3_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-3*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;RR3c_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-3*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;FX1_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;R600_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-3*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;Neff_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy ConstX:TimeNow(),0,100&lt;br /&gt;
#LogProxy ConstY:0&lt;br /&gt;
&lt;br /&gt;
plot &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;T&#039; ls l0 lw 2 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;Tmax&#039; ls l0dot lw 2 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;Tmin&#039; ls l0dot lw 2 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Sonne&#039; ls l4fill lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y1 title &#039;Regenmenge&#039; ls l2fill lw 1 with steps,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Wind&#039; ls l1 lw 1 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Regen&#039; ls l5fill lw 1 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Wolken&#039; ls l6fill lw 1 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 notitle ls l5 lw 4 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 notitle ls l5 lw 1 with lines&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verwendet man dagegen eine Auflösung von 1 Stunde, sind folgende LogProxy-Einträge erforderlich:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;TTT_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;Tx&amp;quot;,$from,$to,18,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;Tn&amp;quot;,$from,$to,6,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;SunD1_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-1*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;RR1c_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-1*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;FX1_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;R101_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-0.5*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;Neff_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy ConstX:TimeNow(),0,100&lt;br /&gt;
#LogProxy ConstY:0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für die Darstellung der nächsten 24 Stunden mit einer Auflösung von 1 Stunde nimmt man folgende GPlot-Konfiguration:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set terminal png transparent size &amp;lt;SIZE&amp;gt; crop&lt;br /&gt;
set output &#039;&amp;lt;OUT&amp;gt;.png&#039;&lt;br /&gt;
set xdata time&lt;br /&gt;
set timefmt &amp;quot;%Y-%m-%d_%H:%M:%S&amp;quot;&lt;br /&gt;
set xlabel &amp;quot; &amp;quot;&lt;br /&gt;
set title &#039;&amp;lt;L1&amp;gt;&#039;&lt;br /&gt;
set ytics&lt;br /&gt;
set y2tics&lt;br /&gt;
set y3tics&lt;br /&gt;
set grid xtics y2tics&lt;br /&gt;
set ylabel &amp;quot;Regen [mm]&amp;quot;&lt;br /&gt;
set y2label &amp;quot;Temperatur [°C]&amp;quot;&lt;br /&gt;
set y3label &amp;quot;Wolken/Regen/Sonne [%]&amp;quot;&lt;br /&gt;
set y3range [0:100]&lt;br /&gt;
&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;TTT_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;SunD1_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-1*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;RR1c_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-1*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;FX1_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;R101_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;,(-0.5*3600))&lt;br /&gt;
#LogProxy Func:logProxy_dwd2Plot(&amp;quot;DWD&amp;quot;,&amp;quot;Neff_&amp;quot;,$from,$to,0,&amp;quot;day&amp;quot;)&lt;br /&gt;
#LogProxy ConstY:0&lt;br /&gt;
&lt;br /&gt;
plot &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 title &#039;T&#039; ls l0 lw 2 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Sonne&#039; ls l4fill lw 1 with lines,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y1 title &#039;Regenmenge&#039; ls l2fill lw 1 with steps,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Wind&#039; ls l1 lw 1 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Regen&#039; ls l5fill lw 1 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y3 title &#039;Wolken&#039; ls l6fill lw 1 with quadraticSmooth,\&lt;br /&gt;
     &amp;quot;&amp;lt;IN&amp;gt;&amp;quot; using 1:2 axes x1y2 notitle ls l2 lw 2 with lines&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Je nachdem, welche Auflösung man verwendet, werden unterschiedliche Readings des DWD_OpenData-Devices benötigt. Diese sind in den LogProxy-Zeilen in der GPlot-Konfigurationsdatei zu finden und müssen auf jeden Fall dem Attribut &#039;&#039;forecastProperties&#039;&#039; des DWD_OpenData-Device hinzugefügt werden.&lt;br /&gt;
&lt;br /&gt;
Viele Detaileinstellungen des Meteogramms lassen sich individualisieren. Man kann z.B. mehr oder weniger Daten anzeigen und zumindest für &#039;&#039;heute&#039;&#039; auch aktuelle Messwerte hinzufügen.&lt;br /&gt;
&lt;br /&gt;
Hier ein Beispiel für ein Meteogramm über 4 Tage mit 3 Stunden Auflösung:&lt;br /&gt;
&lt;br /&gt;
[[File:DWDODmeteogram4d3h.png|500px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Beispiel für die Einrichtung eines Weblinks ===&lt;br /&gt;
Zur graphischen Darstellung der Vorhersage und der Wetterwarnungen mit [[FHEMWEB]] steht das Modul [https://raw.githubusercontent.com/jnsbyr/fhem/master/FHEM/99_DWD_OpenData_Weblink.pm 99_DWD_OpenData_Weblink.pm] zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
Zunächst die Moduldatei herunterladen und in das Modulverzeichnis &#039;&#039;fhem/FHEM&#039;&#039; kopieren. Entweder die Datei direkt auf den FHEM-Server herunterladen (z.B. mit &#039;&#039;wget&#039;&#039;) oder beim indirekten Herunterladen darauf achten, dass dabei das Encoding nicht verändert wird (also z.B. bei WinSCP den Binär-Modus und nicht den Text-Modus verwenden). Ansonsten werden später z.B. Sonderzeichen wie &#039;&#039;°C&#039;&#039; falsch angezeigt. &lt;br /&gt;
&lt;br /&gt;
Anschließend kann in die [[Konfiguration]] z.B. folgendes eingetragen werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 define DWD_Weblink_Generator DWD_OpenData_Weblink&lt;br /&gt;
 attr DWD_Weblink_Generator IODev DWD&lt;br /&gt;
 attr DWD_Weblink_Generator forecastDays 4&lt;br /&gt;
 # refreshRate nur dann setzten, wenn der Browser Java-Script beherrscht:&lt;br /&gt;
 attr DWD_Weblink_Generator refreshRate 900&lt;br /&gt;
 &lt;br /&gt;
 define DWD_Weblink weblink htmlCode { DWD_OpenData_Weblink::AsHtmlH(&amp;quot;DWD_Weblink_Generator&amp;quot;) } &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Damit legt man das Weblink-Generator-Device an und verknüpft es mit dem DWD_OpenData-Device. Außerdem wird der [[weblink ]] selbst angelegt, der seinerseits mit dem Weblink-Generator-Device verknüpft wird. Der Weblink benötigt für seine Funktion eine bestimmte Auswahl der Vorhersage-Merkmale. Wer das Attribut &#039;&#039;forecastProperties&#039;&#039; des DWD_OpenData-Moduls anpassen will, muss diese Merkmale auf jeden Fall mit berücksichtigen. &lt;br /&gt;
&lt;br /&gt;
Wenn vom Weblink nichts im Browser zu sehen ist, kann das daran liegen, dass der Browser kein aktuelles JavaScript verwendet oder JavaScript deaktiviert ist. Dann sollte das Attribut &#039;&#039;refreshRate&#039;&#039; auf 0 Sekunden eingestellt oder gelöscht werden. Mit aktiviertem Refresh werden die Daten auch ohne Seitenneuaufbau regelmäßig und bei Tab-Wechsel aktualisiert.&lt;br /&gt;
&lt;br /&gt;
Die Liste der erforderlichen Vorhersage-Merkmale finden sich zusammen mit allen weiteren Details zur Installation und Konfiguration in der Modulhilfe von &#039;&#039;99_DWD_OpenData_Weblink.pm&#039;&#039;, die man z.B. nach dem Anlegen des Weblink-Generator-Devices über die Weboberfläche abrufen kann.&lt;br /&gt;
&lt;br /&gt;
Hier ein Ausschnitt aus der Darstellung des Weblinks mit [[FHEMWEB]]:&lt;br /&gt;
&lt;br /&gt;
[[File:DWDODweblink.png|500px]]&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=99_myUtils_anlegen&amp;diff=38689</id>
		<title>99 myUtils anlegen</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=99_myUtils_anlegen&amp;diff=38689"/>
		<updated>2023-11-09T10:45:34Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: veraltete &amp;quot;source&amp;quot;-Angaben in &amp;quot;syntaxhighlight&amp;quot; geändert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Die Speicherung von Perl-Code unmittelbar in [[Eventhandler|Eventhandlern]], [[Timehandler|Timehandlern]] oder anderen Geräten in der [[Konfiguration]], in denen Perl-Ausdrücke angegeben werden können, wird mit wachsender Zahl von Geräten und Logiken eventuell unübersichtlich. Um z.B. Doppelungen zu vermeiden und Logikbausteine zentral vorzuhalten, kann man eine oder mehrere eigene Programmdateien erzeugen, in der diese als kleine Programme gesammelt und dann aus entsprechenden Geräten aufgerufen werden können.&lt;br /&gt;
== Eine neue Programmdatei erzeugen ==&lt;br /&gt;
FHEM enthält eine Vorlage &#039;&#039;myUtilsTemplate.pm&#039;&#039;, die zur Erzeugung von Programmdateien genutzt werden sollte; nachfolgend soll beispielhaft eine Datei namens &#039;&#039;99_myUtils.pm&#039;&#039; verwendet werden. &lt;br /&gt;
Vorgehensweise:&lt;br /&gt;
* FHEM-Menüpunkt {{Taste|Edit files}} anklicken&lt;br /&gt;
* Weblink &#039;&#039;myUtilsTemplate.pm&#039;&#039; anklicken&lt;br /&gt;
* Im Textfeld hinter &#039;&#039;Save as&#039;&#039; den Dateinamen &#039;&#039;99_myUtils.pm&#039;&#039; für die Programmdatei  eintragen&lt;br /&gt;
: Hinweis: Wenn ein anderer Dateiname angegeben wird, muss der Name Initialize-Routine entsprechend angepasst werden (siehe nachfolgende Erläuterung zur Grundstruktur unter Nr. 3)&lt;br /&gt;
* {{Taste|Save as}} anklicken&lt;br /&gt;
Nun ist die eigene Programmdatei &#039;&#039;99_myUtils.pm&#039;&#039; mit der notwendigen Grundstruktur unter dem Menüpunkt &#039;&#039;Edit files&#039;&#039; zur Bearbeitung mit dem [[codemirror|Integrierter Editor]] zu finden. Für eine einfache und fehlerminimierende Bearbeitung sollten die [[Konfiguration#Syntaxhervorhebung|Syntaxhervorhebungs-, Befehlsauswahl- und Befehlsvervollständigungsfunktionen]] im Integrierten Editor eingeschaltet sein.&lt;br /&gt;
&lt;br /&gt;
{{Randnotiz|RNTyp=g|RNText=Nutzt man {{Link2CmdRef|Lang=en|Anker=configDB|Label=configDB}}, können (bzw. sollten) die eigenen Programmdateien in die Datenbank importiert werden, statt unmittelbar im Dateisystem gespeichert zu bleiben. Sie können dann weiter über {{Taste|Edit files}} bearbeitet werden, stehen dann aber z.B. bei einem Umzug oder Neuaufsetzen des Systems direkt wieder zur Verfügung.}}&lt;br /&gt;
Die Programmdateien können zwar auch mit einem [[Konfiguration#Externer Editor|externen Editor]] bearbeitet werden, diese Vorgehensweise wird jedoch nicht empfohlen, da dies insbesondere Einsteigern das debugging erschwert.&lt;br /&gt;
&lt;br /&gt;
Eine ‚leere‘ Programmdatei muss grundsätzlich folgenden Grundstruktur besitzen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
 package main;&lt;br /&gt;
 use strict;&lt;br /&gt;
 use warnings;&lt;br /&gt;
&lt;br /&gt;
 sub&lt;br /&gt;
 myUtils_Initialize($$)&lt;br /&gt;
 {&lt;br /&gt;
   my ($hash) = @_;&lt;br /&gt;
 }&lt;br /&gt;
 1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Folgende Dinge sind für eigene Programmdateien besonders zu beachten:&lt;br /&gt;
&lt;br /&gt;
# Der Dateiname muss mit 99_ beginnen. FHEM lädt beim Start alle Programmdateien mit dem prefix 99_. Andere Programmdateien werden erst dann geladen, wenn sie durch eine define-Anweisung in der [[Konfiguration]] angefordert werden. So wird z.B. 10_FS20.pm erst geladen, wenn beim Einlesen der Konfiguration das erste define für ein FS20-device abgearbeitet wird. Da Ihre eigene Programmsammlung wahrscheinlich kein neues Gerät mit einem zugehörigen define-Befehl implementiert, würde sie also nie geladen, wenn ihr Name nicht mit 99_ beginnt.&lt;br /&gt;
# Damit die neue Datei bei &#039;&#039;Edit files&#039;&#039; angezeigt wird, muss sie mit &#039;&#039;.pm&#039;&#039; enden und den Bestandteil &#039;&#039;Utils&#039;&#039; enthalten. Also zum Beispiel &#039;&#039;99_meineUtils.pm&#039;&#039; oder &#039;&#039;99_myUtils_Homematic.pm&#039;&#039;.&lt;br /&gt;
# Der Name der Programmdatei muss mit dem Namen der Initialize-Routine übereinstimmen. Wenn Sie Ihr Programm also 99_Werkzeugkasten.pm nennen, muss die im code dargestellte initialize-Routine sub Werkzeugkasten_Initialize heißen.&lt;br /&gt;
# Die Zeile &amp;lt;code&amp;gt; 1; &amp;lt;/code&amp;gt; muss immer die letzte Programmzeile sein. Wenn Sie also eigene Routinen in Ihre Programmsammlung einfügen, tragen Sie diese zwischen dem Ende der Initialize-Routine und der abschließenden Zeile &amp;lt;code&amp;gt; 1; &amp;lt;/code&amp;gt; ein.&lt;br /&gt;
&lt;br /&gt;
== Eigene Routinen einfügen ==&lt;br /&gt;
Als Beispiel dient das Umsetzen von FS20 toggle-Events aus dem Artikel &amp;quot;[[FS20 Toggle Events auf On/Off umsetzen]]&amp;quot;.&lt;br /&gt;
Das gesamte Programm sieht dann folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
package main;&lt;br /&gt;
use strict;&lt;br /&gt;
use warnings;&lt;br /&gt;
&lt;br /&gt;
sub&lt;br /&gt;
myUtils_Initialize($$)&lt;br /&gt;
{&lt;br /&gt;
  my ($hash) = @_;&lt;br /&gt;
}&lt;br /&gt;
##########################################################&lt;br /&gt;
# Untoggle&lt;br /&gt;
# toggle-Vorgänge in den Status on/off umsetzen&lt;br /&gt;
sub Untoggle($) {&lt;br /&gt;
  my ($obj) = @_;&lt;br /&gt;
&lt;br /&gt;
  if( Value($obj) eq &amp;quot;toggle&amp;quot; ){&lt;br /&gt;
    if( OldValue($obj) eq &amp;quot;off&amp;quot; ) {&lt;br /&gt;
      fhem( &amp;quot;setstate $obj on&amp;quot; );&lt;br /&gt;
    }&lt;br /&gt;
    else {&lt;br /&gt;
      fhem( &amp;quot;setstate $obj off&amp;quot; );&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  else {&lt;br /&gt;
    fhem( &amp;quot;setstate $obj &amp;quot;.Value($obj) );&lt;br /&gt;
  } &lt;br /&gt;
}&lt;br /&gt;
1;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Der Aufruf erfolgt dann z.B. so:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;pre&amp;gt;#fhem.cfg&lt;br /&gt;
define lampe_untoggle notify lampe {Untoggle(&amp;quot;$NAME&amp;quot;)}&amp;lt;/pre&amp;gt;&lt;br /&gt;
Der Aufruf aus einem notify (oder at) erfolgt als Perl-code, muss also in geschweiften Klammern stehen. Der Aufruf erfolgt durch Angabe des Namens der Routine (Untoggle) unter Angabe der zu übergebenden Parameter (hier &amp;quot;$NAME&amp;quot;).&lt;br /&gt;
Im Programm wurde die Routine Untoggle mit &#039;&#039;&#039;einem&#039;&#039;&#039; Parameter definiert ( Untoggle($) , die Anzahl der $-Zeichen bestimmt die Anzahl der zu übergebenden Parameter). Der Wert des übergebenen Parameters wird in der ersten Programmzeile in die Variable $obj übernommen (my ($obj) = @_; ). &lt;br /&gt;
Der Aufruf erfolgt mit Untoggle(„$NAME“) . Der Platzhalter $NAME in fhem steht für den Namen des Geräts. Im o.g. Beispiel erfolgt der Aufruf also eigentlich mit Untoggle(„lampe“). Natürlich können beim Aufruf auch feste Werte ( „lampe1“ ) oder Variablen ( $hour ) übergeben werden.&lt;br /&gt;
&lt;br /&gt;
=== Routinen mit mehreren Parametern ===&lt;br /&gt;
In der Definition der Routine geben Sie außerdem an, wieviele Parameter übergeben werden sollen, für 2 Parameter z.B. so:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;define test at *09:00 { wakeup($we, &amp;quot;Schlafzimmerlampe&amp;quot;) }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Die Deklaration der Routine in Ihrer Programmdatei muss dann so beginnen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;#Nur am Wochenende eingeschaltet&lt;br /&gt;
sub wakeup($$) {&lt;br /&gt;
  my ($wochenende, $device) = @_;&lt;br /&gt;
  if ($wochenende) {&lt;br /&gt;
    fhem( &amp;quot;set $device on&amp;quot; );&lt;br /&gt;
  }&lt;br /&gt;
  else {&lt;br /&gt;
    fhem( &amp;quot;set $device off&amp;quot; );&lt;br /&gt;
  }&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Durch die Anzahl der $-Zeichen in der Routinen-Deklaration wird also die Anzahl der Parameter festgelegt. In der ersten Programmzeile Ihrer Routine übernehmen Sie dann die übergebenen Parameterwerte in lokale Variablen. Wie beim Routinen-Aufruf muss auch hierbei die Anzahl der Parameter mit der Routinen-Deklaration (also Anzahl der $-Zeichen) übereinstimmen&amp;lt;ref&amp;gt;Mehr zu diesen sog. prototypes ist z.B. [https://perldoc.perl.org/perlsub.html#Prototypes hier] nachzulesen; auch [[fhem.pl]] beginnt mit einer Liste der prototyes der darin enthaltenen Funktionen. Da diese Funktionen auch innerhalb der myUtils verwendet werden können, empfiehlt es sich, zunächst dort nachzusehen, ob eventuell bereits hilfreiche Funktionen für das zu lösende Problem vorhanden sind.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Routinen ohne Parameter ===&lt;br /&gt;
Auch Routinen ohne Parameter sind natürlich möglich. Definition und Aufruf sehen dann folgendermassen aus:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;sub parameterlos() {&lt;br /&gt;
  ...&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 { parameterlos() }&lt;br /&gt;
&lt;br /&gt;
== Eigene Programmdatei laden ==&lt;br /&gt;
Die Programmdatei wird beim FHEM-Start immer automatisch geladen. &lt;br /&gt;
&lt;br /&gt;
Bei Änderungen an der Programmdatei bei laufendem FHEM ist bezüglich Neuladen ohne FHEM-Neustart zwischen den verschiedenen Bearbeitungsvarianten der Progammdatei zu unterscheiden.&lt;br /&gt;
&lt;br /&gt;
Bei der Bearbeitung über den &#039;&#039;&#039;Integrierten Editor&#039;&#039;&#039; wird die Programmdatei beim Abspeichern automatisch mit den Änderungen neu geladen.&lt;br /&gt;
&lt;br /&gt;
Bei der nicht empfohlenen Bearbeitung der Programmdatei mit einem &#039;&#039;&#039;externen Editor&#039;&#039;&#039; muss FHEM manuell angewiesen werden, die Programmdatei mit den Änderungen zu laden. Also bearbeiten Sie Ihr Programm, speichern die Programmdatei, und weisen FHEM dann explizit an, die Programmdatei erneut zu laden. Der Befehl dazu, der in das Befehls-Eingabefeld eingegeben wird, lautet: &amp;lt;code&amp;gt;reload 99_myUtils.pm&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Treten beim Laden (Syntax)fehler auf, werden diese am Bildschirm wie auch im Log angezeigt. Da der Ladevorgang fehlgeschlagen ist, stehen Ihre eigenen Routinen nun nicht zur Verfügung (bzw. in der zuletzt erfolgreich geladenen Version). Es empfiehlt sich daher bei der Entwicklung neuer Code-Teile v.a. für &amp;quot;Einsteiger&amp;quot;, diese zunächst in einer separaten myUtils-Datei zu entwickeln und erst dann in die für den &amp;quot;produktiven Betrieb&amp;quot; genutzten myUtils-Dateien zu übernehmen, wenn sie als funktional getestet anzusehen sind.&lt;br /&gt;
== Eigene Programmdatei dokumentieren ==&lt;br /&gt;
In der lokalen Commandref kann man die eigenen Routinen auch dokumentieren.&lt;br /&gt;
Dazu muss am Ende der 99_myUtils folgender Codeblock eingefügt werden&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
=pod&lt;br /&gt;
=begin html&lt;br /&gt;
&lt;br /&gt;
&amp;lt;a id=&amp;quot;myUtils&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;myUtils&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
  &amp;lt;b&amp;gt;Name&amp;lt;/b&amp;gt;&lt;br /&gt;
  &amp;lt;br&amp;gt;&lt;br /&gt;
  Text&amp;lt;br&amp;gt;&lt;br /&gt;
  Examples:&lt;br /&gt;
  &amp;lt;ul&amp;gt;&lt;br /&gt;
   &amp;lt;code&amp;gt;Example Code &amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
  &amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=end html&lt;br /&gt;
=begin html_DE&lt;br /&gt;
&lt;br /&gt;
&amp;lt;a id=&amp;quot;myUtils&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&lt;br /&gt;
&amp;lt;h3&amp;gt;myUtils&amp;lt;/h3&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=end html_DE&lt;br /&gt;
=cut&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der a Tag stellt einen Verweis dar, der h3 Tag kennzeichnet die Überschrift. Beide Tags müssen sein, ansonsten kann FHEM die Doku nicht in die commandref einbinden. Der Abschnitt für die deutsche Doku kann komplett fehlen. Die Beschreibungen der einzelnen Routinen werden mit ul Tags geklammert und eventuell mit ul Tags weiter untergliedert. Dabei entsteht ein eingerückter Text. Beispiele können mit dem code Tag formatiert werden.&lt;br /&gt;
&lt;br /&gt;
Mit diesem Befehl kann die Erzeugung des Commandrefeintrages initiiert und getestet werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;{system(&amp;quot;/usr/bin/perl ./contrib/commandref_join.pl&amp;quot;)}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Für eine schnelle Überprüfung des Commandrefeintrages können Sie auch &amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;help myUtils&amp;lt;/syntaxhighlight&amp;gt; (bzw. statt myUtils den Namen Ihrer Utils-Datei) eingeben.&lt;br /&gt;
&lt;br /&gt;
Weiterführende Hinweise sind in den [[Guidelines zur Dokumentation]] zu finden.&lt;br /&gt;
&lt;br /&gt;
== Weitere Informationen ==&lt;br /&gt;
=== Globale Ablage von Daten ===&lt;br /&gt;
Um Daten zentral zwischenzuspeichern, kann man &lt;br /&gt;
* die Funktionen &#039;&#039;[[DevelopmentModuleAPI#setKeyValue|setKeyValue()]]&#039;&#039; bzw. &#039;&#039;getKeyValue()&#039;&#039; nutzen, um die Daten im Dateisystem abzulegen;&lt;br /&gt;
* in den globalen Hash &#039;&#039;%data schreiben&#039;&#039;, wie in diesem {{Link2Forum|Topic=63737|LinkText=Forumsbeitrag}} erläutert.&lt;br /&gt;
&lt;br /&gt;
=== Vertiefende Informationen ===&lt;br /&gt;
Weiterführende Hinweise, z.B. wie aus einer Sammlung kleiner Tools ggf. ein eigenes Modul entstehen kann, sind der [[DevelopmentModuleIntro]] zu entnehmen. Dort sind v.a. auch einige häufig benötigte Funktionen aus fhem.pl dokumentiert.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Eine Zusammenstellung wichtiger Funktionen ist in den Perl specials der {{Link2CmdRef|Anker=perl|Label=commandref}} enthalten.&lt;br /&gt;
* Eine weitere Sammlung hilfreicher &amp;quot;Helferlein&amp;quot; samt Hilfe enthält [https://svn.fhem.de/trac/browser/trunk/fhem/FHEM/99_Utils.pm 99_Utils.pm].&lt;br /&gt;
* Hilfsfunktionen für Farboperationen: [[Color]].&lt;br /&gt;
* [[Zeitangaben, rechnen mit|Wiki-Beitrag zum Rechnen mit Zeitangaben]]&lt;br /&gt;
* [[Gleitende Mittelwerte berechnen und loggen]]&lt;br /&gt;
* Beispiele für Geräteüberwachungen: [[EBUS#Mithilfe von FHEM|EBUS]], [[Netzwerkgeräte:_Verfügbarkeit_prüfen#Erweiterung 99 myUtils|Netzwerkgeräte]], {{Link2Forum|Topic=51267|Message=935071|LinkText=Nextion-Display bei Inaktivität zurücksetzen}}, {{Link2Forum|Topic=97173|Message=917347|LinkText=devStateIcon für das Modul &#039;&#039;monitoring&#039;&#039;}}&lt;br /&gt;
* [[Batterieüberwachung#Alternativ per Skript|Batterieüberwachung]]&lt;br /&gt;
* Routine zum [[E-Mail_senden#Raspberry Pi|E-Mail senden]] aus FHEM heraus&lt;br /&gt;
* [[E-Mail per notify nach Zeitablauf erneut senden|Beispiel]], wie ggf. an mehreren Stellen relevante Variablen zentral zur Verfügung gestellt werden können.&lt;br /&gt;
* [[Plot-Abriss_vermeiden#Implementierung|Plot-Abrisse vermeiden]]&lt;br /&gt;
* Formatierungsanweisungen auslagern: [[ReadingsGroup#Enigma_Receiver|ReadingsGroup]], [[Spritpreismonitor#Farbliche_Hervorhebung|Spritpreismonitor]], [[EBUS-MQTT2#myUtils-Code|Balkenanzeige]] (hier: für EBUS)&lt;br /&gt;
* Befehle an ein Netzwerkgerät senden: [[Listenlive#Der Code|Listenlive]]&lt;br /&gt;
* [[HM-Dis-WM55_Funk_Statusanzeige#99_myUtils|Homematic-Display]] mit Informationen versorgen&lt;br /&gt;
* {{Link2Forum|Topic=34363|Message=266811|LinkText=Zeit- und Datumsvariablen $hour, $wday, $month, ... in 99_myUtils.pm verfügbar machen}}&lt;br /&gt;
* {{Link2Forum|Topic=36504|Message=287778|LinkText=Globale und flexible Fenster- und Türüberwachung}}&lt;br /&gt;
* {{Link2Forum|Topic=87895|Message=803439|LinkText=57_CALENDAR.pm - events mit deviceNames nutzen}}&lt;br /&gt;
* {{Link2Forum|Topic=96959|Message=901268|LinkText=Konstanten für das Rechnen mit Zeiten}}&lt;br /&gt;
* {{Link2Forum|Topic=97430|Message=906576|LinkText=devStateIcon-Code für Homematic-Thermostate}}&lt;br /&gt;
* {{Link2Forum|Topic=86073|Message=836537|LinkText=php-Script aufrufen und Rückgabewert in einen dummy schreiben}} (hier: Viessmann Heizung))&lt;br /&gt;
* {{Link2Forum|Topic=84831|Message=771485|LinkText=Windchill und Hitzeindex berechnen}}&lt;br /&gt;
* {{Link2Forum|Topic=84016|Message=762888|LinkText=Countdown Timer}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
[[Kategorie:Code Snippets]]&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;br /&gt;
[[Kategorie:Perl]]&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=PRESENCE&amp;diff=38688</id>
		<title>PRESENCE</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=PRESENCE&amp;diff=38688"/>
		<updated>2023-11-09T10:36:56Z</updated>

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

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

		<summary type="html">&lt;p&gt;Drhirn: Baustelle entfernt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=Anwesenheitserkennung von Bluetooth-Geräten&lt;br /&gt;
|ModType=u&lt;br /&gt;
|ModFTopic=127173&lt;br /&gt;
|ModForumArea=Unterstützende Dienste&lt;br /&gt;
|ModTechName=ble2mqtt&lt;br /&gt;
|ModOwner=PatrickR&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;ble2mqtt&#039;&#039;&#039; ist ein Script, dass den Anwesenheitsstatus eines oder mehrerer Bluetooth Low Energy Geräte überprüfen und das Ergebnis an einen MQTT Broker schicken kann.&lt;br /&gt;
&lt;br /&gt;
Es verwendet dazu die Linux Tools &#039;&#039;bluetoothctl&#039;&#039; und &#039;&#039;gatttool&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
ble2mqtt ist in Perl geschrieben und wurde von {{Link2FU|5068|PatrickR}} erstellt. Weitere Informationen finden sich in diesem {{Link2Forum|Topic=127173|LinkText=Forums-Topic }}. Fragen dazu bitte in den Bereich [https://forum.fhem.de/index.php?board=44.0 Unterstützende Dienste]&lt;br /&gt;
&amp;lt;!--diesen {{Link2Forum|Area=44|LinkText=Bereich }}.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Voraussetzungen==&lt;br /&gt;
* Debian od. Raspberry Pi OS&lt;br /&gt;
* Bluetooth Empfänger&lt;br /&gt;
&lt;br /&gt;
==Parameter==&lt;br /&gt;
Beim Start von ble2mqtt können folgende Parameter angegeben werden:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Parameter!!Beschreibung!!Standardwert!!Beispiel!!Optional&lt;br /&gt;
|-&lt;br /&gt;
| --mqttserver&lt;br /&gt;
|Die Adresse des MQTT Brokers inklusive Port&lt;br /&gt;
|&lt;br /&gt;
| --mqttserver mqtt.example.org:1883&lt;br /&gt;
|nein&lt;br /&gt;
|-&lt;br /&gt;
| --mqttfingerprint&lt;br /&gt;
|Der Fingerprint des für die TLS-verschlüsselte Kommunikation mit dem MQTT Broker verwendeten Zertifikates&lt;br /&gt;
|&lt;br /&gt;
| --mqttfingerprint bfe5d244a821194230f1479fe2f8f7bbcd2a8cb8&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --mqtttopic&lt;br /&gt;
| An welches MQTT-Topic das Tool die Informationen schicken soll.&lt;br /&gt;
|ble2mqtt&lt;br /&gt;
| --mqtttopic ble2mqtt/Wohnzimmer&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --mqttuser&lt;br /&gt;
|Der Benutzernamen, unter dem die Verbindung zum Broker hergestellt werden soll&lt;br /&gt;
|&lt;br /&gt;
| --mqttuser ble2mqtt&lt;br /&gt;
|ja bzw. abhängig vom Broker&lt;br /&gt;
|-&lt;br /&gt;
| --mqttpass&lt;br /&gt;
|Das zum Benutzernamen gehörende Passwort&lt;br /&gt;
|&lt;br /&gt;
| --mqttpass verysecret3&lt;br /&gt;
|ja bzw. abhängig vom Broker&lt;br /&gt;
|-&lt;br /&gt;
| --retain&lt;br /&gt;
|Versendet die Nachrichten present und lastseen als retained.&lt;br /&gt;
|0&lt;br /&gt;
| --retain&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --daemonize&lt;br /&gt;
|Wenn ble2mqtt im Hintergrund (als Daemon) ausgeführt werden soll&lt;br /&gt;
|0&lt;br /&gt;
| --daemonize&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --loglevel&lt;br /&gt;
|Wie und was genau protokolliert werden soll. Mögliche Loglevel sind LOG_CRIT, LOG_ERR, LOG_WARNING, LOG_NOTICE, LOG_INFO, LOG_DEBUG.&lt;br /&gt;
|LOG_INFO&lt;br /&gt;
| --loglevel LOG_ERR&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --logtarget&lt;br /&gt;
|Wohin gelogged werden soll. Mögliche Optionen sind &#039;&#039;syslog&#039;&#039; und &#039;&#039;stdout&#039;&#039;.&lt;br /&gt;
|syslog&lt;br /&gt;
| --logtarget stdout&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --absentinterval&lt;br /&gt;
|Anzahl an Sekunden, nach denen das Gerät als abwesend bezeichnet werden soll. Mindestwert ist 30.&lt;br /&gt;
|60&lt;br /&gt;
| --absentinterval 120&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --rssithreshold&lt;br /&gt;
|Ab welcher Abweichung des RSSI Wertes ein Update getriggert werden soll. Mindestwert ist 5.&lt;br /&gt;
|10&lt;br /&gt;
| --rssithreshold 8&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --watchdogthreshold&lt;br /&gt;
|Ab welchem Zeitraum in Sekunden nach Empfangen des letzten BT-Signals ble2mqtt neu gestartet werden soll. Mindestwert ist 30. Der Wert 0 bedeutet deaktiviert, also nie.&lt;br /&gt;
|0&lt;br /&gt;
| --watchdogthreshold 30&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --debug&lt;br /&gt;
|Kann nur gemeinsam mit --daemonize verwendet werden, um Logeinträge auf stdout auszugeben. Je höher die Nummer, desto mehr Output.&lt;br /&gt;
|0&lt;br /&gt;
| --daemonize --debug 4&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --mac&lt;br /&gt;
|Filtert mittels Regex nach MAC-Adressen der von ble2mqtt zu beachtenden BLE-Geräte. Alle anderen Geräte werden ignoriert.&lt;br /&gt;
|&lt;br /&gt;
| --mac &#039;(11:22:33:44:55:66|77:88:99:00:AA:BB)&#039;&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --batterymaxage&lt;br /&gt;
|Zeit in Stunden, nach denen ein Batterie-Wert als veraltet angesehen und aktualisiert wird. Der Wert 0 deaktiviert den Batterie-Check.&lt;br /&gt;
|48&lt;br /&gt;
| --batterymaxage 6&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --forcebattery&lt;br /&gt;
|Nur in Kombination mit --mac. Erzwingt einen Batterie-Check, auch wenn das battery-service am Gerät nicht erkannt wird.&lt;br /&gt;
|0&lt;br /&gt;
| --forcebattery&lt;br /&gt;
|ja&lt;br /&gt;
|}&lt;br /&gt;
===Beispiele===&lt;br /&gt;
* Broker verlangt Username/Passwort; es sollen keine Batterie-Werte ausgelesen werden&lt;br /&gt;
 ble2mqtt --mqttserver mqtt.example.org:1883 --mqttuser ble2mqtt --mqttpass verysecret3 --batterymaxage 0&lt;br /&gt;
&lt;br /&gt;
* Broker verlangt keine Authentifizierung; es soll nach zwei G-Tags gesucht werden; definiertes MQTT-Topic; Batteriewerte benötigt&lt;br /&gt;
 ble2mqtt --mqttserver mqtt.example.org:1883 --mqtttopic ble2mqtt/Wohnzimmer --mac &#039;(11:22:33:44:55:66|77:88:99:00:AA:BB)&#039;&lt;br /&gt;
&lt;br /&gt;
* Broker verlangt keine Authentifizierung; Geräte sollen nach 45s ohne Kontakt als abwesend angezeigt werden; MQTT Nachrichten sollen gespeichert bleiben&lt;br /&gt;
 ble2mqtt --mqttserver mqtt.example.org:1883 --absentinterval 45 --retain&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
Zur Installation muss das ble2mqtt-Script auf den Server kopiert werden und es müssen diverse Linux- und Perl-Pakete installiert werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zuerst das Script nach /usr/local/bin kopieren, um beim Aufruf in der Bash nicht immer den ganzen Pfad voranstellen zu müssen.&lt;br /&gt;
 sudo cp -a ble2mqttd /usr/local/bin/&lt;br /&gt;
Danach das Script noch als ausführbar markieren&lt;br /&gt;
 sudo chmod +x /usr/local/bin/ble2mqttd&lt;br /&gt;
&lt;br /&gt;
===Benötigte Linux Pakete===&lt;br /&gt;
Die benötigten Pakete können ganz einfach mit &#039;&#039;apt&#039;&#039; installiert werden. Dabei werden auch mögliche Abhängigkeiten automatisch installiert.&lt;br /&gt;
&lt;br /&gt;
 sudo apt install -y libssl-dev libio-socket-ssl-perl libreadonly-perl libtest-expect-perl libnet-ssleay-perl libnet-server-perl&lt;br /&gt;
&lt;br /&gt;
===Benötigte Perl-Module===&lt;br /&gt;
Es wird das Modul &#039;&#039;Net::MQTT::Simple&#039;&#039; (&#039;&#039;libnet-mqtt-simple-perl&#039;&#039;) benötigt. Das ist - Stand 08.11.2023 - noch nicht in den Stable-Repositories von Debian verfügbar und muss daher mittels &#039;&#039;cpan&#039;&#039; installiert werden. Voraussetzung dafür ist das Modul &#039;&#039;CPAN::DistnameInfo&#039;&#039;, welches zuerst installiert werden muss.&lt;br /&gt;
&lt;br /&gt;
 sudo cpan CPAN::DistnameInfo&lt;br /&gt;
 sudo cpan Net::MQTT::Simple&lt;br /&gt;
&lt;br /&gt;
Sobald &#039;&#039;libnet-mqtt-simple-perl&#039;&#039; verfügbar ist, kann dieses statt der Perl-Module wie ein normales Linux-Paket installiert werden.&lt;br /&gt;
&lt;br /&gt;
===Erster Test===&lt;br /&gt;
Mit einem einfachen Aufruf von &#039;&#039;&#039;ble2mqtt&#039;&#039;&#039; kann getestet werden, ob alle benötigten Module und Pakete vorhanden sind.&lt;br /&gt;
&lt;br /&gt;
 sudo /usr/local/bin/ble2mqttd&lt;br /&gt;
&lt;br /&gt;
===Erstellen einens Systemd-Daemons===&lt;br /&gt;
Damit &#039;&#039;&#039;ble2mqtt&#039;&#039;&#039; bei jedem Systemstart automatisch gestartet wird, muss ein Systemd-Daemon erstellt werden. Das wird gemacht, in dem eine neue Textdatei mit folgendem Inhalt angelegt und der Daemon dann aktiviert wird.&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|&#039;&#039;&#039;Wichtig:&#039;&#039;&#039; Das Kommando, mit welchen Parametern ble2mqtt gestartet wird, muss natürlich individuell angepasst werden!}}&lt;br /&gt;
&lt;br /&gt;
 sudo nano /etc/systemd/system/ble2mqttd.service&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=ble2mqttd&lt;br /&gt;
After=bluetooth.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
Restart=always&lt;br /&gt;
ExecStart=/usr/local/bin/ble2mqttd --mqttserver mqtt.example.com:1883 --mqtttopic ble2mqtt/wohnzimmer --mac &#039;(11:22:33:44:55:66|77:88:99:00:AA:BB)&#039; --absentinterval 30 --mqttuser &amp;lt;username&amp;gt; --mqttpass &amp;lt;password&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 sudo systemctl daemon-reload&lt;br /&gt;
 sudo systemctl enable ble2mqttd.service&lt;br /&gt;
 sudo systemctl start ble2mqttd.service&lt;br /&gt;
&lt;br /&gt;
==Einbindung in FHEM==&lt;br /&gt;
Da ble2mqtt alle Informationen an einen [[MQTT]]-Broker sendet, können diese Informationen ganz einfach als [[MQTT2_DEVICE]] in FHEM eingebunden werden. Wie dabei vorgegangen werden kann, unterscheidet sich je nach Anwendungsbereich und den eigenen Vorlieben.&lt;br /&gt;
&lt;br /&gt;
Als Beispiel sie hier die Anwesenheitserkennung mittels BT-Tags angeführt.&lt;br /&gt;
&lt;br /&gt;
===Anwesenheitserkennung mittels BT-Tags===&lt;br /&gt;
[[File:ble2mqtt.png|thumb|Readings eines Devices, dass mit diesem Code erstellt wurde]]&lt;br /&gt;
Der folgende Code geht davon aus, dass es mehrere ble2mqtt-Instanzen gibt und ein BT-Tag mit der MAC-Adresse AA:BB:CC:DD:EE:FF erkannt werden soll.&lt;br /&gt;
&lt;br /&gt;
Die verschiedenen ble2mqtt-Instanzen schicken ihre Nachrichten in unterschiedliche Topics.&lt;br /&gt;
Für jede Instanz ein eigenes Topic:&lt;br /&gt;
*ble2mqtt/wohnzimmer&lt;br /&gt;
*ble2mqtt/schlafzimmer&lt;br /&gt;
*ble2mqtt/kueche&lt;br /&gt;
Im Attribut &#039;&#039;devicetopic&#039;&#039; werden diese Topics dann gemeinsam ausgewertet. Das funktioniert, in dem der Name des Subtopics einfach durch den Regex-Ausdruck &#039;&#039;.*&#039;&#039; ersetzt wird.&lt;br /&gt;
&lt;br /&gt;
Bedeutet aber auch, dass die Informationen - wenn gewünscht - wieder in unterschiedliche Readings zerlegt werden müssen. Um z.B. schnell zu erkennen, in welchem Raum der BT-Tag gerade liegt. Das passiert hier z.B. bei den Nachrichten für &#039;&#039;rssi&#039;&#039; und &#039;&#039;presence&#039;&#039;. Daraus resultieren dann eigene Readings für jedes MQTT-Subtopic.&lt;br /&gt;
&lt;br /&gt;
Das &amp;quot;raumübergreifende&amp;quot; Reading &#039;&#039;presence&#039;&#039; wird anhand der des Alters in Sekunden der letzten lastseen-Nachricht gesteuert. Die lastseen-Nachricht wird immer gesendet, wenn der Scanvorgang von ble2mqtt das gewünschte Gerät findet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
define ble2mqttGTag MQTT2_DEVICE FHEM&lt;br /&gt;
attr ble2mqttGTag devicetopic ble2mqtt/.*/AA_BB_CC_DD_EE_FF&lt;br /&gt;
attr ble2mqttGTag event-on-change-reading .*&lt;br /&gt;
attr ble2mqttGTag readingList ble2mqtt/.*/heartbeat:.* heartbeat&lt;br /&gt;
$DEVICETOPIC/rssi:.* {my $room=(split m{[/]}x,$TOPIC)[1]; my $roomMax=$room; my $rssiMax=$EVENT; my @readings = grep { $_ =~ m{\Arssi_(?!$room).*}x } keys %{$defs{&amp;quot;$NAME&amp;quot;}-&amp;gt;{READINGS}}; for (@readings) {my $rssiTmp=ReadingsVal($NAME,$_,&#039;-100&#039;); my $roomTmp=(split m{[_]}x,$_)[1]; if(($rssiMax gt $rssiTmp)&amp;amp;&amp;amp;(ReadingsVal($NAME,&amp;quot;presence_&amp;quot;.$roomTmp,&#039;absent&#039;) eq &#039;present&#039;)) {$rssiMax=$rssiTmp; $roomMax=$roomTmp}}; {rssi=&amp;gt;$rssiMax,room=&amp;gt;$roomMax,&amp;quot;rssi_$room&amp;quot;=&amp;gt;$EVENT}}&lt;br /&gt;
$DEVICETOPIC/lastseen:.* {lastseen=&amp;gt;strftime &amp;quot;%Y-%m-%d %H:%M:%S&amp;quot;, localtime($EVENT)}&lt;br /&gt;
$DEVICETOPIC/present:.* {my $roomAct=(split m{[/]}x,$TOPIC)[1]; my $rssi=ReadingsVal($NAME,&amp;quot;rssi_&amp;quot;.$roomAct,&#039;-100&#039;); my $presenceAct=$EVENT?&#039;present&#039;:&#039;absent&#039;; my $room=$EVENT ? $roomAct:&#039;&#039;; my @readings = grep { $_ =~ m{\Apresence_(?!$roomAct).*}x } keys %{$defs{$NAME}-&amp;gt;{READINGS}}; for (@readings) {if(ReadingsVal($NAME,$_,&#039;absent&#039;) eq &#039;present&#039;) {my $roomTmp=(split m{[_]}x,$_)[1]; my $rssiTmp=ReadingsVal($NAME,&amp;quot;rssi_&amp;quot;.$roomTmp,&#039;-100&#039;); if($rssi gt $rssiTmp){$room=$roomTmp; $rssi=$rssiTmp}}}; {&amp;quot;presence_$roomAct&amp;quot;=&amp;gt;$presenceAct, room=&amp;gt;$room}}&lt;br /&gt;
ble2mqtt/.*/state:.* state&lt;br /&gt;
$DEVICETOPIC/battery:.* batteryLevel&lt;br /&gt;
attr ble2mqttGTag userReadings presence {if (ReadingsAge($NAME,&amp;quot;lastseen&amp;quot;,0)&amp;gt;60) {return &amp;quot;absent&amp;quot;;}else{return &amp;quot;present&amp;quot;;}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Ergebnis ist unter anderem ein Reading &#039;&#039;presence&#039;&#039; mit den Zuständen &#039;&#039;absent&#039;&#039; und &#039;&#039;present&#039;&#039;. Es kann somit ganz einfach als &amp;quot;presenceDevice&amp;quot; in einem [[ROOMMATE]]-Device verwendet werden:&lt;br /&gt;
 attr rr_Franz rr_presenceDevices ble2mqttGTag&lt;br /&gt;
&lt;br /&gt;
[[Category:MQTT]][[Category:Anwesenheitserkennung]][[Category:FHEM Utilities]]&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Benutzer:Drhirn&amp;diff=38685</id>
		<title>Benutzer:Drhirn</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Benutzer:Drhirn&amp;diff=38685"/>
		<updated>2023-11-09T10:24:30Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: Die Seite wurde geleert.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FHEMWEB&amp;diff=38684</id>
		<title>FHEMWEB</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FHEMWEB&amp;diff=38684"/>
		<updated>2023-11-09T10:22:34Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: Hinweis auf zwei Beiträge im Wiki, die sich mit HTTPS beschäftigen, ergänzt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Modul&lt;br /&gt;
|ModPurpose=Standard Fhem-Webfrontend&lt;br /&gt;
|ModType=h&lt;br /&gt;
|ModForumArea=Frontends&lt;br /&gt;
|ModTechName=01_FHEMWEB.pm&lt;br /&gt;
|ModOwner=Rudolf König/rudolfkoenig ({{Link2FU|8|Forum}}/[[Benutzer Diskussion:Rudolfkoenig|Wiki]])&lt;br /&gt;
}}&lt;br /&gt;
{{Randnotiz|RNText=Eine FHEM-Installation kann mehrere FHEMWEB-Definitionen (mit je einem anderen Port) enthalten. Dies kann genutzt werden, um &lt;br /&gt;
* für andere Styles als f18 unterschiedliche Darstellungen für verschiedene Bildschirmgrößen zu erreichen, oder &lt;br /&gt;
* verschiedenen Darstellungen für mehrere Benutzer oder Anwendungsbereiche zu ermöglichen.}} &lt;br /&gt;
[[FHEMWEB]] ist das Standard Webfrontend von Fhem. Es implementiert auch einen einfachen Webserver (optional mit Basic-Auth und HTTPS). Aus historischen Gründen wird es auch als [[PGM2]] bezeichnet. FHEMWEB läuft voraussetzungslos.&lt;br /&gt;
&lt;br /&gt;
== Anpassungen ==&lt;br /&gt;
=== &#039;&#039;Themes&#039;&#039; ===&lt;br /&gt;
FHEMWEB kennt keine Themes im strengen Sinne. Man kann allerdings mit drei Dateien das Aussehen des Frontends anpassen. &lt;br /&gt;
&lt;br /&gt;
Zuerst ist ein Prefix zu vergeben, der das Theme beschreiben soll. Hier möge &#039;&#039;tufte&#039;&#039; als Beispiel dienen (siehe diesen {{Link2Forum|Topic=81637|Message=737465}}). Mit dem Attribut&lt;br /&gt;
:&amp;lt;code&amp;gt;attr &amp;lt;FHEMWEB-name&amp;gt; stylesheetPrefix tufte&amp;lt;/code&amp;gt;&lt;br /&gt;
würde man das entsprechende Theme auswählen. Dieses Theme wiederum setzt voraus, dass sich im Verzeichnis /opt/fhem/www/pgm2 drei Daten mit folgenden Namen befinden:&lt;br /&gt;
* tuftestyle.css: Diese Datei steuert das Layout des Frontends.&lt;br /&gt;
* tuftesvg_style.css: Diese Datei steuert das Layout bei der Einbindung der SVG-Grafiken.&lt;br /&gt;
* tuftesvg_defs.svg: Diese Datei steuert das Layout des SVG-Grafikinhaltes.&lt;br /&gt;
&lt;br /&gt;
=== Attribute ===&lt;br /&gt;
FHEMWEB besitzt mehrere Attribute, die das Aussehen des Frontends verändern können und im Folgenden näher beschrieben werden.&lt;br /&gt;
&lt;br /&gt;
=== devStateIcon ===&lt;br /&gt;
Das Attribut devStateIcon dient dazu, das anzuzeigende Icon eines Devices in Abhängigkeit vom Device-Status (STATE) in der Raumübersicht (room) festzulegen. Zudem kann man einstellen, was bei einem Klick auf das Icon geschieht. Details siehe [[devStateIcon]]&lt;br /&gt;
&lt;br /&gt;
=== sortby ===&lt;br /&gt;
Mit sortby können Elemente im Frontend sortiert werden. Es gibt zwei Beiträge zur Sortierung mit sortby im Forum: {{Link2Forum|Topic=11940|Message=70664}} und {{Link2Forum|Topic=26733|Message=197127}}&lt;br /&gt;
&lt;br /&gt;
=== title ===&lt;br /&gt;
Mit diesem Attribut kann der Titel der Seite gesetzt werden. Dadurch wird das globale Attribut &amp;quot;title&amp;quot; überschrieben, das ansonsten für alle FHEMWEB Instanzen gilt.&lt;br /&gt;
Im Forum gibt es ein Beispiel für einen dynamischen Seitentitel: {{Link2Forum|Topic=48668|Message=403260}}&lt;br /&gt;
&lt;br /&gt;
=== menuEntries ===&lt;br /&gt;
Mit menuEntries können weitere Einträge im Menü aufgenommen werden. Beispielsweise kann man so den Backup-Befehl einbinden. Unter dem Link [[Backup#Backup_manuell_ausf.C3.BChren_.28Weboberfl.C3.A4che.29|Backup-Befehl in FHEM-Menü einbinden]] ist dies näher erläutert.&lt;br /&gt;
&lt;br /&gt;
=== webCmd ===&lt;br /&gt;
Durch Doppelpunkte getrennte Auflistung von Befehlen, die für FHEMWEB gelten sollen (funktioniert nicht mit smallscreen).&lt;br /&gt;
&lt;br /&gt;
=== widgetOverride ===&lt;br /&gt;
Mit diesem Attribut kann man Bedienelemente, die vom Modulautor eigentlich vorgesehen waren, verändern.  Dies gilt insbesondere für set-Befehle, mit denen Parameter verändert werden.&lt;br /&gt;
&lt;br /&gt;
widgetOverride kennt mindestens zwei Parameter: Zuerst kommt der set-Befehl oder das webcmd, das überschrieben werden soll; dann ein Doppelpunkt und dann kommt das neu vorgesehene Bedienelement.&lt;br /&gt;
&lt;br /&gt;
Beispiele:&lt;br /&gt;
* [[WifiLight#Color-Picker_aktivieren|Color-Picker]]&lt;br /&gt;
* [[EnOcean-FUD61NPN-Funk-Universal-Dimmaktor#Anzeige_eines_alternativen_Bedienelementes|knob]]&lt;br /&gt;
* usuzu (= universelle Zeitschaltuhr): {{Link2Forum|Topic=32660}}&lt;br /&gt;
* weitere [[FHEMWEB/Widgets]]&lt;br /&gt;
&lt;br /&gt;
== Sicherheitsrelevante Anpassungen ==&lt;br /&gt;
=== csrfToken ===&lt;br /&gt;
FHEM hat mit der Version 5.8 eine Sicherheitsmaßnahme scharfgeschaltet, den csrfToken. Dieser Token wird bei jedem Neustart von FHEM neu gebildet.&lt;br /&gt;
Weitere Details finden sich im Wiki-Eintrag [[csrfToken-HowTo]]&lt;br /&gt;
&lt;br /&gt;
=== apiWeb Instanz ===&lt;br /&gt;
Die apiWeb Instanz dient dazu, externe Zugriffe auf das FHEM System kontrolliert zu steuern.&lt;br /&gt;
Im Grunde wird nichts anderes gemacht, als eine zweite FHEM Webinstanz einzurichten, welche dann gesondert abgesichert wird.&lt;br /&gt;
&lt;br /&gt;
Man legt sich hierfür eine FHEMWEB Instanz an:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define apiWEB FHEMWEB 8088 global&lt;br /&gt;
attr apiWEB column Alarms: Apartment: Living: Bedroom: Kitchen: Sonos: Residents: Weather: Bathroom: Logs: Statistics: DashboardRoom: System: hidden: all:&lt;br /&gt;
attr apiWEB hiddenroom input,detail,save,Unsorted,Everything,CUL_HM,FS20,Commandref,style,Edit files,Select style,Logfile,Floorplans,Remote doc,FileLogs,Apartment,Bathroom,Bedroom,Kitchen,Living,Residents,System,Weather,Event monitor,NEW&lt;br /&gt;
attr apiWEB room hidden&lt;br /&gt;
attr apiWEB webname webhook&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese wird dann weiter mit Hilfe eines [[allowed]]-Devices abgesichert, in dem nur die tatsächlich benötigten Kommandos erlaubt werden und damit alle anderen nicht erlaubten (attr,define,get,set,...) automatisch nicht mehr zur Verfügung stehen: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
define allowedApiWEB allowed&lt;br /&gt;
attr allowedApiWEB allowedCommands set&lt;br /&gt;
attr allowedApiWEB allowedDevices Lampe1&lt;br /&gt;
attr allowedApiWEB validFor apiWEB&lt;br /&gt;
attr allowedApiWEB allowedIfAuthenticatedByMe 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Desweiteren ist dringend anzuraten, den Zugriff über TLS/SSL und HTTP Basic-Authentication weiter abzusichern. Nähere Informationen findet man hierzu in der {{Link2CmdRef|Anker=FHEMWEB}} unter dem Punkt HTTPS und in den Wiki-Beiträgen [[FHEM_mit_HTTPS_SSL-Zertifikat_und_eine_eigene_Zertifizierungsstelle]] und [[FHEMWEB_mit_Let&#039;s_Encrypt_Zertifikaten]].&lt;br /&gt;
&lt;br /&gt;
Letztlich fehlt noch das entsprechende Attribut:&lt;br /&gt;
:&amp;lt;code&amp;gt;attr WEBhook HTTPS&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Als nächstes aktivieren wir Benutzername+Passwort für den Zugriff. Die {{Link2CmdRef|Anker=allowed}} für allowed gibt auch hier unter dem Punkt basicAuth entsprechende Hinweise.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Begriffserklärung zur Unterscheidung von [[eventMap]], [[devStateIcon]], [[webCmd]] und [[setList]] mit Beispielen in diesem {{Link2Forum|Topic=12080|LinkText=Forenthread}}&lt;br /&gt;
* [[Icons]]&lt;br /&gt;
* [[FHEMWEB/Widgets|FHEMWEB Widgets]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:FHEM Frontends]]&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FHEM_mit_HTTPS_SSL-Zertifikat_und_eine_eigene_Zertifizierungsstelle&amp;diff=38683</id>
		<title>FHEM mit HTTPS SSL-Zertifikat und eine eigene Zertifizierungsstelle</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FHEM_mit_HTTPS_SSL-Zertifikat_und_eine_eigene_Zertifizierungsstelle&amp;diff=38683"/>
		<updated>2023-11-09T10:18:52Z</updated>

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

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

		<summary type="html">&lt;p&gt;Drhirn: Die Seite wurde neu angelegt: „[https://certbot.eff.org Certbot] ist ein freies Open-Source-Tool der [https://www.eff.org/ Electronic Frontier Foundation (EFF)] mit dem automatisiert Zertifikate der [https://letsencrypt.org/ Let&amp;#039;s Encrypt CA] erstellt werden können.  Diese Zertifikate können auch in FHEM verwendet werden, um mittels HTTPS auf FHEMWEB zuzugreifen.  In dieser Anleitung wird beschrieben wie Certbot installiert, #Zertifikate erstellen|Zert…“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[https://certbot.eff.org Certbot] ist ein freies Open-Source-Tool der [https://www.eff.org/ Electronic Frontier Foundation (EFF)] mit dem automatisiert Zertifikate der [https://letsencrypt.org/ Let&#039;s Encrypt CA] erstellt werden können.&lt;br /&gt;
&lt;br /&gt;
Diese Zertifikate können auch in FHEM verwendet werden, um mittels HTTPS auf [[FHEMWEB]] zuzugreifen.&lt;br /&gt;
&lt;br /&gt;
In dieser Anleitung wird beschrieben wie [[#Certbot installieren|Certbot]] installiert, [[#Zertifikate erstellen|Zertifikate damit erstellt]] und diese dann [[#Einbindung in FHEM|FHEM zur Verfügung gestellt]] werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Let&#039;s Encrypt Zertifikate sind in der Regel 90 Tage gültig. Beim Beantragen eines Zertifikates wird von Certbot automatisch ein systemd Timer erstellt, der kurz vor Ablauf des Zertifikat einen Prozess zur Erneuerung desselben startet. Dabei müssen die selben Voraussetzungen gegeben sein, die auch bei der Erst-Erstellung des Zertifikates nötig sind.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Certbot installieren==&lt;br /&gt;
;Voraussetzungen:&lt;br /&gt;
* Debian/Ubuntu/Raspberry Pi OS auf dem FHEM-Server&lt;br /&gt;
* SSH-Zugang zum FHEM-Server&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die empfohlene Installationsweise ist über die [https://snapcraft.io Snap Paketverwaltung]. Diese Anleitung geht von dieser Empfehlung aus. Wer Snap nicht verwenden möchte, findet [https://eff-certbot.readthedocs.io/en/latest/install.html hier] weitere Informationen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es werden zuerst die Paket-Quellen aktualisiert. Danach erfolgt die Installation der Snap Paketverwaltung und einer Laufzeitumgebung dafür:&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt install -y snapd&lt;br /&gt;
 sudo snap install core&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im nächsten Schritt kann dann der Cerbot installiert werden:&lt;br /&gt;
 sudo snap install --classic certbot&lt;br /&gt;
&lt;br /&gt;
Damit Certbot ohne Angabe seines Pfades ausgeführt werden kann, wird noch ein symbolischer Link erstellt:&lt;br /&gt;
 sudo ln -s /snap/bin/certbot /usr/bin/certbot&lt;br /&gt;
&lt;br /&gt;
==Zertifikate erstellen==&lt;br /&gt;
Certbot bietet mehrere Möglichkeiten, Let&#039;s Encrypt Zertifikate zu erstellen. Diese hängen von den jeweiligen technischen Voraussetzungen ab.&lt;br /&gt;
&lt;br /&gt;
Damit ein Zertifikat ausgestellt werden kann, muss der Server bzw. der Serveradministrator bestimmte Aufgaben erfüllen um zu beweisen, dass er auch Besitzer der Domain ist, für die ein Zertifikat erstellt werden soll. Beispiele für solche Aufgaben sind z.B. einen bestimmten Record im DNS-Eintrag der Domain zu erstellen oder eine definierte Datei auf einem Webserver abzulegen. Für jede dieser Aufgaben gibt es ein Certbot Plug-In. Genauere Details finden sich auf der Webseite von [https://letsencrypt.org/de/how-it-works/ Let&#039;s Encrpyt].&lt;br /&gt;
&lt;br /&gt;
Welche der Möglichkeiten bzw. welches Plug-In genutzt wird, entscheidet der Serveradministrator.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im Folgenden sind zwei verschiedene Plug-Ins erklärt. Weitere Informationen oder alternative Möglichkeiten bietet die [https://eff-certbot.readthedocs.io/en/latest/using.html#getting-certificates-and-choosing-plugins Certbot-Dokumentation].&lt;br /&gt;
&lt;br /&gt;
===Standalone-Plugin===&lt;br /&gt;
Die &amp;quot;standalone&amp;quot; Variante bietet sich an, wenn auf dem System kein Web-Server installiert ist oder mit diesem nicht interagiert werden soll/kann.&lt;br /&gt;
&lt;br /&gt;
Um die Let&#039;s Encrypt Aufgabe erfüllen zu können, wird automatisch ein in Certbot eingebauter Webserver gestartet. Dieser liefert eine Datei aus, die von Let&#039;s Encrypt dann überprüft wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Voraussetzungen:&lt;br /&gt;
* Einen DNS Eintrag vom Typ A (IPv4) oder AAAA (IPv6) für eure Domain mit eurer externen IP Adresse&lt;br /&gt;
* Port 80 ist auf der Firewall geöffnet und wird zum FHEM-Server weitergeleitet&lt;br /&gt;
* Port 80 wird auf dem FHEM-Server von keinem anderen Service (Web-Server z.B.) verwendet&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind alle Voraussetzungen erfüllt, kann ein Zertifikat mit folgendem Befehl beantragt werden:&lt;br /&gt;
 sudo certbot certonly --standalone -d www.example.com -d example.com&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;&#039;&#039;--standalone&#039;&#039;&#039;&#039;&#039; bestimmt hier das zu verwendende Plug-In &amp;quot;standalone&amp;quot;&lt;br /&gt;
*&#039;&#039;&#039;&#039;&#039;-d&#039;&#039;&#039;&#039;&#039; die Domain, für die das Zertifikat ausgestellt werden soll. Es können - kommagetrennt - mehrere Domains angegeben werden. Oder der Parameter -d wird einfach öfter verwendet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weiteres Beispiel für das Beantragen eines Zertifikates mit mehreren Domains:&lt;br /&gt;
 sudo certbot certonly --standalone -d www.example.com -d example.com&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wer den ganzen Ablauf zuerst testen möchte, kann einen &amp;quot;dry-run&amp;quot; durchführen. Dabei wird die Ausstellung durch einen Test-Server von Let&#039;s Encrypt durchgeführt, es werden aber keine Zertifikate am FHEM-Server gespeichert: &lt;br /&gt;
 sudo certbot certonly --standalone --dry-run -d www.example.com&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit, einen ausführlicheren Testlauf durchzuführen ist, den Let&#039;s Encrypt Staging-Server (Test-Server) zu verwenden. Dabei werden Zertifikate im System abgelegt, die zwar ungültig sind, aber zu Testzwecken verwendet werden können:&lt;br /&gt;
 sudo certbot certonly --standalone --staging -d www.example.com&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--;Erneuern&lt;br /&gt;
sudo certbot certonly --standalone --force-renewal --staging -d www.example.com--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===DNS Plugins===&lt;br /&gt;
Eine ganz einfache Möglichkeit zur Erstellen von Zertifikaten bieten die DNS Plug-Ins.&lt;br /&gt;
&lt;br /&gt;
Dabei muss kein lokaler Server aus dem Internet erreichbar sein, sondern es wird ein bestimmter DNS-Eintrag der Domain automatisch geändert und überprüft um zu beweisen, dass der Antragsteller Inhaber der Domain ist.&lt;br /&gt;
&lt;br /&gt;
;Voraussetzungen&lt;br /&gt;
*Verwendung eines [https://eff-certbot.readthedocs.io/en/latest/using.html#dns-plugins unterstützten DNS-Providers] zur Verwaltung der eigenen Domain&lt;br /&gt;
*API-Key mit dem Recht, DNS-Einträge zu ändern&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für alle DNS Plug-Ins gilt, dass sie unter dem root-User laufen. Um das zu erlauben, ist folgender Befehl nötig:&lt;br /&gt;
 sudo snap set certbot trust-plugin-with-root=ok&lt;br /&gt;
&lt;br /&gt;
Anschließend muss das korrekte Plug-In installiert werden.&lt;br /&gt;
&lt;br /&gt;
In dieser Anleitung wird die Verwendung des [https://certbot-dns-cloudflare.readthedocs.io/en/stable/ Cloudflare Plug-Ins] erklärt. Die Funktionsweise ist bei anderen ähnlich und auf der jeweiligen [https://eff-certbot.readthedocs.io/en/latest/using.html#dns-plugins Dokumentationsseite] des Plug-Ins ersichtlich.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zuerst wird das Plug-In installiert:&lt;br /&gt;
 sudo snap install certbot-dns-cloudflare&lt;br /&gt;
&lt;br /&gt;
Danach wird eine Datei erstellt, die den API-Key mit der Berechtigung zum Ändern von DNS-Einträgen bei Cloudflare beinhaltet:&lt;br /&gt;
 sudo mkdir /root/.secrets/&lt;br /&gt;
 sudo nano /root/.secrets/cloudflare.ini&lt;br /&gt;
&lt;br /&gt;
;/root/.secrets/cloudflare.ini&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
# Cloudflare API token used by Certbot&lt;br /&gt;
dns_cloudflare_api_token = 0123456789abcdef0123456789abcdef01234567&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Datei muss dann noch vor unbefugtem Zugriff geschützt werden:&lt;br /&gt;
 sudo chmod 0700 /root/.secrets/&lt;br /&gt;
 sudo chmod 0400 /root/.secrets/cloudflare.ini&lt;br /&gt;
&lt;br /&gt;
Sind diese Schritte erledigt, kann ein Zertifikat beantragt werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo certbot certonly \&lt;br /&gt;
  --dns-cloudflare \&lt;br /&gt;
  --dns-cloudflare-credentials /root/.secrets/cloudflare.ini \&lt;br /&gt;
  --dns-cloudflare-propagation-seconds 20 \&lt;br /&gt;
  -d www.example.com -d example.com&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Einbindung in FHEM==&lt;br /&gt;
Um die Zertifikate nun in FHEM nutzen zu können, müssen zuerst die Berechtigungen auf diese geändert und dann symbolische Links zu Pfaden erstellt werden, wie sie FHEM erwartet.&lt;br /&gt;
&lt;br /&gt;
Das Ändern der Berechtigungen ist wichtig, weil der User &#039;&#039;fhem&#039;&#039; sonst keinen Lesezugriff auf diese hätte. Das Erstellen der symbolischen Link, weil FHEM die Zertifikate im Ordner &#039;&#039;/opt/fhem/certs&#039;&#039; erwartet.&lt;br /&gt;
&lt;br /&gt;
Grundsätzlich legt Certbot alle Zertifikate unter &#039;&#039;/etc/letsencrypt/archive&#039;&#039; ab. Und zwar unterschiedliche Versionen der Zertifikate. Damit Anwendungen die jeweils aktuellen Zertifikate ohne Änderung verwenden können, werden aber gleichzeitig auch symbolische Links nach &#039;&#039;/etc/letsencrypt/live&#039;&#039; gesetzt.&lt;br /&gt;
&lt;br /&gt;
Kurz gesagt, für Anwendungen sind nur die jeweiligen Dateien unter &#039;&#039;/etc/letsencrypt/live&#039;&#039; relevant. Dabei vor allem:&lt;br /&gt;
* &#039;&#039;&#039;/etc/letsencrypt/live/www.example.com/privkey.pem&#039;&#039;&#039; (Der private Key)&lt;br /&gt;
* &#039;&#039;&#039;/etc/letsencrypt/live/www.example.com/fullchain.pem&#039;&#039;&#039; (Das erstellte Zertifikat mit der ganzen Signaturkette)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nichts desto trotz müssen aber auf beiden Verzeichnisse (&#039;&#039;archive&#039;&#039; und &#039;&#039;live&#039;&#039;) die Zugriffsrechte geändert werden, damit der User &#039;&#039;fhem&#039;&#039; in späterer Folge daraus lesen kann. Für die Sicherheit der Zertifikate hat das keinen Einfluss, die sind durch eigene Dateisystemrechte geschützt.&lt;br /&gt;
 sudo chmod 0755 /etc/letsencrypt/{live,archive}&lt;br /&gt;
&lt;br /&gt;
Damit FHEM den Private Key lesen kann, ändern wir den Gruppenbesitz der Datei auf die Gruppe &#039;&#039;dialout&#039;&#039;:&lt;br /&gt;
 sudo chgrp dialout /etc/letsencrypt/archive/www.example.com/privkey1.pem&lt;br /&gt;
&lt;br /&gt;
Und vergeben anschließend noch eine Leseberechtigung für diese Gruppe:&lt;br /&gt;
 sudo chmod 0640 /etc/letsencrypt/archive/www.example.com/privkey1.pem&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind alle Berechtigungen vergeben (die sich beim Erneuern der Zertifikate nicht ändern), müssen noch symbolische Links in das Verzeichnis &#039;&#039;/opt/fhem/certs&#039;&#039; erstellt werden, da FHEM die Zertifikats-Dateien genau dort erwartet. Alle folgenden Befehle werden unter dem Benutzerkontext des Users &#039;&#039;fhem&#039;&#039; ausgeführt, damit danach keine Berechtigungen mehr verändert werden müssen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zuerst wird das Verzeichnis selbst erstellt:&lt;br /&gt;
 sudo -u fhem mkdir /opt/fhem/certs&lt;br /&gt;
&lt;br /&gt;
Anschließend ein symbolischer Link für den PrivateKey eingerichtet:&lt;br /&gt;
 sudo -u fhem ln -s /etc/letsencrypt/live/www.example.com/privkey.pem /opt/fhem/certs/server-key.pem&lt;br /&gt;
&lt;br /&gt;
Und danach einer für das Zertifikat:&lt;br /&gt;
 sudo -u fhem ln -s /etc/letsencrypt/live/www.example.com/fullchain.pem /opt/fhem/certs/server-cert.pem&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Änderung in FHEM selbst beschränken sich auf eine einzige Änderung am FHEMWEB-Device (&#039;&#039;WEB&#039;&#039;):&lt;br /&gt;
 attr WEB HTTPS 1&lt;br /&gt;
&lt;br /&gt;
Danach die Konfiguration speichern und FHEM ist ab sofort unter https://www.example.com:8083/ zu erreichen.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HOWTOS]][[Kategorie:Sicherheit]][[Kategorie:Systemadministration]][[Kategorie:FHEM Frontends]]&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Benutzer:Drhirn&amp;diff=38680</id>
		<title>Benutzer:Drhirn</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Benutzer:Drhirn&amp;diff=38680"/>
		<updated>2023-11-09T10:09:43Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[https://certbot.eff.org Certbot] ist ein freies Open-Source-Tool der [https://www.eff.org/ Electronic Frontier Foundation (EFF)] mit dem automatisiert Zertifikate der [https://letsencrypt.org/ Let&#039;s Encrypt CA] erstellt werden können.&lt;br /&gt;
&lt;br /&gt;
Diese Zertifikate können auch in FHEM verwendet werden, um mittels HTTPS auf [[FHEMWEB]] zuzugreifen.&lt;br /&gt;
&lt;br /&gt;
In dieser Anleitung wird beschrieben wie [[#Certbot installieren|Certbot]] installiert, [[#Zertifikate erstellen|Zertifikate damit erstellt]] und diese dann [[#Einbindung in FHEM|FHEM zur Verfügung gestellt]] werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Let&#039;s Encrypt Zertifikate sind in der Regel 90 Tage gültig. Beim Beantragen eines Zertifikates wird von Certbot automatisch ein systemd Timer erstellt, der kurz vor Ablauf des Zertifikat einen Prozess zur Erneuerung desselben startet. Dabei müssen die selben Voraussetzungen gegeben sein, die auch bei der Erst-Erstellung des Zertifikates nötig sind.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Certbot installieren==&lt;br /&gt;
;Voraussetzungen:&lt;br /&gt;
* Debian/Ubuntu/Raspberry Pi OS auf dem FHEM-Server&lt;br /&gt;
* SSH-Zugang zum FHEM-Server&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die empfohlene Installationsweise ist über die [https://snapcraft.io Snap Paketverwaltung]. Diese Anleitung geht von dieser Empfehlung aus. Wer Snap nicht verwenden möchte, findet [https://eff-certbot.readthedocs.io/en/latest/install.html hier] weitere Informationen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es werden zuerst die Paket-Quellen aktualisiert. Danach erfolgt die Installation der Snap Paketverwaltung und einer Laufzeitumgebung dafür:&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt install -y snapd&lt;br /&gt;
 sudo snap install core&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im nächsten Schritt kann dann der Cerbot installiert werden:&lt;br /&gt;
 sudo snap install --classic certbot&lt;br /&gt;
&lt;br /&gt;
Damit Certbot ohne Angabe seines Pfades ausgeführt werden kann, wird noch ein symbolischer Link erstellt:&lt;br /&gt;
 sudo ln -s /snap/bin/certbot /usr/bin/certbot&lt;br /&gt;
&lt;br /&gt;
==Zertifikate erstellen==&lt;br /&gt;
Certbot bietet mehrere Möglichkeiten, Let&#039;s Encrypt Zertifikate zu erstellen. Diese hängen von den jeweiligen technischen Voraussetzungen ab.&lt;br /&gt;
&lt;br /&gt;
Damit ein Zertifikat ausgestellt werden kann, muss der Server bzw. der Serveradministrator bestimmte Aufgaben erfüllen um zu beweisen, dass er auch Besitzer der Domain ist, für die ein Zertifikat erstellt werden soll. Beispiele für solche Aufgaben sind z.B. einen bestimmten Record im DNS-Eintrag der Domain zu erstellen oder eine definierte Datei auf einem Webserver abzulegen. Für jede dieser Aufgaben gibt es ein Certbot Plug-In. Genauere Details finden sich auf der Webseite von [https://letsencrypt.org/de/how-it-works/ Let&#039;s Encrpyt].&lt;br /&gt;
&lt;br /&gt;
Welche der Möglichkeiten bzw. welches Plug-In genutzt wird, entscheidet der Serveradministrator.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im Folgenden sind zwei verschiedene Plug-Ins erklärt. Weitere Informationen oder alternative Möglichkeiten bietet die [https://eff-certbot.readthedocs.io/en/latest/using.html#getting-certificates-and-choosing-plugins Certbot-Dokumentation].&lt;br /&gt;
&lt;br /&gt;
===Standalone-Plugin===&lt;br /&gt;
Die &amp;quot;standalone&amp;quot; Variante bietet sich an, wenn auf dem System kein Web-Server installiert ist oder mit diesem nicht interagiert werden soll/kann.&lt;br /&gt;
&lt;br /&gt;
Um die Let&#039;s Encrypt Aufgabe erfüllen zu können, wird automatisch ein in Certbot eingebauter Webserver gestartet. Dieser liefert eine Datei aus, die von Let&#039;s Encrypt dann überprüft wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Voraussetzungen:&lt;br /&gt;
* Einen DNS Eintrag vom Typ A (IPv4) oder AAAA (IPv6) für eure Domain mit eurer externen IP Adresse&lt;br /&gt;
* Port 80 ist auf der Firewall geöffnet und wird zum FHEM-Server weitergeleitet&lt;br /&gt;
* Port 80 wird auf dem FHEM-Server von keinem anderen Service (Web-Server z.B.) verwendet&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind alle Voraussetzungen erfüllt, kann ein Zertifikat mit folgendem Befehl beantragt werden:&lt;br /&gt;
 sudo certbot certonly --standalone -d www.example.com -d example.com&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;&#039;&#039;--standalone&#039;&#039;&#039;&#039;&#039; bestimmt hier das zu verwendende Plug-In &amp;quot;standalone&amp;quot;&lt;br /&gt;
*&#039;&#039;&#039;&#039;&#039;-d&#039;&#039;&#039;&#039;&#039; die Domain, für die das Zertifikat ausgestellt werden soll. Es können - kommagetrennt - mehrere Domains angegeben werden. Oder der Parameter -d wird einfach öfter verwendet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weiteres Beispiel für das Beantragen eines Zertifikates mit mehreren Domains:&lt;br /&gt;
 sudo certbot certonly --standalone -d www.example.com -d example.com&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wer den ganzen Ablauf zuerst testen möchte, kann einen &amp;quot;dry-run&amp;quot; durchführen. Dabei wird die Ausstellung durch einen Test-Server von Let&#039;s Encrypt durchgeführt, es werden aber keine Zertifikate am FHEM-Server gespeichert: &lt;br /&gt;
 sudo certbot certonly --standalone --dry-run -d www.example.com&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit, einen ausführlicheren Testlauf durchzuführen ist, den Let&#039;s Encrypt Staging-Server (Test-Server) zu verwenden. Dabei werden Zertifikate im System abgelegt, die zwar ungültig sind, aber zu Testzwecken verwendet werden können:&lt;br /&gt;
 sudo certbot certonly --standalone --staging -d www.example.com&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--;Erneuern&lt;br /&gt;
sudo certbot certonly --standalone --force-renewal --staging -d www.example.com--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===DNS Plugins===&lt;br /&gt;
Eine ganz einfache Möglichkeit zur Erstellen von Zertifikaten bieten die DNS Plug-Ins.&lt;br /&gt;
&lt;br /&gt;
Dabei muss kein lokaler Server aus dem Internet erreichbar sein, sondern es wird ein bestimmter DNS-Eintrag der Domain automatisch geändert und überprüft um zu beweisen, dass der Antragsteller Inhaber der Domain ist.&lt;br /&gt;
&lt;br /&gt;
;Voraussetzungen&lt;br /&gt;
*Verwendung eines [https://eff-certbot.readthedocs.io/en/latest/using.html#dns-plugins unterstützten DNS-Providers] zur Verwaltung der eigenen Domain&lt;br /&gt;
*API-Key mit dem Recht, DNS-Einträge zu ändern&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für alle DNS Plug-Ins gilt, dass sie unter dem root-User laufen. Um das zu erlauben, ist folgender Befehl nötig:&lt;br /&gt;
 sudo snap set certbot trust-plugin-with-root=ok&lt;br /&gt;
&lt;br /&gt;
Anschließend muss das korrekte Plug-In installiert werden.&lt;br /&gt;
&lt;br /&gt;
In dieser Anleitung wird die Verwendung des [https://certbot-dns-cloudflare.readthedocs.io/en/stable/ Cloudflare Plug-Ins] erklärt. Die Funktionsweise ist bei anderen ähnlich und auf der jeweiligen [https://eff-certbot.readthedocs.io/en/latest/using.html#dns-plugins Dokumentationsseite] des Plug-Ins ersichtlich.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zuerst wird das Plug-In installiert:&lt;br /&gt;
 sudo snap install certbot-dns-cloudflare&lt;br /&gt;
&lt;br /&gt;
Danach wird eine Datei erstellt, die den API-Key mit der Berechtigung zum Ändern von DNS-Einträgen bei Cloudflare beinhaltet:&lt;br /&gt;
 sudo mkdir /root/.secrets/&lt;br /&gt;
 sudo nano /root/.secrets/cloudflare.ini&lt;br /&gt;
&lt;br /&gt;
;/root/.secrets/cloudflare.ini&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
# Cloudflare API token used by Certbot&lt;br /&gt;
dns_cloudflare_api_token = 0123456789abcdef0123456789abcdef01234567&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Datei muss dann noch vor unbefugtem Zugriff geschützt werden:&lt;br /&gt;
 sudo chmod 0700 /root/.secrets/&lt;br /&gt;
 sudo chmod 0400 /root/.secrets/cloudflare.ini&lt;br /&gt;
&lt;br /&gt;
Sind diese Schritte erledigt, kann ein Zertifikat beantragt werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo certbot certonly \&lt;br /&gt;
  --dns-cloudflare \&lt;br /&gt;
  --dns-cloudflare-credentials /root/.secrets/cloudflare.ini \&lt;br /&gt;
  --dns-cloudflare-propagation-seconds 20 \&lt;br /&gt;
  -d www.example.com -d example.com&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Einbindung in FHEM==&lt;br /&gt;
Um die Zertifikate nun in FHEM nutzen zu können, müssen zuerst die Berechtigungen auf diese geändert und dann symbolische Links zu Pfaden erstellt werden, wie sie FHEM erwartet.&lt;br /&gt;
&lt;br /&gt;
Das Ändern der Berechtigungen ist wichtig, weil der User &#039;&#039;fhem&#039;&#039; sonst keinen Lesezugriff auf diese hätte. Das Erstellen der symbolischen Link, weil FHEM die Zertifikate im Ordner &#039;&#039;/opt/fhem/certs&#039;&#039; erwartet.&lt;br /&gt;
&lt;br /&gt;
Grundsätzlich legt Certbot alle Zertifikate unter &#039;&#039;/etc/letsencrypt/archive&#039;&#039; ab. Und zwar unterschiedliche Versionen der Zertifikate. Damit Anwendungen die jeweils aktuellen Zertifikate ohne Änderung verwenden können, werden aber gleichzeitig auch symbolische Links nach &#039;&#039;/etc/letsencrypt/live&#039;&#039; gesetzt.&lt;br /&gt;
&lt;br /&gt;
Kurz gesagt, für Anwendungen sind nur die jeweiligen Dateien unter &#039;&#039;/etc/letsencrypt/live&#039;&#039; relevant. Dabei vor allem:&lt;br /&gt;
* &#039;&#039;&#039;/etc/letsencrypt/live/www.example.com/privkey.pem&#039;&#039;&#039; (Der private Key)&lt;br /&gt;
* &#039;&#039;&#039;/etc/letsencrypt/live/www.example.com/fullchain.pem&#039;&#039;&#039; (Das erstellte Zertifikat mit der ganzen Signaturkette)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nichts desto trotz müssen aber auf beiden Verzeichnisse (&#039;&#039;archive&#039;&#039; und &#039;&#039;live&#039;&#039;) die Zugriffsrechte geändert werden, damit der User &#039;&#039;fhem&#039;&#039; in späterer Folge daraus lesen kann. Für die Sicherheit der Zertifikate hat das keinen Einfluss, die sind durch eigene Dateisystemrechte geschützt.&lt;br /&gt;
 sudo chmod 0755 /etc/letsencrypt/{live,archive}&lt;br /&gt;
&lt;br /&gt;
Damit FHEM den Private Key lesen kann, ändern wir den Gruppenbesitz der Datei auf die Gruppe &#039;&#039;dialout&#039;&#039;:&lt;br /&gt;
 sudo chgrp dialout /etc/letsencrypt/archive/www.example.com/privkey1.pem&lt;br /&gt;
&lt;br /&gt;
Und vergeben anschließend noch eine Leseberechtigung für diese Gruppe:&lt;br /&gt;
 sudo chmod 0640 /etc/letsencrypt/archive/www.example.com/privkey1.pem&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind alle Berechtigungen vergeben (die sich beim Erneuern der Zertifikate nicht ändern), müssen noch symbolische Links in das Verzeichnis &#039;&#039;/opt/fhem/certs&#039;&#039; erstellt werden, da FHEM die Zertifikats-Dateien genau dort erwartet. Alle folgenden Befehle werden unter dem Benutzerkontext des Users &#039;&#039;fhem&#039;&#039; ausgeführt, damit danach keine Berechtigungen mehr verändert werden müssen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zuerst wird das Verzeichnis selbst erstellt:&lt;br /&gt;
 sudo -u fhem mkdir /opt/fhem/certs&lt;br /&gt;
&lt;br /&gt;
Anschließend ein symbolischer Link für den PrivateKey eingerichtet:&lt;br /&gt;
 sudo -u fhem ln -s /etc/letsencrypt/live/www.example.com/privkey.pem /opt/fhem/certs/server-key.pem&lt;br /&gt;
&lt;br /&gt;
Und danach einer für das Zertifikat:&lt;br /&gt;
 sudo -u fhem ln -s /etc/letsencrypt/live/www.example.com/fullchain.pem /opt/fhem/certs/server-cert.pem&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Änderung in FHEM selbst beschränken sich auf eine einzige Änderung am FHEMWEB-Device (&#039;&#039;WEB&#039;&#039;):&lt;br /&gt;
 attr WEB HTTPS 1&lt;br /&gt;
&lt;br /&gt;
Danach die Konfiguration speichern und FHEM ist ab sofort unter https://www.example.com:8083/ zu erreichen.&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=FHEM_mit_HTTPS_SSL-Zertifikat_und_eine_eigene_Zertifizierungsstelle&amp;diff=38679</id>
		<title>FHEM mit HTTPS SSL-Zertifikat und eine eigene Zertifizierungsstelle</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=FHEM_mit_HTTPS_SSL-Zertifikat_und_eine_eigene_Zertifizierungsstelle&amp;diff=38679"/>
		<updated>2023-11-09T10:04:59Z</updated>

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

		<summary type="html">&lt;p&gt;Drhirn: /* Standalone-Plugin */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[https://certbot.eff.org Certbot] ist ein freies Open-Source-Tool der Electronic Frontier Foundation (EFF) mit dem automatisiert Let&#039;s Encrypt Zertifikate erstellt werden können.&lt;br /&gt;
&lt;br /&gt;
Diese Zertifikate können auch in FHEM verwendet werden, um mittels HTTPS auf [[FHEMWEB]] zuzugreifen.&lt;br /&gt;
&lt;br /&gt;
In dieser Anleitung wird beschrieben wie [[#Certbot installieren|Certbot]] installiert, [[#Zertifikate erstellen|Zertifikate damit erstellt]] und diese dann [[#Einbindung in FHEM|FHEM zur Verfügung gestellt]] werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Let&#039;s Encrypt Zertifikate sind in der Regel 90 Tage gültig. Beim Beantragen eines Zertifikates wird von Certbot automatisch ein systemd Timer erstellt, der kurz vor Ablauf des Zertifikat einen Prozess zur Erneuerung desselben startet. Dabei müssen die selben Voraussetzungen gegeben sein, die auch bei der Erst-Erstellung des Zertifikates nötig sind.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Certbot installieren==&lt;br /&gt;
;Voraussetzungen:&lt;br /&gt;
* Debian/Ubuntu/Raspberry Pi OS auf dem FHEM-Server&lt;br /&gt;
* SSH-Zugang zum FHEM-Server&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die empfohlene Installationsweise ist über die [https://snapcraft.io Snap Paketverwaltung]. Diese Anleitung geht von dieser Empfehlung aus. Wer Snap nicht verwenden möchte, findet [https://eff-certbot.readthedocs.io/en/latest/install.html hier] weitere Informationen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es werden zuerst die Paket-Quellen aktualisiert. Danach erfolgt die Installation der Snap Paketverwaltung und einer Laufzeitumgebung dafür:&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt install -y snapd&lt;br /&gt;
 sudo snap install core&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im nächsten Schritt kann dann der Cerbot installiert werden:&lt;br /&gt;
 sudo snap install --classic certbot&lt;br /&gt;
&lt;br /&gt;
Damit Certbot ohne Angabe seines Pfades ausgeführt werden kann, wird noch ein symbolischer Link erstellt:&lt;br /&gt;
 sudo ln -s /snap/bin/certbot /usr/bin/certbot&lt;br /&gt;
&lt;br /&gt;
==Zertifikate erstellen==&lt;br /&gt;
Certbot bietet mehrere Möglichkeiten, Let&#039;s Encrypt Zertifikate zu erstellen. Diese hängen von den jeweiligen technischen Voraussetzungen ab.&lt;br /&gt;
&lt;br /&gt;
Damit ein Zertifikat ausgestellt werden kann, muss der Server bzw. der Serveradministrator bestimmte Aufgaben erfüllen um zu beweisen, dass er auch Besitzer der Domain ist, für die ein Zertifikat erstellt werden soll. Beispiele für solche Aufgaben sind z.B. einen bestimmten Record im DNS-Eintrag der Domain zu erstellen oder eine definierte Datei auf einem Webserver abzulegen. Für jede dieser Aufgaben gibt es ein Certbot Plug-In. Genauere Details finden sich auf der Webseite von [https://letsencrypt.org/de/how-it-works/ Let&#039;s Encrpyt].&lt;br /&gt;
&lt;br /&gt;
Welche der Möglichkeiten bzw. welches Plug-In genutzt wird, entscheidet der Serveradministrator.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im Folgenden sind zwei verschiedene Plug-Ins erklärt. Weitere Informationen oder alternative Möglichkeiten bietet die [https://eff-certbot.readthedocs.io/en/latest/using.html#getting-certificates-and-choosing-plugins Certbot-Dokumentation].&lt;br /&gt;
&lt;br /&gt;
===Standalone-Plugin===&lt;br /&gt;
Die &amp;quot;standalone&amp;quot; Variante bietet sich an, wenn auf dem System kein Web-Server installiert ist oder mit diesem nicht interagiert werden soll/kann.&lt;br /&gt;
&lt;br /&gt;
Um die Let&#039;s Encrypt Aufgabe erfüllen zu können, wird automatisch ein in Certbot eingebauter Webserver gestartet. Dieser liefert eine Datei aus, die von Let&#039;s Encrypt dann überprüft wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Voraussetzungen:&lt;br /&gt;
* Einen DNS Eintrag vom Typ A (IPv4) oder AAAA (IPv6) für eure Domain mit eurer externen IP Adresse&lt;br /&gt;
* Port 80 ist auf der Firewall geöffnet und wird zum FHEM-Server weitergeleitet&lt;br /&gt;
* Port 80 wird auf dem FHEM-Server von keinem anderen Service (Web-Server z.B.) verwendet&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind alle Voraussetzungen erfüllt, kann ein Zertifikat mit folgendem Befehl beantragt werden:&lt;br /&gt;
 sudo certbot certonly --standalone -d www.example.com -d example.com&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;&#039;&#039;--standalone&#039;&#039;&#039;&#039;&#039; bestimmt hier das zu verwendende Plug-In &amp;quot;standalone&amp;quot;&lt;br /&gt;
*&#039;&#039;&#039;&#039;&#039;-d&#039;&#039;&#039;&#039;&#039; die Domain, für die das Zertifikat ausgestellt werden soll. Es können - kommagetrennt - mehrere Domains angegeben werden. Oder der Parameter -d wird einfach öfter verwendet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weiteres Beispiel für das Beantragen eines Zertifikates mit mehreren Domains:&lt;br /&gt;
 sudo certbot certonly --standalone -d www.example.com -d example.com&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wer den ganzen Ablauf zuerst testen möchte, kann einen &amp;quot;dry-run&amp;quot; durchführen. Dabei wird die Ausstellung durch einen Test-Server von Let&#039;s Encrypt durchgeführt, es werden aber keine Zertifikate am FHEM-Server gespeichert: &lt;br /&gt;
 sudo certbot certonly --standalone --dry-run -d www.example.com&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit, einen ausführlicheren Testlauf durchzuführen ist, den Let&#039;s Encrypt Staging-Server (Test-Server) zu verwenden. Dabei werden Zertifikate im System abgelegt, die zwar ungültig sind, aber zu Testzwecken verwendet werden können:&lt;br /&gt;
 sudo certbot certonly --standalone --staging -d www.example.com&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--;Erneuern&lt;br /&gt;
sudo certbot certonly --standalone --force-renewal --staging -d www.example.com--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===DNS Plugins===&lt;br /&gt;
Eine ganz einfache Möglichkeit zur Erstellen von Zertifikaten bieten die DNS Plug-Ins.&lt;br /&gt;
&lt;br /&gt;
Dabei muss kein lokaler Server aus dem Internet erreichbar sein, sondern es wird ein bestimmter DNS-Eintrag der Domain automatisch geändert und überprüft um zu beweisen, dass der Antragsteller Inhaber der Domain ist.&lt;br /&gt;
&lt;br /&gt;
;Voraussetzungen&lt;br /&gt;
*Verwendung eines [https://eff-certbot.readthedocs.io/en/latest/using.html#dns-plugins unterstützten DNS-Providers] zur Verwaltung der eigenen Domain&lt;br /&gt;
*API-Key mit dem Recht, DNS-Einträge zu ändern&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für alle DNS Plug-Ins gilt, dass sie unter dem root-User laufen. Um das zu erlauben, ist folgender Befehl nötig:&lt;br /&gt;
 sudo snap set certbot trust-plugin-with-root=ok&lt;br /&gt;
&lt;br /&gt;
Anschließend muss das korrekte Plug-In installiert werden.&lt;br /&gt;
&lt;br /&gt;
In dieser Anleitung wird die Verwendung des [https://certbot-dns-cloudflare.readthedocs.io/en/stable/ Cloudflare Plug-Ins] erklärt. Die Funktionsweise ist bei anderen ähnlich und auf der jeweiligen [https://eff-certbot.readthedocs.io/en/latest/using.html#dns-plugins Dokumentationsseite] des Plug-Ins ersichtlich.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zuerst wird das Plug-In installiert:&lt;br /&gt;
 sudo snap install certbot-dns-cloudflare&lt;br /&gt;
&lt;br /&gt;
Danach wird eine Datei erstellt, die den API-Key mit der Berechtigung zum Ändern von DNS-Einträgen bei Cloudflare beinhaltet:&lt;br /&gt;
 sudo mkdir /root/.secrets/&lt;br /&gt;
 sudo nano /root/.secrets/cloudflare.ini&lt;br /&gt;
&lt;br /&gt;
;/root/.secrets/cloudflare.ini&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
# Cloudflare API token used by Certbot&lt;br /&gt;
dns_cloudflare_api_token = 0123456789abcdef0123456789abcdef01234567&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Datei muss dann noch vor unbefugtem Zugriff geschützt werden:&lt;br /&gt;
 sudo chmod 0700 /root/.secrets/&lt;br /&gt;
 sudo chmod 0400 /root/.secrets/cloudflare.ini&lt;br /&gt;
&lt;br /&gt;
Sind diese Schritte erledigt, kann ein Zertifikat beantragt werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo certbot certonly \&lt;br /&gt;
  --dns-cloudflare \&lt;br /&gt;
  --dns-cloudflare-credentials /root/.secrets/cloudflare.ini \&lt;br /&gt;
  --dns-cloudflare-propagation-seconds 20 \&lt;br /&gt;
  -d www.example.com -d example.com&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Einbindung in FHEM==&lt;br /&gt;
Um die Zertifikate nun in FHEM nutzen zu können, müssen zuerst die Berechtigungen auf diese geändert und dann symbolische Links zu Pfaden erstellt werden, wie sie FHEM erwartet.&lt;br /&gt;
&lt;br /&gt;
Das Ändern der Berechtigungen ist wichtig, weil der User &#039;&#039;fhem&#039;&#039; sonst keinen Lesezugriff auf diese hätte. Das Erstellen der symbolischen Link, weil FHEM die Zertifikate im Ordner &#039;&#039;/opt/fhem/certs&#039;&#039; erwartet.&lt;br /&gt;
&lt;br /&gt;
Grundsätzlich legt Certbot alle Zertifikate unter &#039;&#039;/etc/letsencrypt/archive&#039;&#039; ab. Und zwar unterschiedliche Versionen der Zertifikate. Damit Anwendungen die jeweils aktuellen Zertifikate ohne Änderung verwenden können, werden aber gleichzeitig auch symbolische Links nach &#039;&#039;/etc/letsencrypt/live&#039;&#039; gesetzt.&lt;br /&gt;
&lt;br /&gt;
Kurz gesagt, für Anwendungen sind nur die jeweiligen Dateien unter &#039;&#039;/etc/letsencrypt/live&#039;&#039; relevant. Dabei vor allem:&lt;br /&gt;
* &#039;&#039;&#039;/etc/letsencrypt/live/www.example.com/privkey.pem&#039;&#039;&#039; (Der private Key)&lt;br /&gt;
* &#039;&#039;&#039;/etc/letsencrypt/live/www.example.com/fullchain.pem&#039;&#039;&#039; (Das erstellte Zertifikat mit der ganzen Signaturkette)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nichts desto trotz müssen aber auf beiden Verzeichnisse (&#039;&#039;archive&#039;&#039; und &#039;&#039;live&#039;&#039;) die Zugriffsrechte geändert werden, damit der User &#039;&#039;fhem&#039;&#039; in späterer Folge daraus lesen kann. Für die Sicherheit der Zertifikate hat das keinen Einfluss, die sind durch eigene Dateisystemrechte geschützt.&lt;br /&gt;
 sudo chmod 0755 /etc/letsencrypt/{live,archive}&lt;br /&gt;
&lt;br /&gt;
Damit FHEM den Private Key lesen kann, ändern wir den Gruppenbesitz der Datei auf die Gruppe &#039;&#039;dialout&#039;&#039;:&lt;br /&gt;
 sudo chgrp dialout /etc/letsencrypt/archive/www.example.com/privkey1.pem&lt;br /&gt;
&lt;br /&gt;
Und vergeben anschließend noch eine Leseberechtigung für diese Gruppe:&lt;br /&gt;
 sudo chmod 0640 /etc/letsencrypt/archive/www.example.com/privkey1.pem&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind alle Berechtigungen vergeben (die sich beim Erneuern der Zertifikate nicht ändern), müssen noch symbolische Links in das Verzeichnis &#039;&#039;/opt/fhem/certs&#039;&#039; erstellt werden, da FHEM die Zertifikats-Dateien genau dort erwartet. Alle folgenden Befehle werden unter dem Benutzerkontext des Users &#039;&#039;fhem&#039;&#039; ausgeführt, damit danach keine Berechtigungen mehr verändert werden müssen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zuerst wird das Verzeichnis selbst erstellt:&lt;br /&gt;
 sudo -u fhem mkdir /opt/fhem/certs&lt;br /&gt;
&lt;br /&gt;
Anschließend ein symbolischer Link für den PrivateKey eingerichtet:&lt;br /&gt;
 sudo -u fhem ln -s /etc/letsencrypt/live/www.example.com/privkey.pem /opt/fhem/certs/server-key.pem&lt;br /&gt;
&lt;br /&gt;
Und danach einer für das Zertifikat:&lt;br /&gt;
 sudo -u fhem ln -s /etc/letsencrypt/live/www.example.com/fullchain.pem /opt/fhem/certs/server-cert.pem&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Änderung in FHEM selbst beschränken sich auf eine einzige Änderung am FHEMWEB-Device (&#039;&#039;WEB&#039;&#039;):&lt;br /&gt;
 attr WEB HTTPS 1&lt;br /&gt;
&lt;br /&gt;
Danach die Konfiguration speichern und FHEM ist ab sofort unter https://www.example.com:8083/ zu erreichen.&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Benutzer:Drhirn&amp;diff=38677</id>
		<title>Benutzer:Drhirn</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Benutzer:Drhirn&amp;diff=38677"/>
		<updated>2023-11-09T08:49:18Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[https://certbot.eff.org Certbot] ist ein freies Open-Source-Tool der Electronic Frontier Foundation (EFF) mit dem automatisiert Let&#039;s Encrypt Zertifikate erstellt werden können.&lt;br /&gt;
&lt;br /&gt;
Diese Zertifikate können auch in FHEM verwendet werden, um mittels HTTPS auf [[FHEMWEB]] zuzugreifen.&lt;br /&gt;
&lt;br /&gt;
In dieser Anleitung wird beschrieben wie [[#Certbot installieren|Certbot]] installiert, [[#Zertifikate erstellen|Zertifikate damit erstellt]] und diese dann [[#Einbindung in FHEM|FHEM zur Verfügung gestellt]] werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Let&#039;s Encrypt Zertifikate sind in der Regel 90 Tage gültig. Beim Beantragen eines Zertifikates wird von Certbot automatisch ein systemd Timer erstellt, der kurz vor Ablauf des Zertifikat einen Prozess zur Erneuerung desselben startet. Dabei müssen die selben Voraussetzungen gegeben sein, die auch bei der Erst-Erstellung des Zertifikates nötig sind.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Certbot installieren==&lt;br /&gt;
;Voraussetzungen:&lt;br /&gt;
* Debian/Ubuntu/Raspberry Pi OS auf dem FHEM-Server&lt;br /&gt;
* SSH-Zugang zum FHEM-Server&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die empfohlene Installationsweise ist über die [https://snapcraft.io Snap Paketverwaltung]. Diese Anleitung geht von dieser Empfehlung aus. Wer Snap nicht verwenden möchte, findet [https://eff-certbot.readthedocs.io/en/latest/install.html hier] weitere Informationen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es werden zuerst die Paket-Quellen aktualisiert. Danach erfolgt die Installation der Snap Paketverwaltung und einer Laufzeitumgebung dafür:&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt install -y snapd&lt;br /&gt;
 sudo snap install core&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im nächsten Schritt kann dann der Cerbot installiert werden:&lt;br /&gt;
 sudo snap install --classic certbot&lt;br /&gt;
&lt;br /&gt;
Damit Certbot ohne Angabe seines Pfades ausgeführt werden kann, wird noch ein symbolischer Link erstellt:&lt;br /&gt;
 sudo ln -s /snap/bin/certbot /usr/bin/certbot&lt;br /&gt;
&lt;br /&gt;
==Zertifikate erstellen==&lt;br /&gt;
Certbot bietet mehrere Möglichkeiten, Let&#039;s Encrypt Zertifikate zu erstellen. Diese hängen von den jeweiligen technischen Voraussetzungen ab.&lt;br /&gt;
&lt;br /&gt;
Damit ein Zertifikat ausgestellt werden kann, muss der Server bzw. der Serveradministrator bestimmte Aufgaben erfüllen um zu beweisen, dass er auch Besitzer der Domain ist, für die ein Zertifikat erstellt werden soll. Beispiele für solche Aufgaben sind z.B. einen bestimmten Record im DNS-Eintrag der Domain zu erstellen oder eine definierte Datei auf einem Webserver abzulegen. Für jede dieser Aufgaben gibt es ein Certbot Plug-In. Genauere Details finden sich auf der Webseite von [https://letsencrypt.org/de/how-it-works/ Let&#039;s Encrpyt].&lt;br /&gt;
&lt;br /&gt;
Welche der Möglichkeiten bzw. welches Plug-In genutzt wird, entscheidet der Serveradministrator.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im Folgenden sind zwei verschiedene Plug-Ins erklärt. Weitere Informationen oder alternative Möglichkeiten bietet die [https://eff-certbot.readthedocs.io/en/latest/using.html#getting-certificates-and-choosing-plugins Certbot-Dokumentation].&lt;br /&gt;
&lt;br /&gt;
===Standalone-Plugin===&lt;br /&gt;
Die &amp;quot;standalone&amp;quot; Variante bietet sich an, wenn auf dem System kein Web-Server installiert ist oder mit diesem nicht interagiert werden soll/kann.&lt;br /&gt;
&lt;br /&gt;
Um die Let&#039;s Encrypt Aufgabe erfüllen zu können, wird automatisch ein in Certbot eingebauter Webserver gestartet. Dieser liefert eine Datei aus, die von Let&#039;s Encrypt dann überprüft wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Voraussetzungen:&lt;br /&gt;
* Einen DNS Eintrag vom Typ A (IPv4) oder AAAA (IPv6) für eure Domain mit eurer externen IP Adresse&lt;br /&gt;
* Port 80 ist auf der Firewall geöffnet und wird zum FHEM-Server weitergeleitet&lt;br /&gt;
* Port 80 wird auf dem FHEM-Server von keinem anderen Service (Web-Server z.B.) verwendet&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind alle Voraussetzungen erfüllt, kann ein Zertifikat mit folgendem Befehl beantragt werden:&lt;br /&gt;
 sudo certbot certonly --standalone -d www.example.com&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;&#039;&#039;--standalone&#039;&#039;&#039;&#039;&#039; bestimmt hier das zu verwendende Plug-In &amp;quot;standalone&amp;quot;&lt;br /&gt;
*&#039;&#039;&#039;&#039;&#039;-d&#039;&#039;&#039;&#039;&#039; die Domain, für die das Zertifikat ausgestellt werden soll. Es können - kommagetrennt - mehrere Domains angegeben werden. Oder der Parameter -d wird einfach öfter verwendet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weiteres Beispiel für das Beantragen eines Zertifikates mit mehreren Domains:&lt;br /&gt;
 sudo certbot certonly --standalone -d www.example.com -d example.com&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wer den ganzen Ablauf zuerst testen möchte, kann einen &amp;quot;dry-run&amp;quot; durchführen. Dabei wird die Ausstellung durch einen Test-Server von Let&#039;s Encrypt durchgeführt, es werden aber keine Zertifikate am FHEM-Server gespeichert: &lt;br /&gt;
 sudo certbot certonly --standalone --dry-run -d www.example.com&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit, einen ausführlicheren Testlauf durchzuführen ist, den Let&#039;s Encrypt Staging-Server (Test-Server) zu verwenden. Dabei werden Zertifikate im System abgelegt, die zwar ungültig sind, aber zu Testzwecken verwendet werden können:&lt;br /&gt;
 sudo certbot certonly --standalone --staging -d www.example.com&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--;Erneuern&lt;br /&gt;
sudo certbot certonly --standalone --force-renewal --staging -d test.jft.at--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===DNS Plugins===&lt;br /&gt;
Eine ganz einfache Möglichkeit zur Erstellen von Zertifikaten bieten die DNS Plug-Ins.&lt;br /&gt;
&lt;br /&gt;
Dabei muss kein lokaler Server aus dem Internet erreichbar sein, sondern es wird ein bestimmter DNS-Eintrag der Domain automatisch geändert und überprüft um zu beweisen, dass der Antragsteller Inhaber der Domain ist.&lt;br /&gt;
&lt;br /&gt;
;Voraussetzungen&lt;br /&gt;
*Verwendung eines [https://eff-certbot.readthedocs.io/en/latest/using.html#dns-plugins unterstützten DNS-Providers] zur Verwaltung der eigenen Domain&lt;br /&gt;
*API-Key mit dem Recht, DNS-Einträge zu ändern&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für alle DNS Plug-Ins gilt, dass sie unter dem root-User laufen. Um das zu erlauben, ist folgender Befehl nötig:&lt;br /&gt;
 sudo snap set certbot trust-plugin-with-root=ok&lt;br /&gt;
&lt;br /&gt;
Anschließend muss das korrekte Plug-In installiert werden.&lt;br /&gt;
&lt;br /&gt;
In dieser Anleitung wird die Verwendung des [https://certbot-dns-cloudflare.readthedocs.io/en/stable/ Cloudflare Plug-Ins] erklärt. Die Funktionsweise ist bei anderen ähnlich und auf der jeweiligen [https://eff-certbot.readthedocs.io/en/latest/using.html#dns-plugins Dokumentationsseite] des Plug-Ins ersichtlich.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zuerst wird das Plug-In installiert:&lt;br /&gt;
 sudo snap install certbot-dns-cloudflare&lt;br /&gt;
&lt;br /&gt;
Danach wird eine Datei erstellt, die den API-Key mit der Berechtigung zum Ändern von DNS-Einträgen bei Cloudflare beinhaltet:&lt;br /&gt;
 sudo mkdir /root/.secrets/&lt;br /&gt;
 sudo nano /root/.secrets/cloudflare.ini&lt;br /&gt;
&lt;br /&gt;
;/root/.secrets/cloudflare.ini&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
# Cloudflare API token used by Certbot&lt;br /&gt;
dns_cloudflare_api_token = 0123456789abcdef0123456789abcdef01234567&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Datei muss dann noch vor unbefugtem Zugriff geschützt werden:&lt;br /&gt;
 sudo chmod 0700 /root/.secrets/&lt;br /&gt;
 sudo chmod 0400 /root/.secrets/cloudflare.ini&lt;br /&gt;
&lt;br /&gt;
Sind diese Schritte erledigt, kann ein Zertifikat beantragt werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo certbot certonly \&lt;br /&gt;
  --dns-cloudflare \&lt;br /&gt;
  --dns-cloudflare-credentials /root/.secrets/cloudflare.ini \&lt;br /&gt;
  --dns-cloudflare-propagation-seconds 20 \&lt;br /&gt;
  -d www.example.com -d example.com&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Einbindung in FHEM==&lt;br /&gt;
Um die Zertifikate nun in FHEM nutzen zu können, müssen zuerst die Berechtigungen auf diese geändert und dann symbolische Links zu Pfaden erstellt werden, wie sie FHEM erwartet.&lt;br /&gt;
&lt;br /&gt;
Das Ändern der Berechtigungen ist wichtig, weil der User &#039;&#039;fhem&#039;&#039; sonst keinen Lesezugriff auf diese hätte. Das Erstellen der symbolischen Link, weil FHEM die Zertifikate im Ordner &#039;&#039;/opt/fhem/certs&#039;&#039; erwartet.&lt;br /&gt;
&lt;br /&gt;
Grundsätzlich legt Certbot alle Zertifikate unter &#039;&#039;/etc/letsencrypt/archive&#039;&#039; ab. Und zwar unterschiedliche Versionen der Zertifikate. Damit Anwendungen die jeweils aktuellen Zertifikate ohne Änderung verwenden können, werden aber gleichzeitig auch symbolische Links nach &#039;&#039;/etc/letsencrypt/live&#039;&#039; gesetzt.&lt;br /&gt;
&lt;br /&gt;
Kurz gesagt, für Anwendungen sind nur die jeweiligen Dateien unter &#039;&#039;/etc/letsencrypt/live&#039;&#039; relevant. Dabei vor allem:&lt;br /&gt;
* &#039;&#039;&#039;/etc/letsencrypt/live/www.example.com/privkey.pem&#039;&#039;&#039; (Der private Key)&lt;br /&gt;
* &#039;&#039;&#039;/etc/letsencrypt/live/www.example.com/fullchain.pem&#039;&#039;&#039; (Das erstellte Zertifikat mit der ganzen Signaturkette)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nichts desto trotz müssen aber auf beiden Verzeichnisse (&#039;&#039;archive&#039;&#039; und &#039;&#039;live&#039;&#039;) die Zugriffsrechte geändert werden, damit der User &#039;&#039;fhem&#039;&#039; in späterer Folge daraus lesen kann. Für die Sicherheit der Zertifikate hat das keinen Einfluss, die sind durch eigene Dateisystemrechte geschützt.&lt;br /&gt;
 sudo chmod 0755 /etc/letsencrypt/{live,archive}&lt;br /&gt;
&lt;br /&gt;
Damit FHEM den Private Key lesen kann, ändern wir den Gruppenbesitz der Datei auf die Gruppe &#039;&#039;dialout&#039;&#039;:&lt;br /&gt;
 sudo chgrp dialout /etc/letsencrypt/archive/www.example.com/privkey1.pem&lt;br /&gt;
&lt;br /&gt;
Und vergeben anschließend noch eine Leseberechtigung für diese Gruppe:&lt;br /&gt;
 sudo chmod 0640 /etc/letsencrypt/archive/www.example.com/privkey1.pem&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind alle Berechtigungen vergeben (die sich beim Erneuern der Zertifikate nicht ändern), müssen noch symbolische Links in das Verzeichnis &#039;&#039;/opt/fhem/certs&#039;&#039; erstellt werden, da FHEM die Zertifikats-Dateien genau dort erwartet. Alle folgenden Befehle werden unter dem Benutzerkontext des Users &#039;&#039;fhem&#039;&#039; ausgeführt, damit danach keine Berechtigungen mehr verändert werden müssen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zuerst wird das Verzeichnis selbst erstellt:&lt;br /&gt;
 sudo -u fhem mkdir /opt/fhem/certs&lt;br /&gt;
&lt;br /&gt;
Anschließend ein symbolischer Link für den PrivateKey eingerichtet:&lt;br /&gt;
 sudo -u fhem ln -s /etc/letsencrypt/live/www.example.com/privkey.pem /opt/fhem/certs/server-key.pem&lt;br /&gt;
&lt;br /&gt;
Und danach einer für das Zertifikat:&lt;br /&gt;
 sudo -u fhem ln -s /etc/letsencrypt/live/www.example.com/fullchain.pem /opt/fhem/certs/server-cert.pem&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Änderung in FHEM selbst beschränken sich auf eine einzige Änderung am FHEMWEB-Device (&#039;&#039;WEB&#039;&#039;):&lt;br /&gt;
 attr WEB HTTPS 1&lt;br /&gt;
&lt;br /&gt;
Danach die Konfiguration speichern und FHEM ist ab sofort unter https://www.example.com:8083/ zu erreichen.&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Benutzer:Drhirn&amp;diff=38676</id>
		<title>Benutzer:Drhirn</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Benutzer:Drhirn&amp;diff=38676"/>
		<updated>2023-11-09T08:46:15Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: /* Einbindung in FHEM */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[https://certbot.eff.org Certbot] ist ein freies Open-Source-Tool der Electronic Frontier Foundation (EFF) mit dem automatisiert Let&#039;s Encrypt Zertifikate erstellt werden können.&lt;br /&gt;
&lt;br /&gt;
Diese Zertifikate können auch in FHEM verwendet werden, um den Netzwerkverkehr zu verschlüsseln.&lt;br /&gt;
&lt;br /&gt;
In dieser Anleitung wird beschrieben wie [[#Certbot installieren|Certbot]] installiert, [[#Zertifikate erstellen|Zertifikate damit erstellt]] und diese dann [[#Einbindung in FHEM|FHEM zur Verfügung gestellt]] werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Let&#039;s Encrypt Zertifikate sind in der Regel 90 Tage gültig. Beim Beantragen eines Zertifikates wird von Certbot automatisch ein systemd Timer erstellt, der kurz vor Ablauf des Zertifikat einen Prozess zur Erneuerung desselben startet. Dabei müssen die selben Voraussetzungen gegeben sein, die auch bei der Erst-Erstellung des Zertifikates nötig sind.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Certbot installieren==&lt;br /&gt;
;Voraussetzungen:&lt;br /&gt;
* Debian/Ubuntu/Raspberry Pi OS auf dem FHEM-Server&lt;br /&gt;
* SSH-Zugang zum FHEM-Server&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die empfohlene Installationsweise ist über die [https://snapcraft.io Snap Paketverwaltung]. Diese Anleitung geht von dieser Empfehlung aus. Wer Snap nicht verwenden möchte, findet [https://eff-certbot.readthedocs.io/en/latest/install.html hier] weitere Informationen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es werden zuerst die Paket-Quellen aktualisiert. Danach erfolgt die Installation der Snap Paketverwaltung und einer Laufzeitumgebung dafür:&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt install -y snapd&lt;br /&gt;
 sudo snap install core&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im nächsten Schritt kann dann der Cerbot installiert werden:&lt;br /&gt;
 sudo snap install --classic certbot&lt;br /&gt;
&lt;br /&gt;
Damit Certbot ohne Angabe seines Pfades ausgeführt werden kann, wird noch ein symbolischer Link erstellt:&lt;br /&gt;
 sudo ln -s /snap/bin/certbot /usr/bin/certbot&lt;br /&gt;
&lt;br /&gt;
==Zertifikate erstellen==&lt;br /&gt;
Certbot bietet mehrere Möglichkeiten, Let&#039;s Encrypt Zertifikate zu erstellen. Diese hängen von den jeweiligen technischen Voraussetzungen ab.&lt;br /&gt;
&lt;br /&gt;
Damit ein Zertifikat ausgestellt werden kann, muss der Server bzw. der Serveradministrator bestimmte Aufgaben erfüllen um zu beweisen, dass er auch Besitzer der Domain ist, für die ein Zertifikat erstellt werden soll. Beispiele für solche Aufgaben sind z.B. einen bestimmten Record im DNS-Eintrag der Domain zu erstellen oder eine definierte Datei auf einem Webserver abzulegen. Für jede dieser Aufgaben gibt es ein Certbot Plug-In. Genauere Details finden sich auf der Webseite von [https://letsencrypt.org/de/how-it-works/ Let&#039;s Encrpyt].&lt;br /&gt;
&lt;br /&gt;
Welche der Möglichkeiten bzw. welches Plug-In genutzt wird, entscheidet der Serveradministrator.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im Folgenden sind zwei verschiedene Plug-Ins erklärt. Weitere Informationen oder alternative Möglichkeiten bietet die [https://eff-certbot.readthedocs.io/en/latest/using.html#getting-certificates-and-choosing-plugins Certbot-Dokumentation].&lt;br /&gt;
&lt;br /&gt;
===Standalone-Plugin===&lt;br /&gt;
Die &amp;quot;standalone&amp;quot; Variante bietet sich an, wenn auf dem System kein Web-Server installiert ist oder mit diesem nicht interagiert werden soll/kann.&lt;br /&gt;
&lt;br /&gt;
Um die Let&#039;s Encrypt Aufgabe erfüllen zu können, wird automatisch ein in Certbot eingebauter Webserver gestartet. Dieser liefert eine Datei aus, die von Let&#039;s Encrypt dann überprüft wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Voraussetzungen:&lt;br /&gt;
* Einen DNS Eintrag vom Typ A (IPv4) oder AAAA (IPv6) für eure Domain mit eurer externen IP Adresse&lt;br /&gt;
* Port 80 ist auf der Firewall geöffnet und wird zum FHEM-Server weitergeleitet&lt;br /&gt;
* Port 80 wird auf dem FHEM-Server von keinem anderen Service (Web-Server z.B.) verwendet&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind alle Voraussetzungen erfüllt, kann ein Zertifikat mit folgendem Befehl beantragt werden:&lt;br /&gt;
 sudo certbot certonly --standalone -d www.example.com&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;&#039;&#039;--standalone&#039;&#039;&#039;&#039;&#039; bestimmt hier das zu verwendende Plug-In &amp;quot;standalone&amp;quot;&lt;br /&gt;
*&#039;&#039;&#039;&#039;&#039;-d&#039;&#039;&#039;&#039;&#039; die Domain, für die das Zertifikat ausgestellt werden soll. Es können - kommagetrennt - mehrere Domains angegeben werden. Oder der Parameter -d wird einfach öfter verwendet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weiteres Beispiel für das Beantragen eines Zertifikates mit mehreren Domains:&lt;br /&gt;
 sudo certbot certonly --standalone -d www.example.com -d example.com&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wer den ganzen Ablauf zuerst testen möchte, kann einen &amp;quot;dry-run&amp;quot; durchführen. Dabei wird die Ausstellung durch einen Test-Server von Let&#039;s Encrypt durchgeführt, es werden aber keine Zertifikate am FHEM-Server gespeichert: &lt;br /&gt;
 sudo certbot certonly --standalone --dry-run -d www.example.com&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit, einen ausführlicheren Testlauf durchzuführen ist, den Let&#039;s Encrypt Staging-Server (Test-Server) zu verwenden. Dabei werden Zertifikate im System abgelegt, die zwar ungültig sind, aber zu Testzwecken verwendet werden können:&lt;br /&gt;
 sudo certbot certonly --standalone --staging -d www.example.com&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--;Erneuern&lt;br /&gt;
sudo certbot certonly --standalone --force-renewal --staging -d test.jft.at--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===DNS Plugins===&lt;br /&gt;
Eine ganz einfache Möglichkeit zur Erstellen von Zertifikaten bieten die DNS Plug-Ins.&lt;br /&gt;
&lt;br /&gt;
Dabei muss kein lokaler Server aus dem Internet erreichbar sein, sondern es wird ein bestimmter DNS-Eintrag der Domain automatisch geändert und überprüft um zu beweisen, dass der Antragsteller Inhaber der Domain ist.&lt;br /&gt;
&lt;br /&gt;
;Voraussetzungen&lt;br /&gt;
*Verwendung eines [https://eff-certbot.readthedocs.io/en/latest/using.html#dns-plugins unterstützten DNS-Providers] zur Verwaltung der eigenen Domain&lt;br /&gt;
*API-Key mit dem Recht, DNS-Einträge zu ändern&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für alle DNS Plug-Ins gilt, dass sie unter dem root-User laufen. Um das zu erlauben, ist folgender Befehl nötig:&lt;br /&gt;
 sudo snap set certbot trust-plugin-with-root=ok&lt;br /&gt;
&lt;br /&gt;
Anschließend muss das korrekte Plug-In installiert werden.&lt;br /&gt;
&lt;br /&gt;
In dieser Anleitung wird die Verwendung des [https://certbot-dns-cloudflare.readthedocs.io/en/stable/ Cloudflare Plug-Ins] erklärt. Die Funktionsweise ist bei anderen ähnlich und auf der jeweiligen [https://eff-certbot.readthedocs.io/en/latest/using.html#dns-plugins Dokumentationsseite] des Plug-Ins ersichtlich.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zuerst wird das Plug-In installiert:&lt;br /&gt;
 sudo snap install certbot-dns-cloudflare&lt;br /&gt;
&lt;br /&gt;
Danach wird eine Datei erstellt, die den API-Key mit der Berechtigung zum Ändern von DNS-Einträgen bei Cloudflare beinhaltet:&lt;br /&gt;
 sudo mkdir /root/.secrets/&lt;br /&gt;
 sudo nano /root/.secrets/cloudflare.ini&lt;br /&gt;
&lt;br /&gt;
;/root/.secrets/cloudflare.ini&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
# Cloudflare API token used by Certbot&lt;br /&gt;
dns_cloudflare_api_token = 0123456789abcdef0123456789abcdef01234567&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Datei muss dann noch vor unbefugtem Zugriff geschützt werden:&lt;br /&gt;
 sudo chmod 0700 /root/.secrets/&lt;br /&gt;
 sudo chmod 0400 /root/.secrets/cloudflare.ini&lt;br /&gt;
&lt;br /&gt;
Sind diese Schritte erledigt, kann ein Zertifikat beantragt werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo certbot certonly \&lt;br /&gt;
  --dns-cloudflare \&lt;br /&gt;
  --dns-cloudflare-credentials /root/.secrets/cloudflare.ini \&lt;br /&gt;
  --dns-cloudflare-propagation-seconds 20 \&lt;br /&gt;
  -d www.example.com -d example.com&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Einbindung in FHEM==&lt;br /&gt;
Um die Zertifikate nun in FHEM nutzen zu können, müssen zuerst die Berechtigungen auf diese geändert und dann symbolische Links zu Pfaden erstellt werden, wie sie FHEM erwartet.&lt;br /&gt;
&lt;br /&gt;
Das Ändern der Berechtigungen ist wichtig, weil der User &#039;&#039;fhem&#039;&#039; sonst keinen Lesezugriff auf diese hätte. Das Erstellen der symbolischen Link, weil FHEM die Zertifikate im Ordner &#039;&#039;/opt/fhem/certs&#039;&#039; erwartet.&lt;br /&gt;
&lt;br /&gt;
Grundsätzlich legt Certbot alle Zertifikate unter &#039;&#039;/etc/letsencrypt/archive&#039;&#039; ab. Und zwar unterschiedliche Versionen der Zertifikate. Damit Anwendungen die jeweils aktuellen Zertifikate ohne Änderung verwenden können, werden aber gleichzeitig auch symbolische Links nach &#039;&#039;/etc/letsencrypt/live&#039;&#039; gesetzt.&lt;br /&gt;
&lt;br /&gt;
Kurz gesagt, für Anwendungen sind nur die jeweiligen Dateien unter &#039;&#039;/etc/letsencrypt/live&#039;&#039; relevant. Dabei vor allem:&lt;br /&gt;
* &#039;&#039;&#039;/etc/letsencrypt/live/www.example.com/privkey.pem&#039;&#039;&#039; (Der private Key)&lt;br /&gt;
* &#039;&#039;&#039;/etc/letsencrypt/live/www.example.com/fullchain.pem&#039;&#039;&#039; (Das erstellte Zertifikat mit der ganzen Signaturkette)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nichts desto trotz müssen aber auf beiden Verzeichnisse (&#039;&#039;archive&#039;&#039; und &#039;&#039;live&#039;&#039;) die Zugriffsrechte geändert werden, damit der User &#039;&#039;fhem&#039;&#039; in späterer Folge daraus lesen kann. Für die Sicherheit der Zertifikate hat das keinen Einfluss, die sind durch eigene Dateisystemrechte geschützt.&lt;br /&gt;
 sudo chmod 0755 /etc/letsencrypt/{live,archive}&lt;br /&gt;
&lt;br /&gt;
Damit FHEM den Private Key lesen kann, ändern wir den Gruppenbesitz der Datei auf die Gruppe &#039;&#039;dialout&#039;&#039;:&lt;br /&gt;
 sudo chgrp dialout /etc/letsencrypt/archive/www.example.com/privkey1.pem&lt;br /&gt;
&lt;br /&gt;
Und vergeben anschließend noch eine Leseberechtigung für diese Gruppe:&lt;br /&gt;
 sudo chmod 0640 /etc/letsencrypt/archive/www.example.com/privkey1.pem&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind alle Berechtigungen vergeben (die sich beim Erneuern der Zertifikate nicht ändern), müssen noch symbolische Links in das Verzeichnis &#039;&#039;/opt/fhem/certs&#039;&#039; erstellt werden, da FHEM die Zertifikats-Dateien genau dort erwartet. Alle folgenden Befehle werden unter dem Benutzerkontext des Users &#039;&#039;fhem&#039;&#039; ausgeführt, damit danach keine Berechtigungen mehr verändert werden müssen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zuerst wird das Verzeichnis selbst erstellt:&lt;br /&gt;
 sudo -u fhem mkdir /opt/fhem/certs&lt;br /&gt;
&lt;br /&gt;
Anschließend ein symbolischer Link für den PrivateKey eingerichtet:&lt;br /&gt;
 sudo -u fhem ln -s /etc/letsencrypt/live/www.example.com/privkey.pem /opt/fhem/certs/server-key.pem&lt;br /&gt;
&lt;br /&gt;
Und danach einer für das Zertifikat:&lt;br /&gt;
 sudo -u fhem ln -s /etc/letsencrypt/live/www.example.com/fullchain.pem /opt/fhem/certs/server-cert.pem&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Änderung in FHEM selbst beschränken sich auf eine einzige Änderung am FHEMWEB-Device (&#039;&#039;WEB&#039;&#039;):&lt;br /&gt;
 attr WEB HTTPS 1&lt;br /&gt;
&lt;br /&gt;
Danach die Konfiguration speichern und FHEM ist ab sofort unter https://www.example.com:8083/ zu erreichen.&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Benutzer:Drhirn&amp;diff=38675</id>
		<title>Benutzer:Drhirn</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Benutzer:Drhirn&amp;diff=38675"/>
		<updated>2023-11-09T08:44:51Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: /* Einbindung in FHEM */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[https://certbot.eff.org Certbot] ist ein freies Open-Source-Tool der Electronic Frontier Foundation (EFF) mit dem automatisiert Let&#039;s Encrypt Zertifikate erstellt werden können.&lt;br /&gt;
&lt;br /&gt;
Diese Zertifikate können auch in FHEM verwendet werden, um den Netzwerkverkehr zu verschlüsseln.&lt;br /&gt;
&lt;br /&gt;
In dieser Anleitung wird beschrieben wie [[#Certbot installieren|Certbot]] installiert, [[#Zertifikate erstellen|Zertifikate damit erstellt]] und diese dann [[#Einbindung in FHEM|FHEM zur Verfügung gestellt]] werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Let&#039;s Encrypt Zertifikate sind in der Regel 90 Tage gültig. Beim Beantragen eines Zertifikates wird von Certbot automatisch ein systemd Timer erstellt, der kurz vor Ablauf des Zertifikat einen Prozess zur Erneuerung desselben startet. Dabei müssen die selben Voraussetzungen gegeben sein, die auch bei der Erst-Erstellung des Zertifikates nötig sind.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Certbot installieren==&lt;br /&gt;
;Voraussetzungen:&lt;br /&gt;
* Debian/Ubuntu/Raspberry Pi OS auf dem FHEM-Server&lt;br /&gt;
* SSH-Zugang zum FHEM-Server&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die empfohlene Installationsweise ist über die [https://snapcraft.io Snap Paketverwaltung]. Diese Anleitung geht von dieser Empfehlung aus. Wer Snap nicht verwenden möchte, findet [https://eff-certbot.readthedocs.io/en/latest/install.html hier] weitere Informationen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es werden zuerst die Paket-Quellen aktualisiert. Danach erfolgt die Installation der Snap Paketverwaltung und einer Laufzeitumgebung dafür:&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt install -y snapd&lt;br /&gt;
 sudo snap install core&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im nächsten Schritt kann dann der Cerbot installiert werden:&lt;br /&gt;
 sudo snap install --classic certbot&lt;br /&gt;
&lt;br /&gt;
Damit Certbot ohne Angabe seines Pfades ausgeführt werden kann, wird noch ein symbolischer Link erstellt:&lt;br /&gt;
 sudo ln -s /snap/bin/certbot /usr/bin/certbot&lt;br /&gt;
&lt;br /&gt;
==Zertifikate erstellen==&lt;br /&gt;
Certbot bietet mehrere Möglichkeiten, Let&#039;s Encrypt Zertifikate zu erstellen. Diese hängen von den jeweiligen technischen Voraussetzungen ab.&lt;br /&gt;
&lt;br /&gt;
Damit ein Zertifikat ausgestellt werden kann, muss der Server bzw. der Serveradministrator bestimmte Aufgaben erfüllen um zu beweisen, dass er auch Besitzer der Domain ist, für die ein Zertifikat erstellt werden soll. Beispiele für solche Aufgaben sind z.B. einen bestimmten Record im DNS-Eintrag der Domain zu erstellen oder eine definierte Datei auf einem Webserver abzulegen. Für jede dieser Aufgaben gibt es ein Certbot Plug-In. Genauere Details finden sich auf der Webseite von [https://letsencrypt.org/de/how-it-works/ Let&#039;s Encrpyt].&lt;br /&gt;
&lt;br /&gt;
Welche der Möglichkeiten bzw. welches Plug-In genutzt wird, entscheidet der Serveradministrator.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im Folgenden sind zwei verschiedene Plug-Ins erklärt. Weitere Informationen oder alternative Möglichkeiten bietet die [https://eff-certbot.readthedocs.io/en/latest/using.html#getting-certificates-and-choosing-plugins Certbot-Dokumentation].&lt;br /&gt;
&lt;br /&gt;
===Standalone-Plugin===&lt;br /&gt;
Die &amp;quot;standalone&amp;quot; Variante bietet sich an, wenn auf dem System kein Web-Server installiert ist oder mit diesem nicht interagiert werden soll/kann.&lt;br /&gt;
&lt;br /&gt;
Um die Let&#039;s Encrypt Aufgabe erfüllen zu können, wird automatisch ein in Certbot eingebauter Webserver gestartet. Dieser liefert eine Datei aus, die von Let&#039;s Encrypt dann überprüft wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Voraussetzungen:&lt;br /&gt;
* Einen DNS Eintrag vom Typ A (IPv4) oder AAAA (IPv6) für eure Domain mit eurer externen IP Adresse&lt;br /&gt;
* Port 80 ist auf der Firewall geöffnet und wird zum FHEM-Server weitergeleitet&lt;br /&gt;
* Port 80 wird auf dem FHEM-Server von keinem anderen Service (Web-Server z.B.) verwendet&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind alle Voraussetzungen erfüllt, kann ein Zertifikat mit folgendem Befehl beantragt werden:&lt;br /&gt;
 sudo certbot certonly --standalone -d www.example.com&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;&#039;&#039;--standalone&#039;&#039;&#039;&#039;&#039; bestimmt hier das zu verwendende Plug-In &amp;quot;standalone&amp;quot;&lt;br /&gt;
*&#039;&#039;&#039;&#039;&#039;-d&#039;&#039;&#039;&#039;&#039; die Domain, für die das Zertifikat ausgestellt werden soll. Es können - kommagetrennt - mehrere Domains angegeben werden. Oder der Parameter -d wird einfach öfter verwendet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weiteres Beispiel für das Beantragen eines Zertifikates mit mehreren Domains:&lt;br /&gt;
 sudo certbot certonly --standalone -d www.example.com -d example.com&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wer den ganzen Ablauf zuerst testen möchte, kann einen &amp;quot;dry-run&amp;quot; durchführen. Dabei wird die Ausstellung durch einen Test-Server von Let&#039;s Encrypt durchgeführt, es werden aber keine Zertifikate am FHEM-Server gespeichert: &lt;br /&gt;
 sudo certbot certonly --standalone --dry-run -d www.example.com&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit, einen ausführlicheren Testlauf durchzuführen ist, den Let&#039;s Encrypt Staging-Server (Test-Server) zu verwenden. Dabei werden Zertifikate im System abgelegt, die zwar ungültig sind, aber zu Testzwecken verwendet werden können:&lt;br /&gt;
 sudo certbot certonly --standalone --staging -d www.example.com&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--;Erneuern&lt;br /&gt;
sudo certbot certonly --standalone --force-renewal --staging -d test.jft.at--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===DNS Plugins===&lt;br /&gt;
Eine ganz einfache Möglichkeit zur Erstellen von Zertifikaten bieten die DNS Plug-Ins.&lt;br /&gt;
&lt;br /&gt;
Dabei muss kein lokaler Server aus dem Internet erreichbar sein, sondern es wird ein bestimmter DNS-Eintrag der Domain automatisch geändert und überprüft um zu beweisen, dass der Antragsteller Inhaber der Domain ist.&lt;br /&gt;
&lt;br /&gt;
;Voraussetzungen&lt;br /&gt;
*Verwendung eines [https://eff-certbot.readthedocs.io/en/latest/using.html#dns-plugins unterstützten DNS-Providers] zur Verwaltung der eigenen Domain&lt;br /&gt;
*API-Key mit dem Recht, DNS-Einträge zu ändern&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für alle DNS Plug-Ins gilt, dass sie unter dem root-User laufen. Um das zu erlauben, ist folgender Befehl nötig:&lt;br /&gt;
 sudo snap set certbot trust-plugin-with-root=ok&lt;br /&gt;
&lt;br /&gt;
Anschließend muss das korrekte Plug-In installiert werden.&lt;br /&gt;
&lt;br /&gt;
In dieser Anleitung wird die Verwendung des [https://certbot-dns-cloudflare.readthedocs.io/en/stable/ Cloudflare Plug-Ins] erklärt. Die Funktionsweise ist bei anderen ähnlich und auf der jeweiligen [https://eff-certbot.readthedocs.io/en/latest/using.html#dns-plugins Dokumentationsseite] des Plug-Ins ersichtlich.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zuerst wird das Plug-In installiert:&lt;br /&gt;
 sudo snap install certbot-dns-cloudflare&lt;br /&gt;
&lt;br /&gt;
Danach wird eine Datei erstellt, die den API-Key mit der Berechtigung zum Ändern von DNS-Einträgen bei Cloudflare beinhaltet:&lt;br /&gt;
 sudo mkdir /root/.secrets/&lt;br /&gt;
 sudo nano /root/.secrets/cloudflare.ini&lt;br /&gt;
&lt;br /&gt;
;/root/.secrets/cloudflare.ini&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
# Cloudflare API token used by Certbot&lt;br /&gt;
dns_cloudflare_api_token = 0123456789abcdef0123456789abcdef01234567&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Datei muss dann noch vor unbefugtem Zugriff geschützt werden:&lt;br /&gt;
 sudo chmod 0700 /root/.secrets/&lt;br /&gt;
 sudo chmod 0400 /root/.secrets/cloudflare.ini&lt;br /&gt;
&lt;br /&gt;
Sind diese Schritte erledigt, kann ein Zertifikat beantragt werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo certbot certonly \&lt;br /&gt;
  --dns-cloudflare \&lt;br /&gt;
  --dns-cloudflare-credentials /root/.secrets/cloudflare.ini \&lt;br /&gt;
  --dns-cloudflare-propagation-seconds 20 \&lt;br /&gt;
  -d www.example.com -d example.com&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Einbindung in FHEM==&lt;br /&gt;
Um die Zertifikate nun in FHEM nutzen zu können, müssen zuerst die Berechtigungen auf diese geändert und dann symbolische Links zu Pfaden erstellt werden, wie sie FHEM erwartet.&lt;br /&gt;
&lt;br /&gt;
Das Ändern der Berechtigungen ist wichtig, weil der User &#039;&#039;fhem&#039;&#039; sonst keinen Lesezugriff auf diese hätte. Das Erstellen der symbolischen Link, weil FHEM die Zertifikate im Ordner &#039;&#039;/opt/fhem/certs&#039;&#039; erwartet.&lt;br /&gt;
&lt;br /&gt;
Grundsätzlich legt Certbot alle Zertifikate unter &#039;&#039;/etc/letsencrypt/archive&#039;&#039; ab. Und zwar unterschiedliche Versionen der Zertifikate. Damit Anwendungen die jeweils aktuellen Zertifikate ohne Änderung verwenden können, werden aber gleichzeitig auch symbolische Links nach &#039;&#039;/etc/letsencrypt/live&#039;&#039; gesetzt.&lt;br /&gt;
&lt;br /&gt;
Kurz gesagt, für Anwendungen sind nur die jeweiligen Dateien unter &#039;&#039;/etc/letsencrypt/live&#039;&#039; relevant. Dabei vor allem:&lt;br /&gt;
* &#039;&#039;&#039;/etc/letsencrypt/live/www.example.com/privkey.pem&#039;&#039;&#039; (Der private Key)&lt;br /&gt;
* &#039;&#039;&#039;/etc/letsencrypt/live/www.example.com/fullchain.pem&#039;&#039;&#039; (Das erstellte Zertifikat mit der ganzen Signaturkette)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nichts desto trotz müssen aber auf beiden Verzeichnisse (&#039;&#039;archive&#039;&#039; und &#039;&#039;live&#039;&#039;) die Zugriffsrechte geändert werden, damit der User &#039;&#039;fhem&#039;&#039; in späterer Folge daraus lesen kann. Für die Sicherheit der Zertifikate hat das keinen Einfluss, die sind durch eigene Dateisystemrechte geschützt.&lt;br /&gt;
 sudo chmod 0755 /etc/letsencrypt/{live,archive}&lt;br /&gt;
&lt;br /&gt;
Damit FHEM den Private Key lesen kann, ändern wir den Gruppenbesitz der Datei auf die Gruppe &#039;&#039;dialout&#039;&#039;:&lt;br /&gt;
 sudo chgrp dialout /etc/letsencrypt/archive/server/privkey1.pem&lt;br /&gt;
&lt;br /&gt;
Und vergeben anschließend noch eine Leseberechtigung für diese Gruppe:&lt;br /&gt;
 sudo chmod 0640 /etc/letsencrypt/archive/server/privkey1.pem&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind alle Berechtigungen vergeben (die sich beim Erneuern der Zertifikate nicht ändern), müssen noch symbolische Links in das Verzeichnis &#039;&#039;/opt/fhem/certs&#039;&#039; erstellt werden, da FHEM die Zertifikats-Dateien genau dort erwartet. Alle folgenden Befehle werden unter dem Benutzerkontext des Users &#039;&#039;fhem&#039;&#039; ausgeführt, damit danach keine Berechtigungen mehr verändert werden müssen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zuerst wird das Verzeichnis selbst erstellt:&lt;br /&gt;
 sudo -u fhem mkdir /opt/fhem/certs&lt;br /&gt;
&lt;br /&gt;
Anschließend ein symbolischer Link für den PrivateKey eingerichtet:&lt;br /&gt;
 sudo -u fhem ln -s /etc/letsencrypt/live/www.example.com/privkey.pem /opt/fhem/certs/server-key.pem&lt;br /&gt;
&lt;br /&gt;
Und danach einer für das Zertifikat:&lt;br /&gt;
 sudo -u fhem ln -s /etc/letsencrypt/live/www.example.com/fullchain.pem /opt/fhem/certs/server-cert.pem&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Änderung in FHEM selbst beschränken sich auf eine einzige Änderung am FHEMWEB-Device (&#039;&#039;WEB&#039;&#039;):&lt;br /&gt;
 attr WEB HTTPS 1&lt;br /&gt;
&lt;br /&gt;
Danach die Konfiguration speichern und FHEM ist ab sofort unter https://www.example.com:8083/ zu erreichen.&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Ble2mqtt&amp;diff=38672</id>
		<title>Ble2mqtt</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Ble2mqtt&amp;diff=38672"/>
		<updated>2023-11-08T14:55:27Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: /* Erstellen einens Systemd-Daemons */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=Anwesenheitserkennung von Bluetooth-Geräten&lt;br /&gt;
|ModType=u&lt;br /&gt;
|ModFTopic=127173&lt;br /&gt;
|ModForumArea=Unterstützende Dienste&lt;br /&gt;
|ModTechName=ble2mqtt&lt;br /&gt;
|ModOwner=PatrickR&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;ble2mqtt&#039;&#039;&#039; ist ein Script, dass den Anwesenheitsstatus eines oder mehrerer Bluetooth Low Energy Geräte überprüfen und das Ergebnis an einen MQTT Broker schicken kann.&lt;br /&gt;
&lt;br /&gt;
Es verwendet dazu die Linux Tools &#039;&#039;bluetoothctl&#039;&#039; und &#039;&#039;gatttool&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
ble2mqtt ist in Perl geschrieben und wurde von {{Link2FU|5068|PatrickR}} erstellt. Weitere Informationen finden sich in diesem {{Link2Forum|Topic=127173|LinkText=Forums-Topic }}. Fragen dazu bitte in den Bereich [https://forum.fhem.de/index.php?board=44.0 Unterstützende Dienste]&lt;br /&gt;
&amp;lt;!--diesen {{Link2Forum|Area=44|LinkText=Bereich }}.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Voraussetzungen==&lt;br /&gt;
* Debian od. Raspberry Pi OS&lt;br /&gt;
* Bluetooth Empfänger&lt;br /&gt;
&lt;br /&gt;
==Parameter==&lt;br /&gt;
Beim Start von ble2mqtt können folgende Parameter angegeben werden:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Parameter!!Beschreibung!!Standardwert!!Beispiel!!Optional&lt;br /&gt;
|-&lt;br /&gt;
| --mqttserver&lt;br /&gt;
|Die Adresse des MQTT Brokers inklusive Port&lt;br /&gt;
|&lt;br /&gt;
| --mqttserver mqtt.example.org:1883&lt;br /&gt;
|nein&lt;br /&gt;
|-&lt;br /&gt;
| --mqttfingerprint&lt;br /&gt;
|Der Fingerprint des für die TLS-verschlüsselte Kommunikation mit dem MQTT Broker verwendeten Zertifikates&lt;br /&gt;
|&lt;br /&gt;
| --mqttfingerprint bfe5d244a821194230f1479fe2f8f7bbcd2a8cb8&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --mqtttopic&lt;br /&gt;
| An welches MQTT-Topic das Tool die Informationen schicken soll.&lt;br /&gt;
|ble2mqtt&lt;br /&gt;
| --mqtttopic ble2mqtt/Wohnzimmer&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --mqttuser&lt;br /&gt;
|Der Benutzernamen, unter dem die Verbindung zum Broker hergestellt werden soll&lt;br /&gt;
|&lt;br /&gt;
| --mqttuser ble2mqtt&lt;br /&gt;
|ja bzw. abhängig vom Broker&lt;br /&gt;
|-&lt;br /&gt;
| --mqttpass&lt;br /&gt;
|Das zum Benutzernamen gehörende Passwort&lt;br /&gt;
|&lt;br /&gt;
| --mqttpass verysecret3&lt;br /&gt;
|ja bzw. abhängig vom Broker&lt;br /&gt;
|-&lt;br /&gt;
| --retain&lt;br /&gt;
|Versendet die Nachrichten present und lastseen als retained.&lt;br /&gt;
|0&lt;br /&gt;
| --retain&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --daemonize&lt;br /&gt;
|Wenn ble2mqtt im Hintergrund (als Daemon) ausgeführt werden soll&lt;br /&gt;
|0&lt;br /&gt;
| --daemonize&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --loglevel&lt;br /&gt;
|Wie und was genau protokolliert werden soll. Mögliche Loglevel sind LOG_CRIT, LOG_ERR, LOG_WARNING, LOG_NOTICE, LOG_INFO, LOG_DEBUG.&lt;br /&gt;
|LOG_INFO&lt;br /&gt;
| --loglevel LOG_ERR&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --logtarget&lt;br /&gt;
|Wohin gelogged werden soll. Mögliche Optionen sind &#039;&#039;syslog&#039;&#039; und &#039;&#039;stdout&#039;&#039;.&lt;br /&gt;
|syslog&lt;br /&gt;
| --logtarget stdout&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --absentinterval&lt;br /&gt;
|Anzahl an Sekunden, nach denen das Gerät als abwesend bezeichnet werden soll. Mindestwert ist 30.&lt;br /&gt;
|60&lt;br /&gt;
| --absentinterval 120&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --rssithreshold&lt;br /&gt;
|Ab welcher Abweichung des RSSI Wertes ein Update getriggert werden soll. Mindestwert ist 5.&lt;br /&gt;
|10&lt;br /&gt;
| --rssithreshold 8&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --watchdogthreshold&lt;br /&gt;
|Ab welchem Zeitraum in Sekunden nach Empfangen des letzten BT-Signals ble2mqtt neu gestartet werden soll. Mindestwert ist 30. Der Wert 0 bedeutet deaktiviert, also nie.&lt;br /&gt;
|0&lt;br /&gt;
| --watchdogthreshold 30&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --debug&lt;br /&gt;
|Kann nur gemeinsam mit --daemonize verwendet werden, um Logeinträge auf stdout auszugeben. Je höher die Nummer, desto mehr Output.&lt;br /&gt;
|0&lt;br /&gt;
| --daemonize --debug 4&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --mac&lt;br /&gt;
|Filtert mittels Regex nach MAC-Adressen der von ble2mqtt zu beachtenden BLE-Geräte. Alle anderen Geräte werden ignoriert.&lt;br /&gt;
|&lt;br /&gt;
| --mac &#039;(11:22:33:44:55:66|77:88:99:00:AA:BB)&#039;&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --batterymaxage&lt;br /&gt;
|Zeit in Stunden, nach denen ein Batterie-Wert als veraltet angesehen und aktualisiert wird. Der Wert 0 deaktiviert den Batterie-Check.&lt;br /&gt;
|48&lt;br /&gt;
| --batterymaxage 6&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --forcebattery&lt;br /&gt;
|Nur in Kombination mit --mac. Erzwingt einen Batterie-Check, auch wenn das battery-service am Gerät nicht erkannt wird.&lt;br /&gt;
|0&lt;br /&gt;
| --forcebattery&lt;br /&gt;
|ja&lt;br /&gt;
|}&lt;br /&gt;
===Beispiele===&lt;br /&gt;
* Broker verlangt Username/Passwort; es sollen keine Batterie-Werte ausgelesen werden&lt;br /&gt;
 ble2mqtt --mqttserver mqtt.example.org:1883 --mqttuser ble2mqtt --mqttpass verysecret3 --batterymaxage 0&lt;br /&gt;
&lt;br /&gt;
* Broker verlangt keine Authentifizierung; es soll nach zwei G-Tags gesucht werden; definiertes MQTT-Topic; Batteriewerte benötigt&lt;br /&gt;
 ble2mqtt --mqttserver mqtt.example.org:1883 --mqtttopic ble2mqtt/Wohnzimmer --mac &#039;(11:22:33:44:55:66|77:88:99:00:AA:BB)&#039;&lt;br /&gt;
&lt;br /&gt;
* Broker verlangt keine Authentifizierung; Geräte sollen nach 45s ohne Kontakt als abwesend angezeigt werden; MQTT Nachrichten sollen gespeichert bleiben&lt;br /&gt;
 ble2mqtt --mqttserver mqtt.example.org:1883 --absentinterval 45 --retain&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
Zur Installation muss das ble2mqtt-Script auf den Server kopiert werden und es müssen diverse Linux- und Perl-Pakete installiert werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zuerst das Script nach /usr/local/bin kopieren, um beim Aufruf in der Bash nicht immer den ganzen Pfad voranstellen zu müssen.&lt;br /&gt;
 sudo cp -a ble2mqttd /usr/local/bin/&lt;br /&gt;
Danach das Script noch als ausführbar markieren&lt;br /&gt;
 sudo chmod +x /usr/local/bin/ble2mqttd&lt;br /&gt;
&lt;br /&gt;
===Benötigte Linux Pakete===&lt;br /&gt;
Die benötigten Pakete können ganz einfach mit &#039;&#039;apt&#039;&#039; installiert werden. Dabei werden auch mögliche Abhängigkeiten automatisch installiert.&lt;br /&gt;
&lt;br /&gt;
 sudo apt install -y libssl-dev libio-socket-ssl-perl libreadonly-perl libtest-expect-perl libnet-ssleay-perl libnet-server-perl&lt;br /&gt;
&lt;br /&gt;
===Benötigte Perl-Module===&lt;br /&gt;
Es wird das Modul &#039;&#039;Net::MQTT::Simple&#039;&#039; (&#039;&#039;libnet-mqtt-simple-perl&#039;&#039;) benötigt. Das ist - Stand 08.11.2023 - noch nicht in den Stable-Repositories von Debian verfügbar und muss daher mittels &#039;&#039;cpan&#039;&#039; installiert werden. Voraussetzung dafür ist das Modul &#039;&#039;CPAN::DistnameInfo&#039;&#039;, welches zuerst installiert werden muss.&lt;br /&gt;
&lt;br /&gt;
 sudo cpan CPAN::DistnameInfo&lt;br /&gt;
 sudo cpan Net::MQTT::Simple&lt;br /&gt;
&lt;br /&gt;
Sobald &#039;&#039;libnet-mqtt-simple-perl&#039;&#039; verfügbar ist, kann dieses statt der Perl-Module wie ein normales Linux-Paket installiert werden.&lt;br /&gt;
&lt;br /&gt;
===Erster Test===&lt;br /&gt;
Mit einem einfachen Aufruf von &#039;&#039;&#039;ble2mqtt&#039;&#039;&#039; kann getestet werden, ob alle benötigten Module und Pakete vorhanden sind.&lt;br /&gt;
&lt;br /&gt;
 sudo /usr/local/bin/ble2mqttd&lt;br /&gt;
&lt;br /&gt;
===Erstellen einens Systemd-Daemons===&lt;br /&gt;
Damit &#039;&#039;&#039;ble2mqtt&#039;&#039;&#039; bei jedem Systemstart automatisch gestartet wird, muss ein Systemd-Daemon erstellt werden. Das wird gemacht, in dem eine neue Textdatei mit folgendem Inhalt angelegt und der Daemon dann aktiviert wird.&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|&#039;&#039;&#039;Wichtig:&#039;&#039;&#039; Das Kommando, mit welchen Parametern ble2mqtt gestartet wird, muss natürlich individuell angepasst werden!}}&lt;br /&gt;
&lt;br /&gt;
 sudo nano /etc/systemd/system/ble2mqttd.service&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=ble2mqttd&lt;br /&gt;
After=bluetooth.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
Restart=always&lt;br /&gt;
ExecStart=/usr/local/bin/ble2mqttd --mqttserver mqtt.example.com:1883 --mqtttopic ble2mqtt/wohnzimmer --mac &#039;(11:22:33:44:55:66|77:88:99:00:AA:BB)&#039; --absentinterval 30 --mqttuser &amp;lt;username&amp;gt; --mqttpass &amp;lt;password&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 sudo systemctl daemon-reload&lt;br /&gt;
 sudo systemctl enable ble2mqttd.service&lt;br /&gt;
 sudo systemctl start ble2mqttd.service&lt;br /&gt;
&lt;br /&gt;
==Einbindung in FHEM==&lt;br /&gt;
Da ble2mqtt alle Informationen an einen [[MQTT]]-Broker sendet, können diese Informationen ganz einfach als [[MQTT2_DEVICE]] in FHEM eingebunden werden. Wie dabei vorgegangen werden kann, unterscheidet sich je nach Anwendungsbereich und den eigenen Vorlieben.&lt;br /&gt;
&lt;br /&gt;
Als Beispiel sie hier die Anwesenheitserkennung mittels BT-Tags angeführt.&lt;br /&gt;
&lt;br /&gt;
===Anwesenheitserkennung mittels BT-Tags===&lt;br /&gt;
[[File:ble2mqtt.png|thumb|Readings eines Devices, dass mit diesem Code erstellt wurde]]&lt;br /&gt;
Der folgende Code geht davon aus, dass es mehrere ble2mqtt-Instanzen gibt und ein BT-Tag mit der MAC-Adresse AA:BB:CC:DD:EE:FF erkannt werden soll.&lt;br /&gt;
&lt;br /&gt;
Die verschiedenen ble2mqtt-Instanzen schicken ihre Nachrichten in unterschiedliche Topics.&lt;br /&gt;
Für jede Instanz ein eigenes Topic:&lt;br /&gt;
*ble2mqtt/wohnzimmer&lt;br /&gt;
*ble2mqtt/schlafzimmer&lt;br /&gt;
*ble2mqtt/kueche&lt;br /&gt;
Im Attribut &#039;&#039;devicetopic&#039;&#039; werden diese Topics dann gemeinsam ausgewertet. Das funktioniert, in dem der Name des Subtopics einfach durch den Regex-Ausdruck &#039;&#039;.*&#039;&#039; ersetzt wird.&lt;br /&gt;
&lt;br /&gt;
Bedeutet aber auch, dass die Informationen - wenn gewünscht - wieder in unterschiedliche Readings zerlegt werden müssen. Um z.B. schnell zu erkennen, in welchem Raum der BT-Tag gerade liegt. Das passiert hier z.B. bei den Nachrichten für &#039;&#039;rssi&#039;&#039; und &#039;&#039;presence&#039;&#039;. Daraus resultieren dann eigene Readings für jedes MQTT-Subtopic.&lt;br /&gt;
&lt;br /&gt;
Das &amp;quot;raumübergreifende&amp;quot; Reading &#039;&#039;presence&#039;&#039; wird anhand der des Alters in Sekunden der letzten lastseen-Nachricht gesteuert. Die lastseen-Nachricht wird immer gesendet, wenn der Scanvorgang von ble2mqtt das gewünschte Gerät findet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
define ble2mqttGTag MQTT2_DEVICE FHEM&lt;br /&gt;
attr ble2mqttGTag devicetopic ble2mqtt/.*/AA_BB_CC_DD_EE_FF&lt;br /&gt;
attr ble2mqttGTag event-on-change-reading .*&lt;br /&gt;
attr ble2mqttGTag readingList ble2mqtt/.*/heartbeat:.* heartbeat&lt;br /&gt;
$DEVICETOPIC/rssi:.* {my $room=(split m{[/]}x,$TOPIC)[1]; my $roomMax=$room; my $rssiMax=$EVENT; my @readings = grep { $_ =~ m{\Arssi_(?!$room).*}x } keys %{$defs{&amp;quot;$NAME&amp;quot;}-&amp;gt;{READINGS}}; for (@readings) {my $rssiTmp=ReadingsVal($NAME,$_,&#039;-100&#039;); my $roomTmp=(split m{[_]}x,$_)[1]; if(($rssiMax gt $rssiTmp)&amp;amp;&amp;amp;(ReadingsVal($NAME,&amp;quot;presence_&amp;quot;.$roomTmp,&#039;absent&#039;) eq &#039;present&#039;)) {$rssiMax=$rssiTmp; $roomMax=$roomTmp}}; {rssi=&amp;gt;$rssiMax,room=&amp;gt;$roomMax,&amp;quot;rssi_$room&amp;quot;=&amp;gt;$EVENT}}&lt;br /&gt;
$DEVICETOPIC/lastseen:.* {lastseen=&amp;gt;strftime &amp;quot;%Y-%m-%d %H:%M:%S&amp;quot;, localtime($EVENT)}&lt;br /&gt;
$DEVICETOPIC/present:.* {my $roomAct=(split m{[/]}x,$TOPIC)[1]; my $rssi=ReadingsVal($NAME,&amp;quot;rssi_&amp;quot;.$roomAct,&#039;-100&#039;); my $presenceAct=$EVENT?&#039;present&#039;:&#039;absent&#039;; my $room=$EVENT ? $roomAct:&#039;&#039;; my @readings = grep { $_ =~ m{\Apresence_(?!$roomAct).*}x } keys %{$defs{$NAME}-&amp;gt;{READINGS}}; for (@readings) {if(ReadingsVal($NAME,$_,&#039;absent&#039;) eq &#039;present&#039;) {my $roomTmp=(split m{[_]}x,$_)[1]; my $rssiTmp=ReadingsVal($NAME,&amp;quot;rssi_&amp;quot;.$roomTmp,&#039;-100&#039;); if($rssi gt $rssiTmp){$room=$roomTmp; $rssi=$rssiTmp}}}; {&amp;quot;presence_$roomAct&amp;quot;=&amp;gt;$presenceAct, room=&amp;gt;$room}}&lt;br /&gt;
ble2mqtt/.*/state:.* state&lt;br /&gt;
$DEVICETOPIC/battery:.* batteryLevel&lt;br /&gt;
attr ble2mqttGTag userReadings presence {if (ReadingsAge($NAME,&amp;quot;lastseen&amp;quot;,0)&amp;gt;60) {return &amp;quot;absent&amp;quot;;}else{return &amp;quot;present&amp;quot;;}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Ergebnis ist unter anderem ein Reading &#039;&#039;presence&#039;&#039; mit den Zuständen &#039;&#039;absent&#039;&#039; und &#039;&#039;present&#039;&#039;. Es kann somit ganz einfach als &amp;quot;presenceDevice&amp;quot; in einem [[ROOMMATE]]-Device verwendet werden:&lt;br /&gt;
 attr rr_Franz rr_presenceDevices ble2mqttGTag&lt;br /&gt;
&lt;br /&gt;
[[Category:MQTT]][[Category:Anwesenheitserkennung]][[Category:FHEM Utilities]]&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Ble2mqtt&amp;diff=38671</id>
		<title>Ble2mqtt</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Ble2mqtt&amp;diff=38671"/>
		<updated>2023-11-08T14:51:49Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: /* Einbindung in FHEM */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=Anwesenheitserkennung von Bluetooth-Geräten&lt;br /&gt;
|ModType=u&lt;br /&gt;
|ModFTopic=127173&lt;br /&gt;
|ModForumArea=Unterstützende Dienste&lt;br /&gt;
|ModTechName=ble2mqtt&lt;br /&gt;
|ModOwner=PatrickR&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;ble2mqtt&#039;&#039;&#039; ist ein Script, dass den Anwesenheitsstatus eines oder mehrerer Bluetooth Low Energy Geräte überprüfen und das Ergebnis an einen MQTT Broker schicken kann.&lt;br /&gt;
&lt;br /&gt;
Es verwendet dazu die Linux Tools &#039;&#039;bluetoothctl&#039;&#039; und &#039;&#039;gatttool&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
ble2mqtt ist in Perl geschrieben und wurde von {{Link2FU|5068|PatrickR}} erstellt. Weitere Informationen finden sich in diesem {{Link2Forum|Topic=127173|LinkText=Forums-Topic }}. Fragen dazu bitte in den Bereich [https://forum.fhem.de/index.php?board=44.0 Unterstützende Dienste]&lt;br /&gt;
&amp;lt;!--diesen {{Link2Forum|Area=44|LinkText=Bereich }}.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Voraussetzungen==&lt;br /&gt;
* Debian od. Raspberry Pi OS&lt;br /&gt;
* Bluetooth Empfänger&lt;br /&gt;
&lt;br /&gt;
==Parameter==&lt;br /&gt;
Beim Start von ble2mqtt können folgende Parameter angegeben werden:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Parameter!!Beschreibung!!Standardwert!!Beispiel!!Optional&lt;br /&gt;
|-&lt;br /&gt;
| --mqttserver&lt;br /&gt;
|Die Adresse des MQTT Brokers inklusive Port&lt;br /&gt;
|&lt;br /&gt;
| --mqttserver mqtt.example.org:1883&lt;br /&gt;
|nein&lt;br /&gt;
|-&lt;br /&gt;
| --mqttfingerprint&lt;br /&gt;
|Der Fingerprint des für die TLS-verschlüsselte Kommunikation mit dem MQTT Broker verwendeten Zertifikates&lt;br /&gt;
|&lt;br /&gt;
| --mqttfingerprint bfe5d244a821194230f1479fe2f8f7bbcd2a8cb8&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --mqtttopic&lt;br /&gt;
| An welches MQTT-Topic das Tool die Informationen schicken soll.&lt;br /&gt;
|ble2mqtt&lt;br /&gt;
| --mqtttopic ble2mqtt/Wohnzimmer&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --mqttuser&lt;br /&gt;
|Der Benutzernamen, unter dem die Verbindung zum Broker hergestellt werden soll&lt;br /&gt;
|&lt;br /&gt;
| --mqttuser ble2mqtt&lt;br /&gt;
|ja bzw. abhängig vom Broker&lt;br /&gt;
|-&lt;br /&gt;
| --mqttpass&lt;br /&gt;
|Das zum Benutzernamen gehörende Passwort&lt;br /&gt;
|&lt;br /&gt;
| --mqttpass verysecret3&lt;br /&gt;
|ja bzw. abhängig vom Broker&lt;br /&gt;
|-&lt;br /&gt;
| --retain&lt;br /&gt;
|Versendet die Nachrichten present und lastseen als retained.&lt;br /&gt;
|0&lt;br /&gt;
| --retain&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --daemonize&lt;br /&gt;
|Wenn ble2mqtt im Hintergrund (als Daemon) ausgeführt werden soll&lt;br /&gt;
|0&lt;br /&gt;
| --daemonize&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --loglevel&lt;br /&gt;
|Wie und was genau protokolliert werden soll. Mögliche Loglevel sind LOG_CRIT, LOG_ERR, LOG_WARNING, LOG_NOTICE, LOG_INFO, LOG_DEBUG.&lt;br /&gt;
|LOG_INFO&lt;br /&gt;
| --loglevel LOG_ERR&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --logtarget&lt;br /&gt;
|Wohin gelogged werden soll. Mögliche Optionen sind &#039;&#039;syslog&#039;&#039; und &#039;&#039;stdout&#039;&#039;.&lt;br /&gt;
|syslog&lt;br /&gt;
| --logtarget stdout&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --absentinterval&lt;br /&gt;
|Anzahl an Sekunden, nach denen das Gerät als abwesend bezeichnet werden soll. Mindestwert ist 30.&lt;br /&gt;
|60&lt;br /&gt;
| --absentinterval 120&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --rssithreshold&lt;br /&gt;
|Ab welcher Abweichung des RSSI Wertes ein Update getriggert werden soll. Mindestwert ist 5.&lt;br /&gt;
|10&lt;br /&gt;
| --rssithreshold 8&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --watchdogthreshold&lt;br /&gt;
|Ab welchem Zeitraum in Sekunden nach Empfangen des letzten BT-Signals ble2mqtt neu gestartet werden soll. Mindestwert ist 30. Der Wert 0 bedeutet deaktiviert, also nie.&lt;br /&gt;
|0&lt;br /&gt;
| --watchdogthreshold 30&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --debug&lt;br /&gt;
|Kann nur gemeinsam mit --daemonize verwendet werden, um Logeinträge auf stdout auszugeben. Je höher die Nummer, desto mehr Output.&lt;br /&gt;
|0&lt;br /&gt;
| --daemonize --debug 4&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --mac&lt;br /&gt;
|Filtert mittels Regex nach MAC-Adressen der von ble2mqtt zu beachtenden BLE-Geräte. Alle anderen Geräte werden ignoriert.&lt;br /&gt;
|&lt;br /&gt;
| --mac &#039;(11:22:33:44:55:66|77:88:99:00:AA:BB)&#039;&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --batterymaxage&lt;br /&gt;
|Zeit in Stunden, nach denen ein Batterie-Wert als veraltet angesehen und aktualisiert wird. Der Wert 0 deaktiviert den Batterie-Check.&lt;br /&gt;
|48&lt;br /&gt;
| --batterymaxage 6&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --forcebattery&lt;br /&gt;
|Nur in Kombination mit --mac. Erzwingt einen Batterie-Check, auch wenn das battery-service am Gerät nicht erkannt wird.&lt;br /&gt;
|0&lt;br /&gt;
| --forcebattery&lt;br /&gt;
|ja&lt;br /&gt;
|}&lt;br /&gt;
===Beispiele===&lt;br /&gt;
* Broker verlangt Username/Passwort; es sollen keine Batterie-Werte ausgelesen werden&lt;br /&gt;
 ble2mqtt --mqttserver mqtt.example.org:1883 --mqttuser ble2mqtt --mqttpass verysecret3 --batterymaxage 0&lt;br /&gt;
&lt;br /&gt;
* Broker verlangt keine Authentifizierung; es soll nach zwei G-Tags gesucht werden; definiertes MQTT-Topic; Batteriewerte benötigt&lt;br /&gt;
 ble2mqtt --mqttserver mqtt.example.org:1883 --mqtttopic ble2mqtt/Wohnzimmer --mac &#039;(11:22:33:44:55:66|77:88:99:00:AA:BB)&#039;&lt;br /&gt;
&lt;br /&gt;
* Broker verlangt keine Authentifizierung; Geräte sollen nach 45s ohne Kontakt als abwesend angezeigt werden; MQTT Nachrichten sollen gespeichert bleiben&lt;br /&gt;
 ble2mqtt --mqttserver mqtt.example.org:1883 --absentinterval 45 --retain&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
Zur Installation muss das ble2mqtt-Script auf den Server kopiert werden und es müssen diverse Linux- und Perl-Pakete installiert werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zuerst das Script nach /usr/local/bin kopieren, um beim Aufruf in der Bash nicht immer den ganzen Pfad voranstellen zu müssen.&lt;br /&gt;
 sudo cp -a ble2mqttd /usr/local/bin/&lt;br /&gt;
Danach das Script noch als ausführbar markieren&lt;br /&gt;
 sudo chmod +x /usr/local/bin/ble2mqttd&lt;br /&gt;
&lt;br /&gt;
===Benötigte Linux Pakete===&lt;br /&gt;
Die benötigten Pakete können ganz einfach mit &#039;&#039;apt&#039;&#039; installiert werden. Dabei werden auch mögliche Abhängigkeiten automatisch installiert.&lt;br /&gt;
&lt;br /&gt;
 sudo apt install -y libssl-dev libio-socket-ssl-perl libreadonly-perl libtest-expect-perl libnet-ssleay-perl libnet-server-perl&lt;br /&gt;
&lt;br /&gt;
===Benötigte Perl-Module===&lt;br /&gt;
Es wird das Modul &#039;&#039;Net::MQTT::Simple&#039;&#039; (&#039;&#039;libnet-mqtt-simple-perl&#039;&#039;) benötigt. Das ist - Stand 08.11.2023 - noch nicht in den Stable-Repositories von Debian verfügbar und muss daher mittels &#039;&#039;cpan&#039;&#039; installiert werden. Voraussetzung dafür ist das Modul &#039;&#039;CPAN::DistnameInfo&#039;&#039;, welches zuerst installiert werden muss.&lt;br /&gt;
&lt;br /&gt;
 sudo cpan CPAN::DistnameInfo&lt;br /&gt;
 sudo cpan Net::MQTT::Simple&lt;br /&gt;
&lt;br /&gt;
Sobald &#039;&#039;libnet-mqtt-simple-perl&#039;&#039; verfügbar ist, kann dieses statt der Perl-Module wie ein normales Linux-Paket installiert werden.&lt;br /&gt;
&lt;br /&gt;
===Erster Test===&lt;br /&gt;
Mit einem einfachen Aufruf von &#039;&#039;&#039;ble2mqtt&#039;&#039;&#039; kann getestet werden, ob alle benötigten Module und Pakete vorhanden sind.&lt;br /&gt;
&lt;br /&gt;
 sudo /usr/local/bin/ble2mqttd&lt;br /&gt;
&lt;br /&gt;
===Erstellen einens Systemd-Daemons===&lt;br /&gt;
Damit &#039;&#039;&#039;ble2mqtt&#039;&#039;&#039; bei jedem Systemstart automatisch gestartet wird, muss ein Systemd-Daemon erstellt werden. Das wird gemacht, in dem eine neue Textdatei mit folgendem Inhalt angelegt und der Daemon dann aktiviert wird.&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|Text=&#039;&#039;&#039;Wichtig:&#039;&#039;&#039; Das Kommando, mit welchen Parametern ble2mqtt gestartet wird, muss natürlich individuell angepasst werden!}}&lt;br /&gt;
&lt;br /&gt;
 sudo nano /etc/systemd/system/ble2mqttd.service&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=ble2mqttd&lt;br /&gt;
After=bluetooth.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
Restart=always&lt;br /&gt;
ExecStart=/usr/local/bin/ble2mqttd --mqttserver mqtt.example.com:1883 --mqtttopic ble2mqtt/wohnzimmer --mac &#039;(11:22:33:44:55:66|77:88:99:00:AA:BB)&#039; --absentinterval 30 --mqttuser &amp;lt;username&amp;gt; --mqttpass &amp;lt;password&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 sudo systemctl daemon-reload&lt;br /&gt;
 sudo systemctl enable ble2mqttd.service&lt;br /&gt;
 sudo systemctl start ble2mqttd.service&lt;br /&gt;
&lt;br /&gt;
==Einbindung in FHEM==&lt;br /&gt;
Da ble2mqtt alle Informationen an einen [[MQTT]]-Broker sendet, können diese Informationen ganz einfach als [[MQTT2_DEVICE]] in FHEM eingebunden werden. Wie dabei vorgegangen werden kann, unterscheidet sich je nach Anwendungsbereich und den eigenen Vorlieben.&lt;br /&gt;
&lt;br /&gt;
Als Beispiel sie hier die Anwesenheitserkennung mittels BT-Tags angeführt.&lt;br /&gt;
&lt;br /&gt;
===Anwesenheitserkennung mittels BT-Tags===&lt;br /&gt;
[[File:ble2mqtt.png|thumb|Readings eines Devices, dass mit diesem Code erstellt wurde]]&lt;br /&gt;
Der folgende Code geht davon aus, dass es mehrere ble2mqtt-Instanzen gibt und ein BT-Tag mit der MAC-Adresse AA:BB:CC:DD:EE:FF erkannt werden soll.&lt;br /&gt;
&lt;br /&gt;
Die verschiedenen ble2mqtt-Instanzen schicken ihre Nachrichten in unterschiedliche Topics.&lt;br /&gt;
Für jede Instanz ein eigenes Topic:&lt;br /&gt;
*ble2mqtt/wohnzimmer&lt;br /&gt;
*ble2mqtt/schlafzimmer&lt;br /&gt;
*ble2mqtt/kueche&lt;br /&gt;
Im Attribut &#039;&#039;devicetopic&#039;&#039; werden diese Topics dann gemeinsam ausgewertet. Das funktioniert, in dem der Name des Subtopics einfach durch den Regex-Ausdruck &#039;&#039;.*&#039;&#039; ersetzt wird.&lt;br /&gt;
&lt;br /&gt;
Bedeutet aber auch, dass die Informationen - wenn gewünscht - wieder in unterschiedliche Readings zerlegt werden müssen. Um z.B. schnell zu erkennen, in welchem Raum der BT-Tag gerade liegt. Das passiert hier z.B. bei den Nachrichten für &#039;&#039;rssi&#039;&#039; und &#039;&#039;presence&#039;&#039;. Daraus resultieren dann eigene Readings für jedes MQTT-Subtopic.&lt;br /&gt;
&lt;br /&gt;
Das &amp;quot;raumübergreifende&amp;quot; Reading &#039;&#039;presence&#039;&#039; wird anhand der des Alters in Sekunden der letzten lastseen-Nachricht gesteuert. Die lastseen-Nachricht wird immer gesendet, wenn der Scanvorgang von ble2mqtt das gewünschte Gerät findet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
define ble2mqttGTag MQTT2_DEVICE FHEM&lt;br /&gt;
attr ble2mqttGTag devicetopic ble2mqtt/.*/AA_BB_CC_DD_EE_FF&lt;br /&gt;
attr ble2mqttGTag event-on-change-reading .*&lt;br /&gt;
attr ble2mqttGTag readingList ble2mqtt/.*/heartbeat:.* heartbeat&lt;br /&gt;
$DEVICETOPIC/rssi:.* {my $room=(split m{[/]}x,$TOPIC)[1]; my $roomMax=$room; my $rssiMax=$EVENT; my @readings = grep { $_ =~ m{\Arssi_(?!$room).*}x } keys %{$defs{&amp;quot;$NAME&amp;quot;}-&amp;gt;{READINGS}}; for (@readings) {my $rssiTmp=ReadingsVal($NAME,$_,&#039;-100&#039;); my $roomTmp=(split m{[_]}x,$_)[1]; if(($rssiMax gt $rssiTmp)&amp;amp;&amp;amp;(ReadingsVal($NAME,&amp;quot;presence_&amp;quot;.$roomTmp,&#039;absent&#039;) eq &#039;present&#039;)) {$rssiMax=$rssiTmp; $roomMax=$roomTmp}}; {rssi=&amp;gt;$rssiMax,room=&amp;gt;$roomMax,&amp;quot;rssi_$room&amp;quot;=&amp;gt;$EVENT}}&lt;br /&gt;
$DEVICETOPIC/lastseen:.* {lastseen=&amp;gt;strftime &amp;quot;%Y-%m-%d %H:%M:%S&amp;quot;, localtime($EVENT)}&lt;br /&gt;
$DEVICETOPIC/present:.* {my $roomAct=(split m{[/]}x,$TOPIC)[1]; my $rssi=ReadingsVal($NAME,&amp;quot;rssi_&amp;quot;.$roomAct,&#039;-100&#039;); my $presenceAct=$EVENT?&#039;present&#039;:&#039;absent&#039;; my $room=$EVENT ? $roomAct:&#039;&#039;; my @readings = grep { $_ =~ m{\Apresence_(?!$roomAct).*}x } keys %{$defs{$NAME}-&amp;gt;{READINGS}}; for (@readings) {if(ReadingsVal($NAME,$_,&#039;absent&#039;) eq &#039;present&#039;) {my $roomTmp=(split m{[_]}x,$_)[1]; my $rssiTmp=ReadingsVal($NAME,&amp;quot;rssi_&amp;quot;.$roomTmp,&#039;-100&#039;); if($rssi gt $rssiTmp){$room=$roomTmp; $rssi=$rssiTmp}}}; {&amp;quot;presence_$roomAct&amp;quot;=&amp;gt;$presenceAct, room=&amp;gt;$room}}&lt;br /&gt;
ble2mqtt/.*/state:.* state&lt;br /&gt;
$DEVICETOPIC/battery:.* batteryLevel&lt;br /&gt;
attr ble2mqttGTag userReadings presence {if (ReadingsAge($NAME,&amp;quot;lastseen&amp;quot;,0)&amp;gt;60) {return &amp;quot;absent&amp;quot;;}else{return &amp;quot;present&amp;quot;;}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Ergebnis ist unter anderem ein Reading &#039;&#039;presence&#039;&#039; mit den Zuständen &#039;&#039;absent&#039;&#039; und &#039;&#039;present&#039;&#039;. Es kann somit ganz einfach als &amp;quot;presenceDevice&amp;quot; in einem [[ROOMMATE]]-Device verwendet werden:&lt;br /&gt;
 attr rr_Franz rr_presenceDevices ble2mqttGTag&lt;br /&gt;
&lt;br /&gt;
[[Category:MQTT]][[Category:Anwesenheitserkennung]][[Category:FHEM Utilities]]&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Datei:Ble2mqtt.png&amp;diff=38670</id>
		<title>Datei:Ble2mqtt.png</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Datei:Ble2mqtt.png&amp;diff=38670"/>
		<updated>2023-11-08T14:51:31Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: Readings eines MQTT2_DEVICE, dass mit diesem Code aus ble2mqtt erstellt wurde&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Beschreibung ==&lt;br /&gt;
Readings eines MQTT2_DEVICE, dass mit diesem Code aus [[ble2mqtt]] erstellt wurde&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Ble2mqtt&amp;diff=38669</id>
		<title>Ble2mqtt</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Ble2mqtt&amp;diff=38669"/>
		<updated>2023-11-08T14:49:05Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=Anwesenheitserkennung von Bluetooth-Geräten&lt;br /&gt;
|ModType=u&lt;br /&gt;
|ModFTopic=127173&lt;br /&gt;
|ModForumArea=Unterstützende Dienste&lt;br /&gt;
|ModTechName=ble2mqtt&lt;br /&gt;
|ModOwner=PatrickR&lt;br /&gt;
}}&lt;br /&gt;
&#039;&#039;&#039;ble2mqtt&#039;&#039;&#039; ist ein Script, dass den Anwesenheitsstatus eines oder mehrerer Bluetooth Low Energy Geräte überprüfen und das Ergebnis an einen MQTT Broker schicken kann.&lt;br /&gt;
&lt;br /&gt;
Es verwendet dazu die Linux Tools &#039;&#039;bluetoothctl&#039;&#039; und &#039;&#039;gatttool&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
ble2mqtt ist in Perl geschrieben und wurde von {{Link2FU|5068|PatrickR}} erstellt. Weitere Informationen finden sich in diesem {{Link2Forum|Topic=127173|LinkText=Forums-Topic }}. Fragen dazu bitte in den Bereich [https://forum.fhem.de/index.php?board=44.0 Unterstützende Dienste]&lt;br /&gt;
&amp;lt;!--diesen {{Link2Forum|Area=44|LinkText=Bereich }}.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Voraussetzungen==&lt;br /&gt;
* Debian od. Raspberry Pi OS&lt;br /&gt;
* Bluetooth Empfänger&lt;br /&gt;
&lt;br /&gt;
==Parameter==&lt;br /&gt;
Beim Start von ble2mqtt können folgende Parameter angegeben werden:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Parameter!!Beschreibung!!Standardwert!!Beispiel!!Optional&lt;br /&gt;
|-&lt;br /&gt;
| --mqttserver&lt;br /&gt;
|Die Adresse des MQTT Brokers inklusive Port&lt;br /&gt;
|&lt;br /&gt;
| --mqttserver mqtt.example.org:1883&lt;br /&gt;
|nein&lt;br /&gt;
|-&lt;br /&gt;
| --mqttfingerprint&lt;br /&gt;
|Der Fingerprint des für die TLS-verschlüsselte Kommunikation mit dem MQTT Broker verwendeten Zertifikates&lt;br /&gt;
|&lt;br /&gt;
| --mqttfingerprint bfe5d244a821194230f1479fe2f8f7bbcd2a8cb8&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --mqtttopic&lt;br /&gt;
| An welches MQTT-Topic das Tool die Informationen schicken soll.&lt;br /&gt;
|ble2mqtt&lt;br /&gt;
| --mqtttopic ble2mqtt/Wohnzimmer&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --mqttuser&lt;br /&gt;
|Der Benutzernamen, unter dem die Verbindung zum Broker hergestellt werden soll&lt;br /&gt;
|&lt;br /&gt;
| --mqttuser ble2mqtt&lt;br /&gt;
|ja bzw. abhängig vom Broker&lt;br /&gt;
|-&lt;br /&gt;
| --mqttpass&lt;br /&gt;
|Das zum Benutzernamen gehörende Passwort&lt;br /&gt;
|&lt;br /&gt;
| --mqttpass verysecret3&lt;br /&gt;
|ja bzw. abhängig vom Broker&lt;br /&gt;
|-&lt;br /&gt;
| --retain&lt;br /&gt;
|Versendet die Nachrichten present und lastseen als retained.&lt;br /&gt;
|0&lt;br /&gt;
| --retain&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --daemonize&lt;br /&gt;
|Wenn ble2mqtt im Hintergrund (als Daemon) ausgeführt werden soll&lt;br /&gt;
|0&lt;br /&gt;
| --daemonize&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --loglevel&lt;br /&gt;
|Wie und was genau protokolliert werden soll. Mögliche Loglevel sind LOG_CRIT, LOG_ERR, LOG_WARNING, LOG_NOTICE, LOG_INFO, LOG_DEBUG.&lt;br /&gt;
|LOG_INFO&lt;br /&gt;
| --loglevel LOG_ERR&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --logtarget&lt;br /&gt;
|Wohin gelogged werden soll. Mögliche Optionen sind &#039;&#039;syslog&#039;&#039; und &#039;&#039;stdout&#039;&#039;.&lt;br /&gt;
|syslog&lt;br /&gt;
| --logtarget stdout&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --absentinterval&lt;br /&gt;
|Anzahl an Sekunden, nach denen das Gerät als abwesend bezeichnet werden soll. Mindestwert ist 30.&lt;br /&gt;
|60&lt;br /&gt;
| --absentinterval 120&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --rssithreshold&lt;br /&gt;
|Ab welcher Abweichung des RSSI Wertes ein Update getriggert werden soll. Mindestwert ist 5.&lt;br /&gt;
|10&lt;br /&gt;
| --rssithreshold 8&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --watchdogthreshold&lt;br /&gt;
|Ab welchem Zeitraum in Sekunden nach Empfangen des letzten BT-Signals ble2mqtt neu gestartet werden soll. Mindestwert ist 30. Der Wert 0 bedeutet deaktiviert, also nie.&lt;br /&gt;
|0&lt;br /&gt;
| --watchdogthreshold 30&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --debug&lt;br /&gt;
|Kann nur gemeinsam mit --daemonize verwendet werden, um Logeinträge auf stdout auszugeben. Je höher die Nummer, desto mehr Output.&lt;br /&gt;
|0&lt;br /&gt;
| --daemonize --debug 4&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --mac&lt;br /&gt;
|Filtert mittels Regex nach MAC-Adressen der von ble2mqtt zu beachtenden BLE-Geräte. Alle anderen Geräte werden ignoriert.&lt;br /&gt;
|&lt;br /&gt;
| --mac &#039;(11:22:33:44:55:66|77:88:99:00:AA:BB)&#039;&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --batterymaxage&lt;br /&gt;
|Zeit in Stunden, nach denen ein Batterie-Wert als veraltet angesehen und aktualisiert wird. Der Wert 0 deaktiviert den Batterie-Check.&lt;br /&gt;
|48&lt;br /&gt;
| --batterymaxage 6&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --forcebattery&lt;br /&gt;
|Nur in Kombination mit --mac. Erzwingt einen Batterie-Check, auch wenn das battery-service am Gerät nicht erkannt wird.&lt;br /&gt;
|0&lt;br /&gt;
| --forcebattery&lt;br /&gt;
|ja&lt;br /&gt;
|}&lt;br /&gt;
===Beispiele===&lt;br /&gt;
* Broker verlangt Username/Passwort; es sollen keine Batterie-Werte ausgelesen werden&lt;br /&gt;
 ble2mqtt --mqttserver mqtt.example.org:1883 --mqttuser ble2mqtt --mqttpass verysecret3 --batterymaxage 0&lt;br /&gt;
&lt;br /&gt;
* Broker verlangt keine Authentifizierung; es soll nach zwei G-Tags gesucht werden; definiertes MQTT-Topic; Batteriewerte benötigt&lt;br /&gt;
 ble2mqtt --mqttserver mqtt.example.org:1883 --mqtttopic ble2mqtt/Wohnzimmer --mac &#039;(11:22:33:44:55:66|77:88:99:00:AA:BB)&#039;&lt;br /&gt;
&lt;br /&gt;
* Broker verlangt keine Authentifizierung; Geräte sollen nach 45s ohne Kontakt als abwesend angezeigt werden; MQTT Nachrichten sollen gespeichert bleiben&lt;br /&gt;
 ble2mqtt --mqttserver mqtt.example.org:1883 --absentinterval 45 --retain&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
Zur Installation muss das ble2mqtt-Script auf den Server kopiert werden und es müssen diverse Linux- und Perl-Pakete installiert werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zuerst das Script nach /usr/local/bin kopieren, um beim Aufruf in der Bash nicht immer den ganzen Pfad voranstellen zu müssen.&lt;br /&gt;
 sudo cp -a ble2mqttd /usr/local/bin/&lt;br /&gt;
Danach das Script noch als ausführbar markieren&lt;br /&gt;
 sudo chmod +x /usr/local/bin/ble2mqttd&lt;br /&gt;
&lt;br /&gt;
===Benötigte Linux Pakete===&lt;br /&gt;
Die benötigten Pakete können ganz einfach mit &#039;&#039;apt&#039;&#039; installiert werden. Dabei werden auch mögliche Abhängigkeiten automatisch installiert.&lt;br /&gt;
&lt;br /&gt;
 sudo apt install -y libssl-dev libio-socket-ssl-perl libreadonly-perl libtest-expect-perl libnet-ssleay-perl libnet-server-perl&lt;br /&gt;
&lt;br /&gt;
===Benötigte Perl-Module===&lt;br /&gt;
Es wird das Modul &#039;&#039;Net::MQTT::Simple&#039;&#039; (&#039;&#039;libnet-mqtt-simple-perl&#039;&#039;) benötigt. Das ist - Stand 08.11.2023 - noch nicht in den Stable-Repositories von Debian verfügbar und muss daher mittels &#039;&#039;cpan&#039;&#039; installiert werden. Voraussetzung dafür ist das Modul &#039;&#039;CPAN::DistnameInfo&#039;&#039;, welches zuerst installiert werden muss.&lt;br /&gt;
&lt;br /&gt;
 sudo cpan CPAN::DistnameInfo&lt;br /&gt;
 sudo cpan Net::MQTT::Simple&lt;br /&gt;
&lt;br /&gt;
Sobald &#039;&#039;libnet-mqtt-simple-perl&#039;&#039; verfügbar ist, kann dieses statt der Perl-Module wie ein normales Linux-Paket installiert werden.&lt;br /&gt;
&lt;br /&gt;
===Erster Test===&lt;br /&gt;
Mit einem einfachen Aufruf von &#039;&#039;&#039;ble2mqtt&#039;&#039;&#039; kann getestet werden, ob alle benötigten Module und Pakete vorhanden sind.&lt;br /&gt;
&lt;br /&gt;
 sudo /usr/local/bin/ble2mqttd&lt;br /&gt;
&lt;br /&gt;
===Erstellen einens Systemd-Daemons===&lt;br /&gt;
Damit &#039;&#039;&#039;ble2mqtt&#039;&#039;&#039; bei jedem Systemstart automatisch gestartet wird, muss ein Systemd-Daemon erstellt werden. Das wird gemacht, in dem eine neue Textdatei mit folgendem Inhalt angelegt und der Daemon dann aktiviert wird.&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|Text=&#039;&#039;&#039;Wichtig:&#039;&#039;&#039; Das Kommando, mit welchen Parametern ble2mqtt gestartet wird, muss natürlich individuell angepasst werden!}}&lt;br /&gt;
&lt;br /&gt;
 sudo nano /etc/systemd/system/ble2mqttd.service&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=ble2mqttd&lt;br /&gt;
After=bluetooth.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
Restart=always&lt;br /&gt;
ExecStart=/usr/local/bin/ble2mqttd --mqttserver mqtt.example.com:1883 --mqtttopic ble2mqtt/wohnzimmer --mac &#039;(11:22:33:44:55:66|77:88:99:00:AA:BB)&#039; --absentinterval 30 --mqttuser &amp;lt;username&amp;gt; --mqttpass &amp;lt;password&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 sudo systemctl daemon-reload&lt;br /&gt;
 sudo systemctl enable ble2mqttd.service&lt;br /&gt;
 sudo systemctl start ble2mqttd.service&lt;br /&gt;
&lt;br /&gt;
==Einbindung in FHEM==&lt;br /&gt;
Da ble2mqtt alle Informationen an einen [[MQTT]]-Broker sendet, können diese Informationen ganz einfach als [[MQTT2_DEVICE]] in FHEM eingebunden werden. Wie dabei vorgegangen werden kann, unterscheidet sich je nach Anwendungsbereich und den eigenen Vorlieben.&lt;br /&gt;
&lt;br /&gt;
Als Beispiel sie hier die Anwesenheitserkennung mittels BT-Tags angeführt.&lt;br /&gt;
&lt;br /&gt;
===Anwesenheitserkennung mittels BT-Tags===&lt;br /&gt;
[[File:ble2mqtt.png|thumb|Readings eines Devices, dass mit diesem Codes erstellt wurde]]&lt;br /&gt;
Der folgende Code geht davon aus, dass es mehrere ble2mqtt-Instanzen gibt und ein BT-Tag mit der MAC-Adresse AA:BB:CC:DD:EE:FF erkannt werden soll.&lt;br /&gt;
&lt;br /&gt;
Die verschiedenen ble2mqtt-Instanzen schicken ihre Nachrichten in unterschiedliche Topics.&lt;br /&gt;
Für jede Instanz ein eigenes Topic:&lt;br /&gt;
*ble2mqtt/wohnzimmer&lt;br /&gt;
*ble2mqtt/schlafzimmer&lt;br /&gt;
*ble2mqtt/kueche&lt;br /&gt;
Im Attribut &#039;&#039;devicetopic&#039;&#039; werden diese Topics dann gemeinsam ausgewertet. Das funktioniert, in dem der Name des Subtopics einfach durch den Regex-Ausdruck &#039;&#039;.*&#039;&#039; ersetzt wird.&lt;br /&gt;
&lt;br /&gt;
Bedeutet aber auch, dass die Informationen - wenn gewünscht - wieder in unterschiedliche Readings zerlegt werden müssen. Um z.B. schnell zu erkennen, in welchem Raum der BT-Tag gerade liegt. Das passiert hier z.B. bei den Nachrichten für &#039;&#039;rssi&#039;&#039; und &#039;&#039;presence&#039;&#039;. Daraus resultieren dann eigene Readings für jedes MQTT-Subtopic.&lt;br /&gt;
&lt;br /&gt;
Das &amp;quot;raumübergreifende&amp;quot; Reading &#039;&#039;presence&#039;&#039; wird anhand der des Alters in Sekunden der letzten lastseen-Nachricht gesteuert. Die lastseen-Nachricht wird immer gesendet, wenn der Scanvorgang von ble2mqtt das gewünschte Gerät findet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
define ble2mqttGTag MQTT2_DEVICE FHEM&lt;br /&gt;
attr ble2mqttGTag devicetopic ble2mqtt/.*/AA_BB_CC_DD_EE_FF&lt;br /&gt;
attr ble2mqttGTag event-on-change-reading .*&lt;br /&gt;
attr ble2mqttGTag readingList ble2mqtt/.*/heartbeat:.* heartbeat&lt;br /&gt;
$DEVICETOPIC/rssi:.* {my $room=(split m{[/]}x,$TOPIC)[1]; my $roomMax=$room; my $rssiMax=$EVENT; my @readings = grep { $_ =~ m{\Arssi_(?!$room).*}x } keys %{$defs{&amp;quot;$NAME&amp;quot;}-&amp;gt;{READINGS}}; for (@readings) {my $rssiTmp=ReadingsVal($NAME,$_,&#039;-100&#039;); my $roomTmp=(split m{[_]}x,$_)[1]; if(($rssiMax gt $rssiTmp)&amp;amp;&amp;amp;(ReadingsVal($NAME,&amp;quot;presence_&amp;quot;.$roomTmp,&#039;absent&#039;) eq &#039;present&#039;)) {$rssiMax=$rssiTmp; $roomMax=$roomTmp}}; {rssi=&amp;gt;$rssiMax,room=&amp;gt;$roomMax,&amp;quot;rssi_$room&amp;quot;=&amp;gt;$EVENT}}&lt;br /&gt;
$DEVICETOPIC/lastseen:.* {lastseen=&amp;gt;strftime &amp;quot;%Y-%m-%d %H:%M:%S&amp;quot;, localtime($EVENT)}&lt;br /&gt;
$DEVICETOPIC/present:.* {my $roomAct=(split m{[/]}x,$TOPIC)[1]; my $rssi=ReadingsVal($NAME,&amp;quot;rssi_&amp;quot;.$roomAct,&#039;-100&#039;); my $presenceAct=$EVENT?&#039;present&#039;:&#039;absent&#039;; my $room=$EVENT ? $roomAct:&#039;&#039;; my @readings = grep { $_ =~ m{\Apresence_(?!$roomAct).*}x } keys %{$defs{$NAME}-&amp;gt;{READINGS}}; for (@readings) {if(ReadingsVal($NAME,$_,&#039;absent&#039;) eq &#039;present&#039;) {my $roomTmp=(split m{[_]}x,$_)[1]; my $rssiTmp=ReadingsVal($NAME,&amp;quot;rssi_&amp;quot;.$roomTmp,&#039;-100&#039;); if($rssi gt $rssiTmp){$room=$roomTmp; $rssi=$rssiTmp}}}; {&amp;quot;presence_$roomAct&amp;quot;=&amp;gt;$presenceAct, room=&amp;gt;$room}}&lt;br /&gt;
ble2mqtt/.*/state:.* state&lt;br /&gt;
$DEVICETOPIC/battery:.* batteryLevel&lt;br /&gt;
attr ble2mqttGTag userReadings presence {if (ReadingsAge($NAME,&amp;quot;lastseen&amp;quot;,0)&amp;gt;60) {return &amp;quot;absent&amp;quot;;}else{return &amp;quot;present&amp;quot;;}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Ergebnis ist unter anderem ein Reading &#039;&#039;presence&#039;&#039; mit den Zuständen &#039;&#039;absent&#039;&#039; und &#039;&#039;present&#039;&#039;. Es kann somit ganz einfach als &amp;quot;presenceDevice&amp;quot; in einem [[ROOMMATE]]-Device verwendet werden:&lt;br /&gt;
 attr rr_Franz rr_presenceDevices ble2mqttGTag&lt;br /&gt;
&lt;br /&gt;
[[Category:MQTT]][[Category:Anwesenheitserkennung]][[Category:FHEM Utilities]]&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Ble2mqtt&amp;diff=38668</id>
		<title>Ble2mqtt</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Ble2mqtt&amp;diff=38668"/>
		<updated>2023-11-08T14:44:23Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: Die Seite wurde neu angelegt: „{{Baustelle}} &amp;#039;&amp;#039;&amp;#039;ble2mqtt&amp;#039;&amp;#039;&amp;#039; ist ein Script, dass den Anwesenheitsstatus eines oder mehrerer Bluetooth Low Energy Geräte überprüfen und das Ergebnis an einen MQTT Broker schicken kann.  Es verwendet dazu die Linux Tools &amp;#039;&amp;#039;bluetoothctl&amp;#039;&amp;#039; und &amp;#039;&amp;#039;gatttool&amp;#039;&amp;#039;.  ble2mqtt ist in Perl geschrieben und wurde von {{Link2FU|5068|PatrickR}} erstellt. Weitere Informationen finden sich in diesem {{Link2Forum|Topic=127173|LinkText=Forums-Topic }}. Fragen dazu bitte in…“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
&#039;&#039;&#039;ble2mqtt&#039;&#039;&#039; ist ein Script, dass den Anwesenheitsstatus eines oder mehrerer Bluetooth Low Energy Geräte überprüfen und das Ergebnis an einen MQTT Broker schicken kann.&lt;br /&gt;
&lt;br /&gt;
Es verwendet dazu die Linux Tools &#039;&#039;bluetoothctl&#039;&#039; und &#039;&#039;gatttool&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
ble2mqtt ist in Perl geschrieben und wurde von {{Link2FU|5068|PatrickR}} erstellt. Weitere Informationen finden sich in diesem {{Link2Forum|Topic=127173|LinkText=Forums-Topic }}. Fragen dazu bitte in den Bereich [https://forum.fhem.de/index.php?board=44.0 Unterstützende Dienste]&lt;br /&gt;
&amp;lt;!--diesen {{Link2Forum|Area=44|LinkText=Bereich }}.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Voraussetzungen==&lt;br /&gt;
* Debian od. Raspberry Pi OS&lt;br /&gt;
* Bluetooth Empfänger&lt;br /&gt;
&lt;br /&gt;
==Parameter==&lt;br /&gt;
Beim Start von ble2mqtt können folgende Parameter angegeben werden:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Parameter!!Beschreibung!!Standardwert!!Beispiel!!Optional&lt;br /&gt;
|-&lt;br /&gt;
| --mqttserver&lt;br /&gt;
|Die Adresse des MQTT Brokers inklusive Port&lt;br /&gt;
|&lt;br /&gt;
| --mqttserver mqtt.example.org:1883&lt;br /&gt;
|nein&lt;br /&gt;
|-&lt;br /&gt;
| --mqttfingerprint&lt;br /&gt;
|Der Fingerprint des für die TLS-verschlüsselte Kommunikation mit dem MQTT Broker verwendeten Zertifikates&lt;br /&gt;
|&lt;br /&gt;
| --mqttfingerprint bfe5d244a821194230f1479fe2f8f7bbcd2a8cb8&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --mqtttopic&lt;br /&gt;
| An welches MQTT-Topic das Tool die Informationen schicken soll.&lt;br /&gt;
|ble2mqtt&lt;br /&gt;
| --mqtttopic ble2mqtt/Wohnzimmer&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --mqttuser&lt;br /&gt;
|Der Benutzernamen, unter dem die Verbindung zum Broker hergestellt werden soll&lt;br /&gt;
|&lt;br /&gt;
| --mqttuser ble2mqtt&lt;br /&gt;
|ja bzw. abhängig vom Broker&lt;br /&gt;
|-&lt;br /&gt;
| --mqttpass&lt;br /&gt;
|Das zum Benutzernamen gehörende Passwort&lt;br /&gt;
|&lt;br /&gt;
| --mqttpass verysecret3&lt;br /&gt;
|ja bzw. abhängig vom Broker&lt;br /&gt;
|-&lt;br /&gt;
| --retain&lt;br /&gt;
|Versendet die Nachrichten present und lastseen als retained.&lt;br /&gt;
|0&lt;br /&gt;
| --retain&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --daemonize&lt;br /&gt;
|Wenn ble2mqtt im Hintergrund (als Daemon) ausgeführt werden soll&lt;br /&gt;
|0&lt;br /&gt;
| --daemonize&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --loglevel&lt;br /&gt;
|Wie und was genau protokolliert werden soll. Mögliche Loglevel sind LOG_CRIT, LOG_ERR, LOG_WARNING, LOG_NOTICE, LOG_INFO, LOG_DEBUG.&lt;br /&gt;
|LOG_INFO&lt;br /&gt;
| --loglevel LOG_ERR&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --logtarget&lt;br /&gt;
|Wohin gelogged werden soll. Mögliche Optionen sind &#039;&#039;syslog&#039;&#039; und &#039;&#039;stdout&#039;&#039;.&lt;br /&gt;
|syslog&lt;br /&gt;
| --logtarget stdout&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --absentinterval&lt;br /&gt;
|Anzahl an Sekunden, nach denen das Gerät als abwesend bezeichnet werden soll. Mindestwert ist 30.&lt;br /&gt;
|60&lt;br /&gt;
| --absentinterval 120&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --rssithreshold&lt;br /&gt;
|Ab welcher Abweichung des RSSI Wertes ein Update getriggert werden soll. Mindestwert ist 5.&lt;br /&gt;
|10&lt;br /&gt;
| --rssithreshold 8&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --watchdogthreshold&lt;br /&gt;
|Ab welchem Zeitraum in Sekunden nach Empfangen des letzten BT-Signals ble2mqtt neu gestartet werden soll. Mindestwert ist 30. Der Wert 0 bedeutet deaktiviert, also nie.&lt;br /&gt;
|0&lt;br /&gt;
| --watchdogthreshold 30&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --debug&lt;br /&gt;
|Kann nur gemeinsam mit --daemonize verwendet werden, um Logeinträge auf stdout auszugeben. Je höher die Nummer, desto mehr Output.&lt;br /&gt;
|0&lt;br /&gt;
| --daemonize --debug 4&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --mac&lt;br /&gt;
|Filtert mittels Regex nach MAC-Adressen der von ble2mqtt zu beachtenden BLE-Geräte. Alle anderen Geräte werden ignoriert.&lt;br /&gt;
|&lt;br /&gt;
| --mac &#039;(11:22:33:44:55:66|77:88:99:00:AA:BB)&#039;&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --batterymaxage&lt;br /&gt;
|Zeit in Stunden, nach denen ein Batterie-Wert als veraltet angesehen und aktualisiert wird. Der Wert 0 deaktiviert den Batterie-Check.&lt;br /&gt;
|48&lt;br /&gt;
| --batterymaxage 6&lt;br /&gt;
|ja&lt;br /&gt;
|-&lt;br /&gt;
| --forcebattery&lt;br /&gt;
|Nur in Kombination mit --mac. Erzwingt einen Batterie-Check, auch wenn das battery-service am Gerät nicht erkannt wird.&lt;br /&gt;
|0&lt;br /&gt;
| --forcebattery&lt;br /&gt;
|ja&lt;br /&gt;
|}&lt;br /&gt;
===Beispiele===&lt;br /&gt;
* Broker verlangt Username/Passwort; es sollen keine Batterie-Werte ausgelesen werden&lt;br /&gt;
 ble2mqtt --mqttserver mqtt.example.org:1883 --mqttuser ble2mqtt --mqttpass verysecret3 --batterymaxage 0&lt;br /&gt;
&lt;br /&gt;
* Broker verlangt keine Authentifizierung; es soll nach zwei G-Tags gesucht werden; definiertes MQTT-Topic; Batteriewerte benötigt&lt;br /&gt;
 ble2mqtt --mqttserver mqtt.example.org:1883 --mqtttopic ble2mqtt/Wohnzimmer --mac &#039;(11:22:33:44:55:66|77:88:99:00:AA:BB)&#039;&lt;br /&gt;
&lt;br /&gt;
* Broker verlangt keine Authentifizierung; Geräte sollen nach 45s ohne Kontakt als abwesend angezeigt werden; MQTT Nachrichten sollen gespeichert bleiben&lt;br /&gt;
 ble2mqtt --mqttserver mqtt.example.org:1883 --absentinterval 45 --retain&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
Zur Installation muss das ble2mqtt-Script auf den Server kopiert werden und es müssen diverse Linux- und Perl-Pakete installiert werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zuerst das Script nach /usr/local/bin kopieren, um beim Aufruf in der Bash nicht immer den ganzen Pfad voranstellen zu müssen.&lt;br /&gt;
 sudo cp -a ble2mqttd /usr/local/bin/&lt;br /&gt;
Danach das Script noch als ausführbar markieren&lt;br /&gt;
 sudo chmod +x /usr/local/bin/ble2mqttd&lt;br /&gt;
&lt;br /&gt;
===Benötigte Linux Pakete===&lt;br /&gt;
Die benötigten Pakete können ganz einfach mit &#039;&#039;apt&#039;&#039; installiert werden. Dabei werden auch mögliche Abhängigkeiten automatisch installiert.&lt;br /&gt;
&lt;br /&gt;
 sudo apt install -y libssl-dev libio-socket-ssl-perl libreadonly-perl libtest-expect-perl libnet-ssleay-perl libnet-server-perl&lt;br /&gt;
&lt;br /&gt;
===Benötigte Perl-Module===&lt;br /&gt;
Es wird das Modul &#039;&#039;Net::MQTT::Simple&#039;&#039; (&#039;&#039;libnet-mqtt-simple-perl&#039;&#039;) benötigt. Das ist - Stand 08.11.2023 - noch nicht in den Stable-Repositories von Debian verfügbar und muss daher mittels &#039;&#039;cpan&#039;&#039; installiert werden. Voraussetzung dafür ist das Modul &#039;&#039;CPAN::DistnameInfo&#039;&#039;, welches zuerst installiert werden muss.&lt;br /&gt;
&lt;br /&gt;
 sudo cpan CPAN::DistnameInfo&lt;br /&gt;
 sudo cpan Net::MQTT::Simple&lt;br /&gt;
&lt;br /&gt;
Sobald &#039;&#039;libnet-mqtt-simple-perl&#039;&#039; verfügbar ist, kann dieses statt der Perl-Module wie ein normales Linux-Paket installiert werden.&lt;br /&gt;
&lt;br /&gt;
===Erster Test===&lt;br /&gt;
Mit einem einfachen Aufruf von &#039;&#039;&#039;ble2mqtt&#039;&#039;&#039; kann getestet werden, ob alle benötigten Module und Pakete vorhanden sind.&lt;br /&gt;
&lt;br /&gt;
 sudo /usr/local/bin/ble2mqttd&lt;br /&gt;
&lt;br /&gt;
===Erstellen einens Systemd-Daemons===&lt;br /&gt;
Damit &#039;&#039;&#039;ble2mqtt&#039;&#039;&#039; bei jedem Systemstart automatisch gestartet wird, muss ein Systemd-Daemon erstellt werden. Das wird gemacht, in dem eine neue Textdatei mit folgendem Inhalt angelegt und der Daemon dann aktiviert wird.&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|Text=&#039;&#039;&#039;Wichtig:&#039;&#039;&#039; Das Kommando, mit welchen Parametern ble2mqtt gestartet wird, muss natürlich individuell angepasst werden!}}&lt;br /&gt;
&lt;br /&gt;
 sudo nano /etc/systemd/system/ble2mqttd.service&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[Unit]&lt;br /&gt;
Description=ble2mqttd&lt;br /&gt;
After=bluetooth.target&lt;br /&gt;
&lt;br /&gt;
[Service]&lt;br /&gt;
Type=simple&lt;br /&gt;
Restart=always&lt;br /&gt;
ExecStart=/usr/local/bin/ble2mqttd --mqttserver mqtt.example.com:1883 --mqtttopic ble2mqtt/wohnzimmer --mac &#039;(11:22:33:44:55:66|77:88:99:00:AA:BB)&#039; --absentinterval 30 --mqttuser &amp;lt;username&amp;gt; --mqttpass &amp;lt;password&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[Install]&lt;br /&gt;
WantedBy=multi-user.target&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 sudo systemctl daemon-reload&lt;br /&gt;
 sudo systemctl enable ble2mqttd.service&lt;br /&gt;
 sudo systemctl start ble2mqttd.service&lt;br /&gt;
&lt;br /&gt;
==Einbindung in FHEM==&lt;br /&gt;
Da ble2mqtt alle Informationen an einen [[MQTT]]-Broker sendet, können diese Informationen ganz einfach als [[MQTT2_DEVICE]] in FHEM eingebunden werden. Wie dabei vorgegangen werden kann, unterscheidet sich je nach Anwendungsbereich und den eigenen Vorlieben.&lt;br /&gt;
&lt;br /&gt;
Als Beispiel sie hier die Anwesenheitserkennung mittels BT-Tags angeführt.&lt;br /&gt;
&lt;br /&gt;
===Anwesenheitserkennung mittels BT-Tags===&lt;br /&gt;
[[File:ble2mqtt.png|thumb|Readings eines Devices, dass mit diesem Codes erstellt wurde]]&lt;br /&gt;
Der folgende Code geht davon aus, dass es mehrere ble2mqtt-Instanzen gibt und ein BT-Tag mit der MAC-Adresse AA:BB:CC:DD:EE:FF erkannt werden soll.&lt;br /&gt;
&lt;br /&gt;
Die verschiedenen ble2mqtt-Instanzen schicken ihre Nachrichten in unterschiedliche Topics.&lt;br /&gt;
Für jede Instanz ein eigenes Topic:&lt;br /&gt;
*ble2mqtt/wohnzimmer&lt;br /&gt;
*ble2mqtt/schlafzimmer&lt;br /&gt;
*ble2mqtt/kueche&lt;br /&gt;
Im Attribut &#039;&#039;devicetopic&#039;&#039; werden diese Topics dann gemeinsam ausgewertet. Das funktioniert, in dem der Name des Subtopics einfach durch den Regex-Ausdruck &#039;&#039;.*&#039;&#039; ersetzt wird.&lt;br /&gt;
&lt;br /&gt;
Bedeutet aber auch, dass die Informationen - wenn gewünscht - wieder in unterschiedliche Readings zerlegt werden müssen. Um z.B. schnell zu erkennen, in welchem Raum der BT-Tag gerade liegt. Das passiert hier z.B. bei den Nachrichten für &#039;&#039;rssi&#039;&#039; und &#039;&#039;presence&#039;&#039;. Daraus resultieren dann eigene Readings für jedes MQTT-Subtopic.&lt;br /&gt;
&lt;br /&gt;
Das &amp;quot;raumübergreifende&amp;quot; Reading &#039;&#039;presence&#039;&#039; wird anhand der des Alters in Sekunden der letzten lastseen-Nachricht gesteuert. Die lastseen-Nachricht wird immer gesendet, wenn der Scanvorgang von ble2mqtt das gewünschte Gerät findet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
define ble2mqttGTag MQTT2_DEVICE FHEM&lt;br /&gt;
attr ble2mqttGTag devicetopic ble2mqtt/.*/AA_BB_CC_DD_EE_FF&lt;br /&gt;
attr ble2mqttGTag event-on-change-reading .*&lt;br /&gt;
attr ble2mqttGTag readingList ble2mqtt/.*/heartbeat:.* heartbeat&lt;br /&gt;
$DEVICETOPIC/rssi:.* {my $room=(split m{[/]}x,$TOPIC)[1]; my $roomMax=$room; my $rssiMax=$EVENT; my @readings = grep { $_ =~ m{\Arssi_(?!$room).*}x } keys %{$defs{&amp;quot;$NAME&amp;quot;}-&amp;gt;{READINGS}}; for (@readings) {my $rssiTmp=ReadingsVal($NAME,$_,&#039;-100&#039;); my $roomTmp=(split m{[_]}x,$_)[1]; if(($rssiMax gt $rssiTmp)&amp;amp;&amp;amp;(ReadingsVal($NAME,&amp;quot;presence_&amp;quot;.$roomTmp,&#039;absent&#039;) eq &#039;present&#039;)) {$rssiMax=$rssiTmp; $roomMax=$roomTmp}}; {rssi=&amp;gt;$rssiMax,room=&amp;gt;$roomMax,&amp;quot;rssi_$room&amp;quot;=&amp;gt;$EVENT}}&lt;br /&gt;
$DEVICETOPIC/lastseen:.* {lastseen=&amp;gt;strftime &amp;quot;%Y-%m-%d %H:%M:%S&amp;quot;, localtime($EVENT)}&lt;br /&gt;
$DEVICETOPIC/present:.* {my $roomAct=(split m{[/]}x,$TOPIC)[1]; my $rssi=ReadingsVal($NAME,&amp;quot;rssi_&amp;quot;.$roomAct,&#039;-100&#039;); my $presenceAct=$EVENT?&#039;present&#039;:&#039;absent&#039;; my $room=$EVENT ? $roomAct:&#039;&#039;; my @readings = grep { $_ =~ m{\Apresence_(?!$roomAct).*}x } keys %{$defs{$NAME}-&amp;gt;{READINGS}}; for (@readings) {if(ReadingsVal($NAME,$_,&#039;absent&#039;) eq &#039;present&#039;) {my $roomTmp=(split m{[_]}x,$_)[1]; my $rssiTmp=ReadingsVal($NAME,&amp;quot;rssi_&amp;quot;.$roomTmp,&#039;-100&#039;); if($rssi gt $rssiTmp){$room=$roomTmp; $rssi=$rssiTmp}}}; {&amp;quot;presence_$roomAct&amp;quot;=&amp;gt;$presenceAct, room=&amp;gt;$room}}&lt;br /&gt;
ble2mqtt/.*/state:.* state&lt;br /&gt;
$DEVICETOPIC/battery:.* batteryLevel&lt;br /&gt;
attr ble2mqttGTag userReadings presence {if (ReadingsAge($NAME,&amp;quot;lastseen&amp;quot;,0)&amp;gt;60) {return &amp;quot;absent&amp;quot;;}else{return &amp;quot;present&amp;quot;;}}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Ergebnis ist unter anderem ein Reading &#039;&#039;presence&#039;&#039; mit den Zuständen &#039;&#039;absent&#039;&#039; und &#039;&#039;present&#039;&#039;. Es kann somit ganz einfach als &amp;quot;presenceDevice&amp;quot; in einem [[ROOMMATE]]-Device verwendet werden:&lt;br /&gt;
 attr rr_Franz rr_presenceDevices ble2mqttGTag&lt;br /&gt;
&lt;br /&gt;
[[Category:MQTT]][[Category:Anwesenheitserkennung]][[Category:FHEM Utilities]]&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Benutzer:Drhirn&amp;diff=38652</id>
		<title>Benutzer:Drhirn</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Benutzer:Drhirn&amp;diff=38652"/>
		<updated>2023-10-12T13:57:33Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: /* Einbindung in FHEM */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[https://certbot.eff.org Certbot] ist ein freies Open-Source-Tool der Electronic Frontier Foundation (EFF) mit dem automatisiert Let&#039;s Encrypt Zertifikate erstellt werden können.&lt;br /&gt;
&lt;br /&gt;
Diese Zertifikate können auch in FHEM verwendet werden, um den Netzwerkverkehr zu verschlüsseln.&lt;br /&gt;
&lt;br /&gt;
In dieser Anleitung wird beschrieben wie [[#Certbot installieren|Certbot]] installiert, [[#Zertifikate erstellen|Zertifikate damit erstellt]] und diese dann [[#Einbindung in FHEM|FHEM zur Verfügung gestellt]] werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Let&#039;s Encrypt Zertifikate sind in der Regel 90 Tage gültig. Beim Beantragen eines Zertifikates wird von Certbot automatisch ein systemd Timer erstellt, der kurz vor Ablauf des Zertifikat einen Prozess zur Erneuerung desselben startet. Dabei müssen die selben Voraussetzungen gegeben sein, die auch bei der Erst-Erstellung des Zertifikates nötig sind.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Certbot installieren==&lt;br /&gt;
;Voraussetzungen:&lt;br /&gt;
* Debian/Ubuntu/Raspberry Pi OS auf dem FHEM-Server&lt;br /&gt;
* SSH-Zugang zum FHEM-Server&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die empfohlene Installationsweise ist über die [https://snapcraft.io Snap Paketverwaltung]. Diese Anleitung geht von dieser Empfehlung aus. Wer Snap nicht verwenden möchte, findet [https://eff-certbot.readthedocs.io/en/latest/install.html hier] weitere Informationen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es werden zuerst die Paket-Quellen aktualisiert. Danach erfolgt die Installation der Snap Paketverwaltung und einer Laufzeitumgebung dafür:&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt install -y snapd&lt;br /&gt;
 sudo snap install core&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im nächsten Schritt kann dann der Cerbot installiert werden:&lt;br /&gt;
 sudo snap install --classic certbot&lt;br /&gt;
&lt;br /&gt;
Damit Certbot ohne Angabe seines Pfades ausgeführt werden kann, wird noch ein symbolischer Link erstellt:&lt;br /&gt;
 sudo ln -s /snap/bin/certbot /usr/bin/certbot&lt;br /&gt;
&lt;br /&gt;
==Zertifikate erstellen==&lt;br /&gt;
Certbot bietet mehrere Möglichkeiten, Let&#039;s Encrypt Zertifikate zu erstellen. Diese hängen von den jeweiligen technischen Voraussetzungen ab.&lt;br /&gt;
&lt;br /&gt;
Damit ein Zertifikat ausgestellt werden kann, muss der Server bzw. der Serveradministrator bestimmte Aufgaben erfüllen um zu beweisen, dass er auch Besitzer der Domain ist, für die ein Zertifikat erstellt werden soll. Beispiele für solche Aufgaben sind z.B. einen bestimmten Record im DNS-Eintrag der Domain zu erstellen oder eine definierte Datei auf einem Webserver abzulegen. Für jede dieser Aufgaben gibt es ein Certbot Plug-In. Genauere Details finden sich auf der Webseite von [https://letsencrypt.org/de/how-it-works/ Let&#039;s Encrpyt].&lt;br /&gt;
&lt;br /&gt;
Welche der Möglichkeiten bzw. welches Plug-In genutzt wird, entscheidet der Serveradministrator.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im Folgenden sind zwei verschiedene Plug-Ins erklärt. Weitere Informationen oder alternative Möglichkeiten bietet die [https://eff-certbot.readthedocs.io/en/latest/using.html#getting-certificates-and-choosing-plugins Certbot-Dokumentation].&lt;br /&gt;
&lt;br /&gt;
===Standalone-Plugin===&lt;br /&gt;
Die &amp;quot;standalone&amp;quot; Variante bietet sich an, wenn auf dem System kein Web-Server installiert ist oder mit diesem nicht interagiert werden soll/kann.&lt;br /&gt;
&lt;br /&gt;
Um die Let&#039;s Encrypt Aufgabe erfüllen zu können, wird automatisch ein in Certbot eingebauter Webserver gestartet. Dieser liefert eine Datei aus, die von Let&#039;s Encrypt dann überprüft wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Voraussetzungen:&lt;br /&gt;
* Einen DNS Eintrag vom Typ A (IPv4) oder AAAA (IPv6) für eure Domain mit eurer externen IP Adresse&lt;br /&gt;
* Port 80 ist auf der Firewall geöffnet und wird zum FHEM-Server weitergeleitet&lt;br /&gt;
* Port 80 wird auf dem FHEM-Server von keinem anderen Service (Web-Server z.B.) verwendet&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind alle Voraussetzungen erfüllt, kann ein Zertifikat mit folgendem Befehl beantragt werden:&lt;br /&gt;
 sudo certbot certonly --standalone -d www.example.com&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;&#039;&#039;--standalone&#039;&#039;&#039;&#039;&#039; bestimmt hier das zu verwendende Plug-In &amp;quot;standalone&amp;quot;&lt;br /&gt;
*&#039;&#039;&#039;&#039;&#039;-d&#039;&#039;&#039;&#039;&#039; die Domain, für die das Zertifikat ausgestellt werden soll. Es können - kommagetrennt - mehrere Domains angegeben werden. Oder der Parameter -d wird einfach öfter verwendet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weiteres Beispiel für das Beantragen eines Zertifikates mit mehreren Domains:&lt;br /&gt;
 sudo certbot certonly --standalone -d www.example.com -d example.com&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wer den ganzen Ablauf zuerst testen möchte, kann einen &amp;quot;dry-run&amp;quot; durchführen. Dabei wird die Ausstellung durch einen Test-Server von Let&#039;s Encrypt durchgeführt, es werden aber keine Zertifikate am FHEM-Server gespeichert: &lt;br /&gt;
 sudo certbot certonly --standalone --dry-run -d www.example.com&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit, einen ausführlicheren Testlauf durchzuführen ist, den Let&#039;s Encrypt Staging-Server (Test-Server) zu verwenden. Dabei werden Zertifikate im System abgelegt, die zwar ungültig sind, aber zu Testzwecken verwendet werden können:&lt;br /&gt;
 sudo certbot certonly --standalone --staging -d www.example.com&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--;Erneuern&lt;br /&gt;
sudo certbot certonly --standalone --force-renewal --staging -d test.jft.at--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===DNS Plugins===&lt;br /&gt;
Eine ganz einfache Möglichkeit zur Erstellen von Zertifikaten bieten die DNS Plug-Ins.&lt;br /&gt;
&lt;br /&gt;
Dabei muss kein lokaler Server aus dem Internet erreichbar sein, sondern es wird ein bestimmter DNS-Eintrag der Domain automatisch geändert und überprüft um zu beweisen, dass der Antragsteller Inhaber der Domain ist.&lt;br /&gt;
&lt;br /&gt;
;Voraussetzungen&lt;br /&gt;
*Verwendung eines [https://eff-certbot.readthedocs.io/en/latest/using.html#dns-plugins unterstützten DNS-Providers] zur Verwaltung der eigenen Domain&lt;br /&gt;
*API-Key mit dem Recht, DNS-Einträge zu ändern&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für alle DNS Plug-Ins gilt, dass sie unter dem root-User laufen. Um das zu erlauben, ist folgender Befehl nötig:&lt;br /&gt;
 sudo snap set certbot trust-plugin-with-root=ok&lt;br /&gt;
&lt;br /&gt;
Anschließend muss das korrekte Plug-In installiert werden.&lt;br /&gt;
&lt;br /&gt;
In dieser Anleitung wird die Verwendung des [https://certbot-dns-cloudflare.readthedocs.io/en/stable/ Cloudflare Plug-Ins] erklärt. Die Funktionsweise ist bei anderen ähnlich und auf der jeweiligen [https://eff-certbot.readthedocs.io/en/latest/using.html#dns-plugins Dokumentationsseite] des Plug-Ins ersichtlich.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zuerst wird das Plug-In installiert:&lt;br /&gt;
 sudo snap install certbot-dns-cloudflare&lt;br /&gt;
&lt;br /&gt;
Danach wird eine Datei erstellt, die den API-Key mit der Berechtigung zum Ändern von DNS-Einträgen bei Cloudflare beinhaltet:&lt;br /&gt;
 sudo mkdir /root/.secrets/&lt;br /&gt;
 sudo nano /root/.secrets/cloudflare.ini&lt;br /&gt;
&lt;br /&gt;
;/root/.secrets/cloudflare.ini&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
# Cloudflare API token used by Certbot&lt;br /&gt;
dns_cloudflare_api_token = 0123456789abcdef0123456789abcdef01234567&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Datei muss dann noch vor unbefugtem Zugriff geschützt werden:&lt;br /&gt;
 sudo chmod 0700 /root/.secrets/&lt;br /&gt;
 sudo chmod 0400 /root/.secrets/cloudflare.ini&lt;br /&gt;
&lt;br /&gt;
Sind diese Schritte erledigt, kann ein Zertifikat beantragt werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo certbot certonly \&lt;br /&gt;
  --dns-cloudflare \&lt;br /&gt;
  --dns-cloudflare-credentials /root/.secrets/cloudflare.ini \&lt;br /&gt;
  --dns-cloudflare-propagation-seconds 20 \&lt;br /&gt;
  -d www.example.com -d example.com&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Einbindung in FHEM==&lt;br /&gt;
Um die Zertifikate nun in FHEM nutzen zu können, müssen zuerst die Berechtigungen auf diese geändert und dann symbolische Links zu Pfaden erstellt werden, wie sie FHEM erwartet.&lt;br /&gt;
&lt;br /&gt;
Das Ändern der Berechtigungen ist wichtig, weil der User &#039;&#039;fhem&#039;&#039; sonst keinen Lesezugriff auf diese hätte. Das Erstellen der symbolischen Link, weil FHEM die Zertifikate im Ordner &#039;&#039;/opt/fhem/certs&#039;&#039; erwartet.&lt;br /&gt;
&lt;br /&gt;
Grundsätzlich legt Certbot alle Zertifikate unter &#039;&#039;/etc/letsencrypt/archive&#039;&#039; ab. Und zwar unterschiedliche Versionen der Zertifikate. Damit Anwendungen die jeweils aktuellen Zertifikate ohne Änderung verwenden können, werden aber gleichzeitig auch symbolische Links nach &#039;&#039;/etc/letsencrypt/live&#039;&#039; gesetzt.&lt;br /&gt;
&lt;br /&gt;
Kurz gesagt, für Anwendungen sind nur die jeweiligen Dateien unter &#039;&#039;/etc/letsencrypt/live&#039;&#039; relevant. Dabei vor allem:&lt;br /&gt;
* &#039;&#039;&#039;/etc/letsencrypt/live/www.example.com/privkey.pem&#039;&#039;&#039; (Der private Key)&lt;br /&gt;
* &#039;&#039;&#039;/etc/letsencrypt/live/www.example.com/fullchain.pem&#039;&#039;&#039; (Das erstellte Zertifikat mit der ganzen Signaturkette)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nichts desto trotz müssen aber auf beiden Verzeichnisse (&#039;&#039;archive&#039;&#039; und &#039;&#039;live&#039;&#039;) die Zugriffsrechte geändert werden, damit der User &#039;&#039;fhem&#039;&#039; in späterer Folge daraus lesen kann. Für die Sicherheit der Zertifikate hat das keinen Einfluss, die sind durch eigene Dateisystemrechte geschützt.&lt;br /&gt;
 sudo chmod 0755 /etc/letsencrypt/{live,archive}&lt;br /&gt;
&lt;br /&gt;
Damit FHEM den Private Key lesen kann, ändern wir den Gruppenbesitz der Datei auf die Gruppe &#039;&#039;dialout&#039;&#039;:&lt;br /&gt;
 sudo chgrp dialout /etc/letsencrypt/archive/server/privkey1.pem&lt;br /&gt;
&lt;br /&gt;
Und vergeben anschließend noch eine Leseberechtigung für diese Gruppe:&lt;br /&gt;
 sudo chmod 0640 /etc/letsencrypt/archive/server/privkey1.pem&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind alle Berechtigungen vergeben (die sich beim Erneuern der Zertifikate nicht ändern), müssen noch symbolische Links in das Verzeichnis &#039;&#039;/opt/fhem/certs&#039;&#039; erstellt werden, da FHEM die Zertifikats-Dateien genau dort erwartet. Alle folgenden Befehle werden unter dem Benutzerkontext des Users &#039;&#039;fhem&#039;&#039; ausgeführt, damit danach keine Berechtigungen mehr verändert werden müssen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zuerst wird das Verzeichnis selbst erstellt:&lt;br /&gt;
 sudo -u fhem mkdir /opt/fhem/certs&lt;br /&gt;
&lt;br /&gt;
Anschließend ein symbolischer Link für den PrivateKey eingerichtet:&lt;br /&gt;
 sudo -u fhem ln -s /etc/letsencrypt/live/test.jft.at/privkey.pem /opt/fhem/certs/server-key.pem&lt;br /&gt;
&lt;br /&gt;
Und danach einer für das Zertifikat:&lt;br /&gt;
 sudo -u fhem ln -s /etc/letsencrypt/live/test.jft.at/fullchain.pem /opt/fhem/certs/server-cert.pem&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Änderung in FHEM selbst beschränken sich auf eine einzige Änderung am FHEMWEB-Device (&#039;&#039;WEB&#039;&#039;):&lt;br /&gt;
 attr WEB HTTPS 1&lt;br /&gt;
&lt;br /&gt;
Danach die Konfiguration speichern und FHEM ist ab sofort unter https://www.example.com:8083/ zu erreichen.&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Benutzer:Drhirn&amp;diff=38651</id>
		<title>Benutzer:Drhirn</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Benutzer:Drhirn&amp;diff=38651"/>
		<updated>2023-10-12T13:51:53Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[https://certbot.eff.org Certbot] ist ein freies Open-Source-Tool der Electronic Frontier Foundation (EFF) mit dem automatisiert Let&#039;s Encrypt Zertifikate erstellt werden können.&lt;br /&gt;
&lt;br /&gt;
Diese Zertifikate können auch in FHEM verwendet werden, um den Netzwerkverkehr zu verschlüsseln.&lt;br /&gt;
&lt;br /&gt;
In dieser Anleitung wird beschrieben wie [[#Certbot installieren|Certbot]] installiert, [[#Zertifikate erstellen|Zertifikate damit erstellt]] und diese dann [[#Einbindung in FHEM|FHEM zur Verfügung gestellt]] werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Let&#039;s Encrypt Zertifikate sind in der Regel 90 Tage gültig. Beim Beantragen eines Zertifikates wird von Certbot automatisch ein systemd Timer erstellt, der kurz vor Ablauf des Zertifikat einen Prozess zur Erneuerung desselben startet. Dabei müssen die selben Voraussetzungen gegeben sein, die auch bei der Erst-Erstellung des Zertifikates nötig sind.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Certbot installieren==&lt;br /&gt;
;Voraussetzungen:&lt;br /&gt;
* Debian/Ubuntu/Raspberry Pi OS auf dem FHEM-Server&lt;br /&gt;
* SSH-Zugang zum FHEM-Server&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die empfohlene Installationsweise ist über die [https://snapcraft.io Snap Paketverwaltung]. Diese Anleitung geht von dieser Empfehlung aus. Wer Snap nicht verwenden möchte, findet [https://eff-certbot.readthedocs.io/en/latest/install.html hier] weitere Informationen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es werden zuerst die Paket-Quellen aktualisiert. Danach erfolgt die Installation der Snap Paketverwaltung und einer Laufzeitumgebung dafür:&lt;br /&gt;
 sudo apt update&lt;br /&gt;
 sudo apt install -y snapd&lt;br /&gt;
 sudo snap install core&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im nächsten Schritt kann dann der Cerbot installiert werden:&lt;br /&gt;
 sudo snap install --classic certbot&lt;br /&gt;
&lt;br /&gt;
Damit Certbot ohne Angabe seines Pfades ausgeführt werden kann, wird noch ein symbolischer Link erstellt:&lt;br /&gt;
 sudo ln -s /snap/bin/certbot /usr/bin/certbot&lt;br /&gt;
&lt;br /&gt;
==Zertifikate erstellen==&lt;br /&gt;
Certbot bietet mehrere Möglichkeiten, Let&#039;s Encrypt Zertifikate zu erstellen. Diese hängen von den jeweiligen technischen Voraussetzungen ab.&lt;br /&gt;
&lt;br /&gt;
Damit ein Zertifikat ausgestellt werden kann, muss der Server bzw. der Serveradministrator bestimmte Aufgaben erfüllen um zu beweisen, dass er auch Besitzer der Domain ist, für die ein Zertifikat erstellt werden soll. Beispiele für solche Aufgaben sind z.B. einen bestimmten Record im DNS-Eintrag der Domain zu erstellen oder eine definierte Datei auf einem Webserver abzulegen. Für jede dieser Aufgaben gibt es ein Certbot Plug-In. Genauere Details finden sich auf der Webseite von [https://letsencrypt.org/de/how-it-works/ Let&#039;s Encrpyt].&lt;br /&gt;
&lt;br /&gt;
Welche der Möglichkeiten bzw. welches Plug-In genutzt wird, entscheidet der Serveradministrator.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Im Folgenden sind zwei verschiedene Plug-Ins erklärt. Weitere Informationen oder alternative Möglichkeiten bietet die [https://eff-certbot.readthedocs.io/en/latest/using.html#getting-certificates-and-choosing-plugins Certbot-Dokumentation].&lt;br /&gt;
&lt;br /&gt;
===Standalone-Plugin===&lt;br /&gt;
Die &amp;quot;standalone&amp;quot; Variante bietet sich an, wenn auf dem System kein Web-Server installiert ist oder mit diesem nicht interagiert werden soll/kann.&lt;br /&gt;
&lt;br /&gt;
Um die Let&#039;s Encrypt Aufgabe erfüllen zu können, wird automatisch ein in Certbot eingebauter Webserver gestartet. Dieser liefert eine Datei aus, die von Let&#039;s Encrypt dann überprüft wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Voraussetzungen:&lt;br /&gt;
* Einen DNS Eintrag vom Typ A (IPv4) oder AAAA (IPv6) für eure Domain mit eurer externen IP Adresse&lt;br /&gt;
* Port 80 ist auf der Firewall geöffnet und wird zum FHEM-Server weitergeleitet&lt;br /&gt;
* Port 80 wird auf dem FHEM-Server von keinem anderen Service (Web-Server z.B.) verwendet&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind alle Voraussetzungen erfüllt, kann ein Zertifikat mit folgendem Befehl beantragt werden:&lt;br /&gt;
 sudo certbot certonly --standalone -d www.example.com&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;&#039;&#039;--standalone&#039;&#039;&#039;&#039;&#039; bestimmt hier das zu verwendende Plug-In &amp;quot;standalone&amp;quot;&lt;br /&gt;
*&#039;&#039;&#039;&#039;&#039;-d&#039;&#039;&#039;&#039;&#039; die Domain, für die das Zertifikat ausgestellt werden soll. Es können - kommagetrennt - mehrere Domains angegeben werden. Oder der Parameter -d wird einfach öfter verwendet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weiteres Beispiel für das Beantragen eines Zertifikates mit mehreren Domains:&lt;br /&gt;
 sudo certbot certonly --standalone -d www.example.com -d example.com&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wer den ganzen Ablauf zuerst testen möchte, kann einen &amp;quot;dry-run&amp;quot; durchführen. Dabei wird die Ausstellung durch einen Test-Server von Let&#039;s Encrypt durchgeführt, es werden aber keine Zertifikate am FHEM-Server gespeichert: &lt;br /&gt;
 sudo certbot certonly --standalone --dry-run -d www.example.com&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit, einen ausführlicheren Testlauf durchzuführen ist, den Let&#039;s Encrypt Staging-Server (Test-Server) zu verwenden. Dabei werden Zertifikate im System abgelegt, die zwar ungültig sind, aber zu Testzwecken verwendet werden können:&lt;br /&gt;
 sudo certbot certonly --standalone --staging -d www.example.com&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--;Erneuern&lt;br /&gt;
sudo certbot certonly --standalone --force-renewal --staging -d test.jft.at--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===DNS Plugins===&lt;br /&gt;
Eine ganz einfache Möglichkeit zur Erstellen von Zertifikaten bieten die DNS Plug-Ins.&lt;br /&gt;
&lt;br /&gt;
Dabei muss kein lokaler Server aus dem Internet erreichbar sein, sondern es wird ein bestimmter DNS-Eintrag der Domain automatisch geändert und überprüft um zu beweisen, dass der Antragsteller Inhaber der Domain ist.&lt;br /&gt;
&lt;br /&gt;
;Voraussetzungen&lt;br /&gt;
*Verwendung eines [https://eff-certbot.readthedocs.io/en/latest/using.html#dns-plugins unterstützten DNS-Providers] zur Verwaltung der eigenen Domain&lt;br /&gt;
*API-Key mit dem Recht, DNS-Einträge zu ändern&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für alle DNS Plug-Ins gilt, dass sie unter dem root-User laufen. Um das zu erlauben, ist folgender Befehl nötig:&lt;br /&gt;
 sudo snap set certbot trust-plugin-with-root=ok&lt;br /&gt;
&lt;br /&gt;
Anschließend muss das korrekte Plug-In installiert werden.&lt;br /&gt;
&lt;br /&gt;
In dieser Anleitung wird die Verwendung des [https://certbot-dns-cloudflare.readthedocs.io/en/stable/ Cloudflare Plug-Ins] erklärt. Die Funktionsweise ist bei anderen ähnlich und auf der jeweiligen [https://eff-certbot.readthedocs.io/en/latest/using.html#dns-plugins Dokumentationsseite] des Plug-Ins ersichtlich.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zuerst wird das Plug-In installiert:&lt;br /&gt;
 sudo snap install certbot-dns-cloudflare&lt;br /&gt;
&lt;br /&gt;
Danach wird eine Datei erstellt, die den API-Key mit der Berechtigung zum Ändern von DNS-Einträgen bei Cloudflare beinhaltet:&lt;br /&gt;
 sudo mkdir /root/.secrets/&lt;br /&gt;
 sudo nano /root/.secrets/cloudflare.ini&lt;br /&gt;
&lt;br /&gt;
;/root/.secrets/cloudflare.ini&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
# Cloudflare API token used by Certbot&lt;br /&gt;
dns_cloudflare_api_token = 0123456789abcdef0123456789abcdef01234567&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Datei muss dann noch vor unbefugtem Zugriff geschützt werden:&lt;br /&gt;
 sudo chmod 0700 /root/.secrets/&lt;br /&gt;
 sudo chmod 0400 /root/.secrets/cloudflare.ini&lt;br /&gt;
&lt;br /&gt;
Sind diese Schritte erledigt, kann ein Zertifikat beantragt werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sudo certbot certonly \&lt;br /&gt;
  --dns-cloudflare \&lt;br /&gt;
  --dns-cloudflare-credentials /root/.secrets/cloudflare.ini \&lt;br /&gt;
  --dns-cloudflare-propagation-seconds 20 \&lt;br /&gt;
  -d www.example.com -d example.com&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Einbindung in FHEM==&lt;br /&gt;
Um die Zertifikate nun in FHEM nutzen zu können, müssen zuerst die Berechtigungen auf diese geändert und dann symbolische Links zu Pfaden erstellt werden, wie sie FHEM erwartet.&lt;br /&gt;
&lt;br /&gt;
Das Ändern der Berechtigungen ist wichtig, weil der User &#039;&#039;fhem&#039;&#039; sonst keinen Lesezugriff auf diese hätte. Das Erstellen der symbolischen Link, weil FHEM die Zertifikate im Ordner &#039;&#039;/opt/fhem/certs&#039;&#039; erwartet.&lt;br /&gt;
&lt;br /&gt;
Grundsätzlich legt Certbot alle Zertifikate unter &#039;&#039;/etc/letsencrypt/archive&#039;&#039; ab. Und zwar unterschiedliche Versionen der Zertifikate. Damit Anwendungen die jeweils aktuellen Zertifikate ohne Änderung verwenden können, werden aber gleichzeitig auch symbolische Links nach &#039;&#039;/etc/letsencrypt/live&#039;&#039; gesetzt.&lt;br /&gt;
&lt;br /&gt;
Kurz gesagt, für Anwendungen sind nur die jeweiligen Dateien unter &#039;&#039;/etc/letsencrypt/live&#039;&#039; relevant. Dabei vor allem:&lt;br /&gt;
* &#039;&#039;&#039;/etc/letsencrypt/live/www.example.com/privkey.pem&#039;&#039;&#039; (Der private Key)&lt;br /&gt;
* &#039;&#039;&#039;/etc/letsencrypt/live/www.example.com/fullchain.pem&#039;&#039;&#039; (Das erstellte Zertifikat mit der ganzen Signaturkette)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nichts desto trotz müssen aber auf beiden Verzeichnisse (&#039;&#039;archive&#039;&#039; und &#039;&#039;live&#039;&#039;) die Zugriffsrechte geändert werden, damit der User &#039;&#039;fhem&#039;&#039; in späterer Folge daraus lesen kann. Für die Sicherheit der Zertifikate hat das keinen Einfluss, die sind durch eigene Dateisystemrechte geschützt.&lt;br /&gt;
 sudo chmod 0755 /etc/letsencrypt/{live,archive}&lt;br /&gt;
&lt;br /&gt;
Damit FHEM den Private Key lesen kann, ändern wir den Gruppenbesitz der Datei auf die Gruppe &#039;&#039;dialout&#039;&#039;:&lt;br /&gt;
 sudo chgrp dialout /etc/letsencrypt/archive/server/privkey1.pem&lt;br /&gt;
&lt;br /&gt;
Und vergeben anschließend noch eine Leseberechtigung für diese Gruppe:&lt;br /&gt;
 sudo chmod 0640 /etc/letsencrypt/archive/server/privkey1.pem&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sind alle Berechtigungen vergeben, müssen noch symbolische Links in das Verzeichnis &#039;&#039;/opt/fhem/certs&#039;&#039; erstellt werden, da FHEM die Zertifikats-Dateien genau dort erwartet. Alle folgenden Befehle werden unter dem Benutzerkontext des Users &#039;&#039;fhem&#039;&#039; ausgeführt, damit danach keine Berechtigungen mehr verändert werden müssen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zuerst wird das Verzeichnis selbst erstellt:&lt;br /&gt;
 sudo -u fhem mkdir /opt/fhem/certs&lt;br /&gt;
&lt;br /&gt;
Anschließend ein symbolischer Link für den PrivateKey eingerichtet:&lt;br /&gt;
 sudo -u fhem ln -s /etc/letsencrypt/live/test.jft.at/privkey.pem /opt/fhem/certs/server-key.pem&lt;br /&gt;
&lt;br /&gt;
Und danach einer für das Zertifikat:&lt;br /&gt;
 sudo -u fhem ln -s /etc/letsencrypt/live/test.jft.at/fullchain.pem /opt/fhem/certs/server-cert.pem&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Änderung in FHEM selbst beschränken sich auf eine einzige Änderung am FHEMWEB-Device (&#039;&#039;WEB&#039;&#039;):&lt;br /&gt;
 attr WEB HTTPS 1&lt;br /&gt;
&lt;br /&gt;
Danach die Konfiguration speichern und FHEM ist ab sofort unter https://www.example.com:8083/ zu erreichen.&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=Zigbee2mqtt&amp;diff=37571</id>
		<title>Zigbee2mqtt</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=Zigbee2mqtt&amp;diff=37571"/>
		<updated>2022-10-14T07:42:23Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: &amp;quot;report&amp;quot; ist deprecated, das noch da stehen zu lassen ist verwirrend. Wird auch nicht mehr benötigt.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
[[Bild:MQTT2_zigbee2mqtt_Bulbs.png|400px|thumb|Darstellung in FHEMWEB]]&lt;br /&gt;
[https://www.zigbee2mqtt.io/ zigbee2mqtt] ist ein open-source Projekt, mit dem zigbee-Geräte über MQTT direkt angesprochen werden können, ohne dass hierfür eine Bridge eines Herstellers benötigt wird.&lt;br /&gt;
&lt;br /&gt;
== Installation von zigbee2mqtt ==&lt;br /&gt;
Die Installation des zigbee2mqtt-Diensts ist auf der [https://www.zigbee2mqtt.io/ Homepage des Projekts] beschrieben. Ergänzend muss in der &#039;&#039;configuration.yaml&#039;&#039; eine &#039;&#039;client_id&#039;&#039; unter &#039;&#039;mqtt&#039;&#039; (z.B. zigbee_pi) vergeben werden&amp;lt;ref&amp;gt;Die Anführungszeichen sowie genau zwei Leerzeichen sind hier erforderlich!&amp;lt;/ref&amp;gt;.&lt;br /&gt;
 mqtt:&lt;br /&gt;
   client_id: &#039;zigbee_pi&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;tbd: weitere sinnvolle Einstellungen, availability, ...&#039;&#039;&lt;br /&gt;
&amp;lt;!-- + report&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Stand 03/2022 überholt: Einige Geräte werden erst dann per autocreate angelegt oder melden ihren Status nur, wenn [https://www.zigbee2mqtt.io/guide/configuration/mqtt.html#mqtt-behaviour report] aktiviert ist.&lt;br /&gt;
&lt;br /&gt;
 advanced:&lt;br /&gt;
   report: true&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Da der Dienst auch später in den Anlernmodus versetzt werden kann, kann man auch gleich &amp;lt;code&amp;gt;permit_join: false&amp;lt;/code&amp;gt; setzen, um das versehentliche Einbinden neuer oder fremder Geräte zu unterbinden.&lt;br /&gt;
&lt;br /&gt;
Zur Verbesserung der Bedienerfreundlichkeit empfiehlt es sich, das [https://www.zigbee2mqtt.io/information/frontend.html frontend] von zigbee2mqtt zu aktivieren:&lt;br /&gt;
&lt;br /&gt;
Hier kann man einige Einstellungen bequem vornehmen (beispielsweise den &amp;quot;friendly name&amp;quot;) und auch die gepairten Geräte direkt schalten.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
frontend:&lt;br /&gt;
  # Optional, default 8080&lt;br /&gt;
  port: 8080&lt;br /&gt;
  # Optional, default 0.0.0.0&lt;br /&gt;
  host: 0.0.0.0&lt;br /&gt;
  # Optional, enables authentication, disabled by default&lt;br /&gt;
  auth_token: your-secret-token&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|Wird ein CC2531 auf demselben Linux-Computer verwendet, auf dem auch FHEM installiert ist, kann es vorkommen, dass FHEM diesen mit einem [[CUL]] verwechselt und durch &#039;&#039;initialUsbCheck&#039;&#039; in FHEM einbindet, wodurch er für den zigbee2mqtt-Dienst nicht mehr verfügbar ist. Dann sollte &#039;&#039;initialUsbCheck&#039;&#039; deaktiviert und das automatisch angelegte CUL-Device wieder gelöscht werden. Weiter sollte der CC2531 auch in FHEM &#039;&#039;&#039;und&#039;&#039;&#039; zigbee2mqtt &#039;&#039;[[Mehrere USB-Geräte einbinden|by-id]]&#039;&#039; eingebunden werden, um Probleme beim gleichzeitigen Einsatz anderer Geräte, die &#039;&#039;/dev/ttyACMx&#039;&#039; belegen können, zu vermeiden (betrifft z.B. CUL/MapleCUL ).}}&lt;br /&gt;
{{Hinweis|Zwischenzeitlich stehen neben den CC2531 bzw. CC2530 einige weitere, wesentlich leistungsfähigere Coordinator-Chipsets zur Verfügung. Ein Blick auf die betreffenden Info-Seiten bei zigbee2mqtt sei daher ausdrücklich empfohlen!}}&lt;br /&gt;
&lt;br /&gt;
== Define eines MQTT2-Devices als &amp;quot;Bridge&amp;quot; ==&lt;br /&gt;
Dann kann eine Art &amp;quot;Grund-Device&amp;quot; angelegt werden, das für die Ansteuerung des eigentlichen Server-Dienstes genutzt wird, der bereits unmittelbar nach der erfolgreichen Konfiguration von zigbee2mqtt zur Verfügung steht. In der Regel sollte dieses automatisch erstellt werden, wenn der zigbee2mqtt-Dienst (oder der betreffende Rechner) neu gestartet wird (oder FHEM oder dort ein Sensor einen Messwert sendet). Beispiel&amp;lt;ref&amp;gt;Hier waren bereits zwei Zigbee-Geräte angelernt&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
 defmod MQTT2_zigbee_pi MQTT2_DEVICE zigbee_pi&lt;br /&gt;
 attr MQTT2_zigbee_pi IODev MQTT2_FHEM_Server&lt;br /&gt;
 attr MQTT2_zigbee_pi readingList zigbee_pi:zigbee2mqtt/bridge/state:.* state\&lt;br /&gt;
   zigbee_pi:zigbee2mqtt/0x90fd9ffffe65db16:.* { json2nameValue($EVENT, &#039;&#039;) }\&#039;&#039;&lt;br /&gt;
   zigbee_pi:zigbee2mqtt/0x90fd9ffffe0bcd51:.* { json2nameValue($EVENT, &#039;&#039;) }\&#039;&#039;&lt;br /&gt;
   zigbee_pi:zigbee2mqtt/bridge/log:.* { json2nameValue($EVENT, &#039;log_&#039;) }&lt;br /&gt;
 attr MQTT2_zigbee_pi room MQTT2_DEVICE&lt;br /&gt;
&lt;br /&gt;
Für die Funktion einer zigbee2mqtt-Bridge steht ein {{Link2CmdRef|Anker=set|Lang=en|Label=template}} bereit, das direkt die passenden Attribute vergibt, um dem zigbee2mqtt-Dienst passende Anweisungen geben zu können und weitere Geräte für die eigentlichen Aktoren und Sensoren anzulegen:&lt;br /&gt;
:&amp;lt;code&amp;gt;set MQTT2_zigbee_pi attrTemplate zigbee2mqtt_bridge&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ist dieses angelegt, kann zigbee2mqtt mit &lt;br /&gt;
:&amp;lt;code&amp;gt;set MQTT2_zigbee_pi permit_join true&amp;lt;/code&amp;gt; &lt;br /&gt;
in den Anlernmodus versetzt werden, anzulernende Geräte müssen anschließend jeweils nach Bedienungsanleitung in den Anlernmodus gebracht werden.&lt;br /&gt;
&lt;br /&gt;
== Vereinzeln der eigentlichen Geräte ==&lt;br /&gt;
Über das mit dem template vergebene bridgeRegexp-Attribut  &lt;br /&gt;
:&amp;lt;code&amp;gt;attr MQTT2_zigbee_pi bridgeRegexp zigbee2mqtt/([A-Za-z0-9]*)[/]?.*:.* &amp;quot;zigbee_$1&amp;quot; &amp;lt;/code&amp;gt;&lt;br /&gt;
werden anschließend neue MQTT2_DEVICE-Geräte automatisch angelegt, sobald ein bisher unbekanntes Zigbee-Gerät einen neuen Status (z.B. einen Messwert) meldet. Um zu erfragen, welche Geräte dem zigbee-Deinst bekannt sind, kann via &amp;lt;code&amp;gt;get MQTT2_zigbee_pi devicelist true&amp;lt;/code&amp;gt; eine Liste abgefragt werden, die weitere Informationen zu den bereits angelernten Geräten enthält.&lt;br /&gt;
Geräte, die nicht automatisch etwas senden, kann man mit Hilfe des MQTT2_SERVER-Geräts einmalig schalten, damit diese ihren Status bzw. das erfolgreiche Schalten zurückmelden, Beispiel&amp;lt;ref&amp;gt;Die mit 0x... beginnende Angabe entspricht dabei dem &#039;&#039;friendly_name&#039;&#039;.&amp;lt;/ref&amp;gt;:&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;set MQTT2_FHEM_Server publish zigbee2mqtt/0x90fd9ffffe0bcd51/set {&amp;quot;state&amp;quot;:&amp;quot;ON&amp;quot;,&amp;quot;brightness&amp;quot;:60}&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
(Alternativ kann man das Gerät auch über das Frontend von zigbee2mqtt schalten, um das Device in FHEM automatisch anzulegen.)&lt;br /&gt;
&lt;br /&gt;
Für Gerätetypen, für die bereits templates vorhanden sind, ist es am einfachsten, diese einmalig auf die Geräte anzuwenden. Das Vorgehen entspricht dabei dem oben für die Bridge beschriebenen. Dafür wird immer vorausgesetzt, dass ein neues Device mit autocreate (ggf. über die bridgeRegexp) angelegt wurde&amp;lt;ref&amp;gt;Dieses befindet sich dann im Raum MQTT2_DEVICE. Um diesen sichtbar zu machen, muss ggf. die Browser-Seite neu geladen werden.&amp;lt;/ref&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
Beispiele:&lt;br /&gt;
=== IKEA-Tradfri-Birne ===&lt;br /&gt;
{{Randnotiz|RNTyp=g|RNText=Wie wähle ich nun das richtige Template für mein Leuchtmittel aus?&lt;br /&gt;
-&amp;gt; Es wird nicht zwischen einer Birne/Bulb/Lampe und einem LED-Controller unterschieden sondern anhand der möglichen Lichtdarstellung des Gerätes:&lt;br /&gt;
&lt;br /&gt;
light_dimmer:&lt;br /&gt;
Das anzusteuernde Geräte besitzt ausschließlich eine feste Lichtfarbe welche gedimmt werden kann.&lt;br /&gt;
&lt;br /&gt;
light_cct:&lt;br /&gt;
Das anzusteuernde Gerät besitzt eine warmweiße sowie kaltweiße Lichtfarbe welche verändert sowie gedimmt werden kann.&lt;br /&gt;
&lt;br /&gt;
light_rgb_xxx:&lt;br /&gt;
Das anzusteuernde Gerät besitzt die Möglichlichkeit einer farbigen Lichtdarstellung (Rot, Grün, Blau) und kann gedimmt werden.&lt;br /&gt;
&lt;br /&gt;
light_rgbw_xxx:&lt;br /&gt;
Das anzusteuernde Gerät besitzt die Möglichlichkeit einer farbigen Lichtdarstellung (Rot, Grün, Blau) und besitzt eine warmweiße ODER kaltweiße Lichtfarbe welche eingestellt sowie gedimmt werden kann.&lt;br /&gt;
&lt;br /&gt;
light_rgbcct_xxx:&lt;br /&gt;
Das anzusteuernde Gerät besitzt die Möglichlichkeit einer farbigen Lichtdarstellung (Rot, Grün, Blau) und besitzt eine warmweiße UND kaltweiße Lichtfarbe welche verändert sowie gedimmt werden kann.&lt;br /&gt;
   &lt;br /&gt;
   xxx:&lt;br /&gt;
      hex:   Farbänderung mit hex&lt;br /&gt;
      rgb:   Farbänderung mit r g b&lt;br /&gt;
      xy:   Farbänderung mit x sowie y&lt;br /&gt;
      hue:   Farbänderung mit hue und saturation&lt;br /&gt;
&lt;br /&gt;
Warum diese Einteilung in &amp;quot;hex&amp;quot;, &amp;quot;rgb&amp;quot;, &amp;quot;xy&amp;quot; sowie &amp;quot;hue&amp;quot;?&lt;br /&gt;
-&amp;gt; Zigbee2MQTT unterstützt das Übermitteln aller dieser Werte, allerdings unterscheiden sich hier die Geräte. Manche &amp;quot;verstehen&amp;quot; nur z.B. Hex-Farbänderungen, andere halt nur eine Farbänderung mit rgb-Werten.&lt;br /&gt;
-&amp;gt; Aus diesem Grund muss an dieser Stelle probiert werden mit welchem der 4 Templates sich die Farbveränderung des Gerätes steuern lässt!&lt;br /&gt;
&lt;br /&gt;
HINWEIS: Templates für Farbänderungen mithilfe von XY- sowie HUE-Werten wurden bis heute nicht angelegt!&lt;br /&gt;
}}&lt;br /&gt;
Beispiel eines dimmbaren Tradfri-Leuchtmittels&lt;br /&gt;
 defmod IKEA_Bulb2 MQTT2_DEVICE&lt;br /&gt;
 attr IKEA_Bulb2 IODev MQTT2_FHEM_Server&lt;br /&gt;
 attr IKEA_Bulb2 icon light_control&lt;br /&gt;
 attr IKEA_Bulb2 devStateIcon {zigbee2mqtt_devStateIcon255($name)}&lt;br /&gt;
 attr IKEA_Bulb2 readingList zigbee_pi:zigbee2mqtt/0x90fd9ffffe0bcd51:.* { json2nameValue($EVENT) }&lt;br /&gt;
 attr IKEA_Bulb2 setList on:noArg zigbee2mqtt/0x90fd9ffffe0bcd51/set {&amp;quot;state&amp;quot;:&amp;quot;ON&amp;quot;}\&lt;br /&gt;
     off:noArg zigbee2mqtt/0x90fd9ffffe0bcd51/set {&amp;quot;state&amp;quot;:&amp;quot;OFF&amp;quot;}\&lt;br /&gt;
     brightness:colorpicker,BRI,0,15,255 zigbee2mqtt/0x90fd9ffffe0bcd51/set {&amp;quot;state&amp;quot;:&amp;quot;on&amp;quot;,&amp;quot;$EVTPART0&amp;quot;:&amp;quot;$EVTPART1&amp;quot;}&lt;br /&gt;
 attr IKEA_Bulb2 webCmd toggle:on:off:brightness&lt;br /&gt;
 attr IKEA_Bulb2 model L_02a_zigbee2mqtt_bulb&lt;br /&gt;
&lt;br /&gt;
Kann man auch die Farbtemperatur einstellen, wird die setList wie folgt erweitert oder das entsprechende template&amp;lt;ref&amp;gt;Durch die &#039;&#039;model&#039;&#039;-Angabe kann nachvollzogen werden, welches template angewendet wurde.&amp;lt;/ref&amp;gt; angewendet:&lt;br /&gt;
 ...&lt;br /&gt;
 color_temp:colorpicker,CT,250,1,454 zigbee2mqtt/0x90fd9ffffe0bcd51/set {&amp;quot;$EVTPART0&amp;quot;:&amp;quot;$EVTPART1&amp;quot;}&lt;br /&gt;
&lt;br /&gt;
Die templates sind dabei in der Regel so gestaltet, dass eventuell mehr Optionen in FHEMWEB erscheinen, als tatsächlich vorhanden oder erwünscht sind. &lt;br /&gt;
Da sich obige einfarbige dimmbare Lampe durch Klicken auf das devStateIcon schalten lässt, ist für die vollständige Ansteuerung bereits dieses webCmd hinreichend:&lt;br /&gt;
:&amp;lt;code&amp;gt;attr IKEA_Bulb2 webCmd brightness&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Temp/Hum. Sensor ===&lt;br /&gt;
tbd&lt;br /&gt;
&lt;br /&gt;
=== Motion Sensor ===&lt;br /&gt;
Als MQTT-Server wird hier &#039;&#039;mosquitto&#039;&#039; verwendet, als IO-Device wird daher ein {{Link2CmdRef|Anker=MQTT2_CLIENT|Lang=en|Label=MQTT2_CLIENT}}-Gerät definiert: &lt;br /&gt;
&lt;br /&gt;
 defmod mqtt2_client MQTT2_CLIENT 192.168.2.4:1883&lt;br /&gt;
 attr mqtt2_client autocreate 1&lt;br /&gt;
 attr mqtt2_client rawEvents zigbee2mqtt/GB_Bewegungsmelder:.*&lt;br /&gt;
 attr mqtt2_client room test&lt;br /&gt;
 attr mqtt2_client subscriptions #&lt;br /&gt;
&lt;br /&gt;
Das eigentliche Device sieht dann so aus:&lt;br /&gt;
 defmod GB_Bewegungsmelder_MQTT2 MQTT2_DEVICE zigbee_158d0001f9d030&lt;br /&gt;
 attr GB_Bewegungsmelder_MQTT2 IODev mqtt2_client&lt;br /&gt;
 attr GB_Bewegungsmelder_MQTT2 devStateIcon motion:motion_detector@red off:motion_detector@green no_motion:motion_detector@green&lt;br /&gt;
 attr GB_Bewegungsmelder_MQTT2 icon motion_detector@blue&lt;br /&gt;
 attr GB_Bewegungsmelder_MQTT2 readingList mqtt2client:zigbee2mqtt/GB_Bewegungsmelder:.* { json2nameValue($EVENT) }&lt;br /&gt;
 attr GB_Bewegungsmelder_MQTT2 room MQTT2_DEVICE&lt;br /&gt;
 attr GB_Bewegungsmelder_MQTT2 stateFormat {\&lt;br /&gt;
 if(ReadingsVal(&amp;quot;$name&amp;quot;,&amp;quot;occupancy&amp;quot;,0) eq &amp;quot;true&amp;quot;) {\&lt;br /&gt;
 	sprintf(&amp;quot;motion&amp;quot;);;\&lt;br /&gt;
 	} else {\&lt;br /&gt;
 	sprintf(&amp;quot;no_motion&amp;quot;);;	\&lt;br /&gt;
 	}\&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=== Anlegen von Zigbee2MQTT-Gruppen in FHEM ===&lt;br /&gt;
{{Hinweis|Die nachfolgende Darstellung ist vorläufig!}}&lt;br /&gt;
{{Hinweis|Bevor man eine Gruppe mithilfe von Zigbee2MQTT anlegen kann, sollte man sicherstellen, dass man über die aktuelleste Version von Zigbee2MQTT verfügt (min. vom 15. Februar 2019). Außerdem sollte auch der Koordinator (zumeist CC2531) die aktuellste Firmware besitzen (min. vom 15. Februar 2019). Falls ein flashen des Koordinators mit der neusten Firmware erfolgen soll, ist darauf zu achten, dass nach einem flashen alle Geräte neu angelernt werden müssen! (Hinweise zum flashen ohne erneutem anlernen sind hier zu finden: https://www.zigbee2mqtt.io/information/flashing_without_re-pairing.html)}}&lt;br /&gt;
&lt;br /&gt;
====Erstellen einer Zigbee2MQTT-Gruppe====&lt;br /&gt;
Bevor das Ganze in FHEM funktioniert, muss eine Gruppe in der &amp;quot;configuration.yaml&amp;quot; angelegt werden, dieser Vorgang ist auf folgender Seite beschrieben: https://www.zigbee2mqtt.io/information/groups.html&lt;br /&gt;
Wenn die Geräte anschließend über den FHEM MQTT2-Server der Gruppe hinzugefügen werden sollen, kann dies mit folgendem Befehl erfolgen:&lt;br /&gt;
 set &amp;lt;MQTT2-Server&amp;gt; publish zigbee2mqtt/bridge/group/&amp;lt;Zigbee2MQTT Friendly-Gruppenname&amp;gt;/add &amp;lt;Zigbee2MQTT Friendly-Gerätename&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
:&amp;lt;code&amp;gt;set MQTT2_FHEM_Server publish zigbee2mqtt/bridge/group/Wohnzimmer/add Stehlampe&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dieser Befehl kann so oft verwendet werden, wie man Geräte zu einer Gruppe hinzufügen möchte.&lt;br /&gt;
&lt;br /&gt;
Zum Entfernen eines Gerätes aus einer Gruppe kann folgender Befehl verwendet werden:&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;set &amp;lt;MQTT2-Server&amp;gt; publish zigbee2mqtt/bridge/group/&amp;lt;Zigbee2MQTT Friendly-Gruppenname&amp;gt;/remove &amp;lt;Zigbee2MQTT Friendly-Gerätename&amp;gt;&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
Beispiel:&lt;br /&gt;
:&amp;lt;code&amp;gt;set MQTT2_FHEM_Server publish zigbee2mqtt/bridge/group/Wohnzimmer/remove Kuechenlampe&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Anlegen der Gruppe in FHEM====&lt;br /&gt;
Da Gruppen in Zigbee2MQTT aktuell keine Rückmeldung über ihren Status geben, wird auch beim einmaligen Schalten kein Gerät automatisch in FHEM angelegt. Aus diesem Grund muss dies mit folgendem Befehl noch manuell erfolgen:&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;defmod &amp;lt;FHEM NAME&amp;gt; MQTT2_DEVICE&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
Beispiel&lt;br /&gt;
:&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;defmod lichtWohnzimmer MQTT2_DEVICE&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
Anschließend wird auch für dieses Gerät wieder ein passendes template ausgewählt, als wäre es ein normales Zigbee2MQTT-Gerät.&lt;br /&gt;
Im anschließenden Dialogfenster, welches sich nach dem Setzen des templates öffnet, müssen die folgenden Werte durch passende ersetzt werden:&lt;br /&gt;
 BASE_TOPIC -&amp;gt; zigbee2mqtt&lt;br /&gt;
 DEV_ID -&amp;gt; &amp;lt;Zigbee2MQTT Friendly-Gruppenname&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Danach sollte sich die Gruppe wie ein normales Zigbee2MQTT Gerät steuern lassen.&lt;br /&gt;
&lt;br /&gt;
== Hinweise ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:HOWTOS]]&lt;br /&gt;
[[Kategorie:MQTT]]&lt;br /&gt;
[[Kategorie:ZigBee]]&lt;br /&gt;
[[Kategorie:IP Components|IP Komponenten]]&lt;br /&gt;
[[Kategorie:Interfaces]]&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=RHASSPY&amp;diff=37537</id>
		<title>RHASSPY</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=RHASSPY&amp;diff=37537"/>
		<updated>2022-09-07T10:05:56Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: Link zu Rhasspy auf GitHub entfernt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
Diese Seite beschreibt die Konfiguration und Verwendung des Moduls 10_RHASSPY.pm. &lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=Anbindung von FHEM an den Rhasspy Sprachassistenten&lt;br /&gt;
|ModType=contrib&lt;br /&gt;
|ModCmdRef=RHASSPY&lt;br /&gt;
|ModForumArea=Frontends/Sprachsteuerung&lt;br /&gt;
|ModFTopic=119447&lt;br /&gt;
|ModTechName=10_RHASSPY.pm&lt;br /&gt;
|ModOwner=Beta-User ({{Link2FU|9229|Forum}}/[[Benutzer Diskussion:Beta-User|Wiki]]), drhirn ({{Link2FU|15727|Forum}}/[[Benutzer Diskussion:Drhirn|Wiki]])&lt;br /&gt;
}}&lt;br /&gt;
[[File:Rhasspy_fhem.png|thumb|right|Schematische Darstellung von Rhasspy und FHEM/RHASSPY]]&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
[https://github.com/rhasspy/rhasspy Rhasspy] ist eine Open Source Server-Lösung für Spracherkennung und Sprachsteuerung, welche auf einem RaspBerry Pi oder einem anderen Debian-basierten Serversystem lauffähig ist. Es handelt sich dabei um eine Sammlung von Programmen (=Skripten in der Python-Sprechweise), die unter einer einheitlichen und sehr  flexiblen Benutzungsoberfläche zusammengefasst sind. Die Besonderheit an Rhasspy ist, dass es nach der Installation komplett offline betrieben werden kann. Es werden also keine Daten an einen Server im Internet geschickt, und für den Betrieb nur für FHEM werden nur moderate Hardwareanforderungen gestellt - ein aktueller Raspberry Pi ab Modell 3B+ sollte in der Regel genügen.&lt;br /&gt;
&lt;br /&gt;
Die Anbindung weiterer Räume ist über sogenannte &amp;quot;Satelliten&amp;quot; möglich. Dies kann z.B. ein Pi Zero mit Mikro und Lautsprecher sein, ein ESP32 mit entsprechender Hardware oder ein Mobiltelefon mit Android und der entsprechenden App.&lt;br /&gt;
&lt;br /&gt;
Rhasspy besteht aus vielen unterschiedlichen Modulen (Hot-Word Erkennung, Text-to-Speech, Speech-to-Text, Intent Erkennung, etc.). Alle diese Module kommunizieren miteinander über das [[MQTT|MQTT]]-Protokoll.&lt;br /&gt;
&lt;br /&gt;
Das Modul [[RHASSPY]] prüft Teile des MQTT-Traffics, konvertiert diese JSON-Nachrichten in FHEM-Befehle und sendet Nachrichten zurück an Rhasspy um z.B. Antworten über Text-to-Speech auszugeben.&lt;br /&gt;
&lt;br /&gt;
RHASSPY verwendet das Modul 00_MQTT2_CLIENT.pm um Nachrichten zu empfangen und zu senden. Daher ist es notwendig, eine Instanz dieses Moduls als FHEM-Device zu erstellen, bevor RHASSPY verwendet werden kann.&lt;br /&gt;
&lt;br /&gt;
Hervorgegangen ist RHASSPY aus dem Snips-Modul, nachdem Snips an Sonos verkauft und anschließend eingestellt wurde. Danke also an Thyraz, der die grundlegenden Arbeiten erledigt hat!&lt;br /&gt;
&lt;br /&gt;
=== Konventionen ===&lt;br /&gt;
{{Hinweis| In diesem Artikel und der CommandRef werden folgende Schreibweisen verwendet:&lt;br /&gt;
* &#039;&#039;&#039;[[RHASSPY]]&#039;&#039;&#039; bezieht sich auf das FHEM-Modul&lt;br /&gt;
* &#039;&#039;&#039;rhasspy&#039;&#039;&#039; bezieht sich auf das das FHEM-Device&lt;br /&gt;
* &#039;&#039;&#039;Rhasspy&#039;&#039;&#039; bezeichnet die (zentrale) Serverinstallation}}&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|Dialoge werden in RHASSPY verwaltet wie [https://rhasspy.readthedocs.io/en/latest/reference/#dialogue-manager hier] beschrieben. Dialoge werden also nicht funktionieren, sobald für das Dialogue-Management etwas anderes als &#039;&#039;RHASSPY&#039;&#039; eingestellt ist}}&lt;br /&gt;
&lt;br /&gt;
=== Erste Schritte ===&lt;br /&gt;
Die Installation und Erstinbetriebnahme von Rhasspy wird in einer Schnellstart-Anleitung erklärt: [[RHASSPY/Schnellstart]] Diese Anleitung sollte auch befolgt werden, wenn man sich sehr gut mit FHEM auskennt. Wer dies erfolgreich absolviert hat, kann gleich zu Abschnitt [[#Set-Befehle_.28SET.29|Set-Befehle (SET)]] weiterspringen, und/oder die [[RHASSPY/Vertiefung|Vertiefung]] durcharbeiten.&lt;br /&gt;
&lt;br /&gt;
=== Details zur Verwaltung des RHASSPY Moduls ===&lt;br /&gt;
Das Modul ist derzeit nicht in der &amp;quot;offiziellen&amp;quot; FHEM Distribution enthalten und muss daher manuell installiert werden. Dafür gibt es zwei Möglichkeiten.&lt;br /&gt;
&lt;br /&gt;
*Im Subversion Repository, kurz SVN von FHEM ist die jeweils aktuelle &amp;quot;stable&amp;quot; Version des Moduls im &#039;&#039;contrib&#039;&#039;-Zweig zu finden. Diese kann mit folgendem Befehl, der im FHEM Befehls-Eingabefeld einzugeben ist, heruntergeladen werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;{ Svn_GetFile(&#039;contrib/RHASSPY/10_RHASSPY.pm&#039;, &#039;FHEM/10_RHASSPY.pm&#039;) }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Genauere Informationen zu dieser Vorgangsweise finden sich unter [[Update#Einzelne_Dateien_aus_dem_SVN_holen]]. Nach Installation des Moduls muss FHEM neu gestartet werden.&lt;br /&gt;
&lt;br /&gt;
Nach Installation des Moduls muss FHEM neu gestartet werden.&lt;br /&gt;
&lt;br /&gt;
== Einrichtung MQTT2_CLIENT ==&lt;br /&gt;
Rhasspy kommuniziert hauptsächlich über das [[MQTT]]-Protokoll. Und zwar sowohl Rhasspy-intern, wie auch mit FHEM. Da dies auch für die übertragene Sprache und Audio-Dateien gilt und es daher zu sehr viel MQTT-Verkehr kommt, sollte der Rhasspy-interne MQTT-Server verwendet werden. Daher ist die Einrichtung eines [[MQTT2_CLIENT]]-Devices notwendig, um die für FHEM relevanten Daten zu beziehen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zuerst muss ein MQTT2_CLIENT Device erstellt werden, welches sich mit dem MQTT-Server (Mosquitto) von Rhasspy verbindet:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;define &amp;lt;deviceName&amp;gt; MQTT2_CLIENT &amp;lt;ip-oder-hostname-des-mqtt-servers&amp;gt;:&amp;lt;port&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anschließend wird die &#039;&#039;clientOrder&#039;&#039; gesetzt, um die richtige Benachrichtigungsreihenfolge einzustellen. Wird das MQTT2_CLIENT Device nur für RHASSPY verwendet, reicht hier die Angabe &amp;lt;code&amp;gt;RHASSPY&amp;lt;/code&amp;gt;. Ansonsten müssen noch alle anderen Devices (z.B. &amp;lt;code&amp;gt;MQTT_GENERIC_BRIDGE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;MQTT2_DEVICE&amp;lt;/code&amp;gt;) angegeben werden.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;attr &amp;lt;deviceName&amp;gt; clientOrder RHASSPY [device2] [device3]&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Um die Topics einzuschränken, die das Device abonniert, müssen diese angegeben werden. Wird der MQTT-Server nur für RHASSPY verwendet, reicht die Angabe &amp;lt;code&amp;gt;setByTheProgram&amp;lt;/code&amp;gt;. Ansonsten müssen alle für RHASSPY notwendigen Topics eingefügt werden.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;attr &amp;lt;deviceName&amp;gt; subscriptions setByTheProgram&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
bzw.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;attr &amp;lt;deviceName&amp;gt; subscriptions hermes/intent/+ hermes/dialogueManager/sessionStarted hermes/dialogueManager/sessionEnded hermes/nlu/intentNotRecognized hermes/hotword/+/detected hermes/hotword/toggleOn     hermes/hotword/toggleOff hermes/tts/say&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Beispiele&lt;br /&gt;
* Rhasspy-interner MQTT-Server wird mit seinem Standard-Port verwendet. Rhasspy läuft auf der selben Maschine wie FHEM. MQTT2_CLIENT wird nur für RHASSPY verwendet.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod rhasspyMQTT2 MQTT2_CLIENT localhost:12183&lt;br /&gt;
attr rhasspyMQTT2 clientOrder RHASSPY&lt;br /&gt;
attr rhasspyMQTT2 subscriptions setByTheProgram&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* Rhasspy läuft auf einem eigenen Server und verwendet einen externen MQTT Server mit eigener Port-Einstellung. MQTT2_CLIENT wird für RHASSPY, aber auch MQTT_GENERIC_BRIDGE und MQTT2_DEVICE verwendet.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod rhasspyMQTT2 MQTT2_CLIENT 192.168.1.122:1884&lt;br /&gt;
attr rhasspyMQTT2 clientOrder RHASSPY MQTT_GENERIC_BRIDGE MQTT2_DEVICE&lt;br /&gt;
attr rhasspyMQTT2 subscriptions hermes/intent/+ hermes/dialogueManager/sessionStarted hermes/dialogueManager/sessionEnded hermes/nlu/intentNotRecognized hermes/hotword/+/detected hermes/hotword/toggleOn hermes/hotword/toggleOff hermes/tts/say [zusätzliche Subscriptions für andere MQTT-Module]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Definition von RHASSPY (DEF)==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;define &amp;lt;name&amp;gt; RHASSPY &amp;lt;baseUrl&amp;gt; &amp;lt;devspec&amp;gt; &amp;lt;defaultRoom&amp;gt; &amp;lt;siteId&amp;gt; &amp;lt;language&amp;gt; &amp;lt;fhemId&amp;gt; &amp;lt;prefix&amp;gt; &amp;lt;useGenericAttrs&amp;gt; &amp;lt;handleHotword&amp;gt; &amp;lt;autoTraining&amp;gt; &amp;lt;encoding&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
{{Randnotiz|RNTyp=Info|RNText=RHASSPY verwendet sehr oft &amp;lt;parseParams&amp;gt;. Nicht nur im Define, sondern z.B. auch, um Attribut-Werte auszuwerten. Es sollten also alle Parameter im Define in der Form key=value angegeben werden.).}}{{Randnotiz|RNTyp=Info|RNText=RHASSPY führt jede Menge Daten aus unterschiedlichen Quellen zusammen um seine Funktion erfüllen zu können. Die endgültige Daten-Struktur, die RHASSPY verwendet, kann mittels des [[List|list]]-Kommandos angezeigt werden. Es wird empfohlen, sich diese Daten-Struktur auf jeden Fall anzusehen. Vor allem dann, wenn etwas nicht wie gewünscht funktioniert.}}&lt;br /&gt;
Alle Parameter sind &#039;&#039;&#039;optional&#039;&#039;&#039;. Die meisten werden im Normalfall gar nicht benötigt (z.B. &amp;lt;code&amp;gt;fhemId&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;prefix&amp;lt;/code&amp;gt;), oder können auf den automatisch vergebenen Werten belassen werden. Sollten sie aber verwendet und später geändert werden, kann es zu unvorhergesehenem Verhalten kommen. Speziell beim Einstieg in das Thema RHASSPY sollten nicht mehr, als die ersten drei verwendet werden. Ausgenommen eventuell noch &amp;lt;code&amp;gt;language&amp;lt;/code&amp;gt;, möchte man eine andere Sprache als Englisch oder Deutsch verwenden und &amp;lt;code&amp;gt;siteId&amp;lt;/code&amp;gt;, das für Tests und andere Text-Eingabemöglichkeiten wichtig ist.&lt;br /&gt;
&lt;br /&gt;
=== baseUrl ===&lt;br /&gt;
Die URL zum Rhasspy-Webservice. Sollten eine Base und mehrere Satelliten verwendet werden, die URL zur Base. Bitte sicherstellen, dass die Adresse richtig ist (IP und Port)! Default ist &amp;lt;code&amp;gt;baseUrl=http://127.0.0.1:12101&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== devspec ===&lt;br /&gt;
&#039;&#039;devspec&#039;&#039; der Geräte, die mit Rhasspy gesteuert werden sollen. Wenn der &#039;&#039;genericDeviceType&#039;&#039;-Support aktiviert ist, ist der Default &amp;lt;code&amp;gt;devspec=genericDeviceType=.+&amp;lt;/code&amp;gt;, sonst wird &amp;lt;code&amp;gt;devspec=room=Rhasspy&amp;lt;/code&amp;gt; verwendet. Ohne ein passendes Match in der devspec wird kein Gerät mit dem Modul interagieren, egal, ob sonst irgendwelche RHASSPY-spezifischen Attribute beim Gerät gesetzt sind. Genauere Informationen, wie z.B. eine Liste von Geräten oder Kombinationen aus Geräten und Räumen (z.B. &amp;lt;code&amp;gt;devspec=room=livingroom,room=bathroom,bedroomlamp&amp;lt;/code&amp;gt;) verwendet werden können, finden sich in der [https://commandref.fhem.de/commandref.html#devspec CommandRef].&lt;br /&gt;
&lt;br /&gt;
=== defaultRoom ===&lt;br /&gt;
Der Name des Standard-Raumes, der verwendet wird, wenn im Sprachkommando kein Raum enthalten ist und auch kein passender für das Device gefunden werden kann. Default ist &amp;lt;code&amp;gt;defaultRoom=default&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== language ===&lt;br /&gt;
Sprache, in der mit Rhasspy gesprochen wird. Der Standard-Wert hängt vom &#039;&#039;global&#039;&#039;-Device ab. Dieser ist standardmäßig &amp;lt;code&amp;gt;language=en&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== fhemId ===&lt;br /&gt;
Wird verwendet um auf MQTT-Seite zwischen mehreren Installationen des RHASSPY-Moduls zu unterscheiden. Ist auch ein Teil des Topic-Trees, auf den die jeweilige RHASSPY-Instanz hört. Default ist &amp;lt;code&amp;gt;fhemId=fhem&amp;lt;/code&amp;gt;.&lt;br /&gt;
{{Hinweis|Dialoge werden in RHASSPY verwaltet wie [https://rhasspy.readthedocs.io/en/latest/reference/#dialogue-manager hier] beschrieben. Dialoge werden also nicht funktionieren, sobald für das Dialogue-Management etwas anderes als &#039;&#039;RHASSPY&#039;&#039; eingestellt ist}}&lt;br /&gt;
&lt;br /&gt;
=== siteId ===&lt;br /&gt;
Wenn bestimmte Funktionen genutzt werden sollen, muss die RHASSPY-Instanz für Rhasspy als &#039;&#039;Satellit&#039;&#039; eigenständig angesprochen werden können. Hierzu muss dann eine eindeutige Kennung vergeben werden, und diese ist insbesondere dann auch in der für die Intent Recognition zuständigen Rhasspy-Komponente als Satellit anzugeben. Wird diese nicht explizit gesetzt, wird diese aus dem &#039;&#039;language&#039;&#039;-Kürzel und der &#039;&#039;fhemId&#039;&#039; zusammengesetzt.&lt;br /&gt;
{{Hinweis|Für die Funktionalitäten &#039;&#039;test_sentence&#039;&#039;, &#039;&#039;test_file&#039;&#039;, &#039;&#039;msgDialog&#039;&#039; und &#039;&#039;AMAD.*&#039;&#039; ist es &#039;&#039;&#039;zwingend erforderlich&#039;&#039;&#039;, die siteId in der Rhasspy-Intent-Recognition-Komponente einzutragen!}}&lt;br /&gt;
&lt;br /&gt;
=== prefix ===&lt;br /&gt;
Wird verwendet um auf FHEM-Seite zwischen mehreren Installationen des RHASSPY-Moduls zu unterscheiden. Praktisch, wenn man mehrere Instanzen von RHASSPY auf einer FHEM Installation laufen hat und z.B. verschiedene Bezeichner für Gruppen und Räume haben möchte (z.B. unterschiedliche Sprachen). Default ist &amp;lt;code&amp;gt;prefix=rhasspy&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== useGenericAttrs ===&lt;br /&gt;
Üblicherweise verwendet RHASSPY - wie auch einige andere FHEM Module für Sprachassistenten - das Attribut &#039;&#039;genericDeviceType&#039;&#039; um Schaltmöglichkeiten von Geräten automatisch zu erkennen. Dieser Parameter fügt das Attribut &#039;&#039;genericDeviceType&#039;&#039; zur globalen Attributliste hinzu. Der Wert 0 verhindert dieses hinzufügen und die automatisierte Eigenschaftenerkennung. Default ist &amp;lt;code&amp;gt;useGenericAttrs=1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== encoding ===&lt;br /&gt;
Sollte es Probleme mit Umlauten geben, kann das Character-Encoding geändert werden. Default ist &amp;lt;code&amp;gt;encoding=utf8&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== handleHotword ===&lt;br /&gt;
Triggert das Reading &#039;&#039;hotword&#039;&#039;, wenn ein Hotword erkannt wurde (und erstellt das Reading, falls noch nicht vorhanden). Weitere Informationen dazu stehen beim Attribut [[#rhasspyHotwords|&#039;&#039;rhasspyHotwords&#039;&#039;]]. Default ist &amp;lt;code&amp;gt;handleHotword=0&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== autoTraining ===&lt;br /&gt;
Da Änderungen auf der FHEM-Seite (z.B. bei Änderungen der rhasspyNames) auch Rhasspy bekannt gemacht werden müssen und anschließend ein Training erfolgen muss, damit Rhasspy diese Änderugnen ebenfalls berücksichtigt, übergibt RHASSPY derartige Änderungen nach Ablauf von einer Minute seit der letzten Änderung an Rhasspy und initiiert dann ein Training. Setzt man diesen Schlüssel auf &amp;quot;0&amp;quot;, wird diese Funktion deaktiviert, alle anderen numerischen Werte werden als Änderung dieses Timeouts (in Sekunden) interpretiert&lt;br /&gt;
Default ist &amp;lt;code&amp;gt;autoTraining=60&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|Nach dem Definieren eines RHASSPY-Modules sollte das IODev manuell gesetzt werden um ein automatische IO-Zuweisung zu verhindern. Z.B. &amp;lt;code&amp;gt;attr &amp;lt;deviceName&amp;gt; IODev &amp;lt;m2client&amp;gt;&amp;lt;/code&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
;Beispiele:&lt;br /&gt;
Läuft Rhasspy auf der selben Maschine wie FHEM, die Sprache ist im &#039;&#039;global&#039;&#039;-Device bereits richtig eingestellt und der Standardraum entspricht der siteId, die in Rhasspy vergeben wurde:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;define Rhasspy RHASSPY&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Läuft Rhasspy auf einem anderen System wie FHEM, der Standard-Raum enspricht nicht dem, was Rhasspy liefert, die Sprache soll auch anders sein und es sollen sowohl Geräte mit vorhandenem &#039;&#039;genericDeviceType&#039;&#039; Attribut, als auch die Geräte &#039;&#039;device_a1&#039;&#039; und &#039;&#039;device_xy&#039;&#039; gesteuert werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;define Rhasspy RHASSPY baseUrl=http://192.168.1.210:12101 defaultRoom=&amp;quot;Büro Lisa&amp;quot; language=de devspec=genericDeviceType=.+,device_a1,device_xy handleHotword=1&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Set-Befehle (SET) ==&lt;br /&gt;
&lt;br /&gt;
=== customSlot ===&lt;br /&gt;
Erstellt einen neuen - oder überschreibt einen alten - Slot in Rhasspy&lt;br /&gt;
* &amp;lt;code&amp;gt;slotname&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;slotdata&amp;lt;/code&amp;gt; sind verpflichtend&lt;br /&gt;
* &amp;lt;code&amp;gt;overwrite&amp;lt;/code&amp;gt; ist optional. Default ist &amp;lt;code&amp;gt;overwrite=true&amp;lt;/code&amp;gt;. Das Setzen eines anderes Wertes verhindert das Überschreiben einen bereits bestehenden Slot mit gleichem Namen.&lt;br /&gt;
* &amp;lt;code&amp;gt;training&amp;lt;/code&amp;gt; ist optional. Default ist &amp;lt;code&amp;gt;training=true&amp;lt;/code&amp;gt;. Das Setzen eines anderen Wertes verhindert ein Training von Rhasspy nach dem Speichern des Slots.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiele:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; customSlot mySlot a,b,c overwrite training&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; customSlot slotname=mySlot slotdata=a,b,c overwrite=false&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== fetchSiteIds ===&lt;br /&gt;
Liest alle in Rhasspy vorhandenen siteIDs aus und speichert sie im Reading &#039;&#039;siteIds&#039;&#039;. Wird z.B. verwendet, um festzustellen, auf welchem Satelliten der User über das Ende eines Timers benachrichtigt werden soll.&lt;br /&gt;
Muss immer ausgeführt werden, wenn eine neue siteId in Rhasspy hinzugefügt wird (neuer Satellit z.B.).&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; fetchSiteIds&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== play ===&lt;br /&gt;
Sendet eine WAV Datei an Rhasspy, &amp;lt;code&amp;gt;siteId&amp;lt;/code&amp;gt; und &amp;lt;path&amp;gt; sind verpflichtend!&lt;br /&gt;
&lt;br /&gt;
Optional kann die Anzahl der Wiederholungen (Default: 1) und die Dauer der Pause zwischen den jeweiligen Wiederholungen (Default: 15) angeben werden.&lt;br /&gt;
&#039;&#039;Beispiele:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; play siteId=&amp;quot;default&amp;quot; path=&amp;quot;/opt/fhem/test.wav&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; play siteId=&amp;quot;default&amp;quot; path=&amp;quot;./test.wav&amp;quot; repeats=3 wait=20&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== speak ===&lt;br /&gt;
Sendet einen Text an das TTS-Sytem, welches ihn dann als Sprache ausgibt.&lt;br /&gt;
&lt;br /&gt;
Beide Argumente &amp;lt;code&amp;gt;siteId&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;text&amp;lt;/code&amp;gt; sind verpflichtend!&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; speak siteId=&amp;quot;wohnzimmer&amp;quot; text=&amp;quot;This is a test&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== textCommand ===&lt;br /&gt;
Sendet ein Text-Kommando an Rhasspy.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; textCommand schalte das licht ein&amp;lt;/code&amp;gt;&lt;br /&gt;
Mangels siteId erfolgt hier keine Rückmeldung zum ausgeführten Kommando.&lt;br /&gt;
&lt;br /&gt;
=== trainRhasspy ===&lt;br /&gt;
Startet das Training von Rhasspy.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; trainRhasspy&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== update ===&lt;br /&gt;
&#039;&#039;update&#039;&#039; kennt diverse Abstufungen:&lt;br /&gt;
&lt;br /&gt;
==== update devicemap ====&lt;br /&gt;
Wenn an der Konfiguration von RHASSPY oder an den von ihm gesteuerten Geräten etwas geändert wurde, muss dieser Befehl ausgeführt werden, um die Datenstruktur von RHASSPY zu aktualisieren, Rhasspy von den Änderungen zu informieren (Slots z.B.) und ein Training zu starten. Wenn [[#autoTraining|autoTraining]] nicht deaktiviert wurde, erfolgt dies bei Änderungen an relevanten Attributen nach einiger Zeit zwar automatisch, über diesen Befehl kann aber sichergestellt werden, dass dies unmittelbar und ohne Vergleich mit Alt-Daten erfolgt.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update devicemap&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== update devicemap_only ====&lt;br /&gt;
Aktualisiert die Datenstruktur von RHASSPY. Es werden weder Slots in Rhasspy geändert, noch das Training gestartet.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update devicemap_only&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== update slots ====&lt;br /&gt;
Aktualisiert (bzw. erstellt) alle Slots in Rhasspy mit den aktuellen Geräten, Räumen, usw.&lt;br /&gt;
&lt;br /&gt;
Erstellte/Aktualisierte Slots sind z.B.:&lt;br /&gt;
* de.fhem.AllKeywords  (Hinweis: Die ersten beiden Teile &#039;&#039;de&#039;&#039; und &#039;&#039;fhem&#039;&#039; hängen von der DEF des RHASSPY-Devices ab)&lt;br /&gt;
* de.fhem.Device&lt;br /&gt;
* de.fhem.Device-&#039;&#039;genericDeviceType&#039;&#039;&lt;br /&gt;
* de.fhem.Device-&#039;&#039;Intent&#039;&#039;&lt;br /&gt;
* de.fhem.Group&lt;br /&gt;
* de.fhem.Room&lt;br /&gt;
* de.fhem.MediaChannels&lt;br /&gt;
* de.fhem.Color&lt;br /&gt;
* de.fhem.NumericType&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update slots&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== slots_no_training ====&lt;br /&gt;
Wie &amp;lt;code&amp;gt;slots&amp;lt;/code&amp;gt;, aber ohne Training nach dem Update.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update slots_no_training&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== update language ====&lt;br /&gt;
Liest das das Sprach-File (&#039;&#039;languageFile&#039;&#039;) neu ein.&lt;br /&gt;
&lt;br /&gt;
Muss immer ausgeführt werden, wenn in diesem File oder dem Attribut &#039;&#039;languageFile&#039;&#039; etwas geändert wurde!&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update language&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== update intent_filter ====&lt;br /&gt;
Setzt die Intent Filter, die vom Rhasspy Dialogue Manger verwendet werden zurück. Details dazu bei [[#intentFilter|intentFilter]] im &#039;&#039;rhasspyTweaks&#039;&#039;-Attribut.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update intent_filter&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== update all ====&lt;br /&gt;
Aktualisiert die Devicemap und das languageFile&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update all&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== volume ===&lt;br /&gt;
Stellt die Lautstärke der gewünschten siteId auf einen Wert zwischen 0 and 1 (float). Beide Argumente &amp;lt;code&amp;gt;siteId&amp;lt;/code&amp;gt; &amp;lt;code&amp;gt;volume&amp;lt;/code&amp;gt; sind verpflichtend.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; siteId=&amp;quot;default&amp;quot; volume=&amp;quot;0.5&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|Bitte nicht vergessen, dass nach jeder Änderung an RHASSPY oder an einem von RHASSPY gesteuerten Gerät ein &amp;lt;code&amp;gt;update devicemap&amp;lt;/code&amp;gt; ausgeführt werden sollte, v.a. wenn das [[#autoTraining|autoTraining]] in der DEF deaktiviert wurde!}}&lt;br /&gt;
&lt;br /&gt;
== Get-Befehle (GET) ==&lt;br /&gt;
=== export_mapping ===&lt;br /&gt;
Liefert für das angegebene Device ein &amp;quot;klassisches&amp;quot; &#039;&#039;rhasspyMapping&#039;&#039;, das dann als Basis für eigene Weiterentwicklungen genutzt werden kann. Funktioniert ggf. nicht in allen Fällen (z.B. bei &#039;&#039;SetScene&#039;&#039; und dem Szenen-Format für &#039;&#039;HUEBridge&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
=== test_file ===&lt;br /&gt;
Anzugeben ist der Dateiname (einschl. Pfad)&lt;br /&gt;
&lt;br /&gt;
Die Datei wird zeilenweise eingelesen und an die Rhasspy-Komponente für die Intent-Erkennung übergeben. Das Ergebnis der Analyse wird in eine File geschrieben, die auf &#039;_result.txt&#039; endet. &#039;&#039;stop&#039;&#039; als Dateiname unterbricht einen laufenden Test. Die ggf. abgeleiteten Kommandos werden nicht ausgeführt, FHEM wird während eines laufende Tests auch keine anderen Kommandos von der Rhasspy-Seite her annehmen.&lt;br /&gt;
Für diese Funktion ist es zwingend erforderlich, dass die &#039;&#039;siteId&#039;&#039; der RHASSPY-Instanz bei der Intent-Recognition-Komponente in Rhasspy als Satellit angegeben wurde.&lt;br /&gt;
&lt;br /&gt;
=== test_sentence ===&lt;br /&gt;
Es kann ein beliebiger einzelner Satz eingegeben werden, die Ausgabe erfolgt dann in einem eigenen Dialogfeld, ansonsten gilt sinngemäß dasselbe wie bei &#039;&#039;test_file&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==Attribute (ATTR)==&lt;br /&gt;
Um RHASSPY zum Laufen zu bringen, müssen unterschiedliche Attribute gesetzt werden. Dabei gibt es&lt;br /&gt;
*Attribute, die im RHASSPY-Device selbst gesetzt werden müssen und&lt;br /&gt;
*Attribute, die in den Devices gesetzt werden müssen, die von RHASSPY kontrolliert werden sollen.&lt;br /&gt;
&lt;br /&gt;
Letztere werden im Abschnitt [[#FHEM-Devices für die Verwendung mit Rhasspy konfigurieren|FHEM-Devices für die Verwendung mit Rhasspy konfigurieren]] behandelt.&lt;br /&gt;
&lt;br /&gt;
In diesem Abschnitt werden die Attribute behandelt, die auf das RHASSPY-Device selbst wirken.&lt;br /&gt;
&lt;br /&gt;
===IODev===&lt;br /&gt;
Das MQTT2_CLIENT Device, welches die MQTT-Nachrichten für RHASSPY liefert.&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;code&amp;gt;attr &amp;lt;rhasspyDevice&amp;gt; IODev rhasspyMQTT2&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===forceNEXT===&lt;br /&gt;
Wenn dieses Attribut auf 1 gesetzt ist, leitet RHASSPY eingehende MQTT-Nachrichten an andere MQTT2-IO-Client Module wie MQTT2_DEVICE weiter, auch wenn das Topic zu einem von RHASSPY abonnierten passt.&lt;br /&gt;
Standardmäßig werden diese Nachrichten nicht weitergeleitet um eine bessere Kompatibilität mit dem &#039;&#039;autocreate&#039;&#039;-Feature des MQTT2_DEVICE sicher zu stellen.&lt;br /&gt;
Siehe dazu das {{Link2CmdRef|Anker=MQTT2_CLIENT-attr-clientOrder|Lang=en|Label=clientOrder}}-Attribut in der CommandRef zum MQTT2_CLIENT Device.&lt;br /&gt;
Das Setzen dieses Attributs in einer RHASSPY-Instanz kann auch andere eventuell vorhandene RHASSPY-Instanzen beinflussen.&lt;br /&gt;
Default ist &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;code&amp;gt;attr &amp;lt;rhasspyDevice&amp;gt; forceNext 1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===languageFile===&lt;br /&gt;
{{Randnotiz|RNTyp=g|RNText=Bei Nutzung von configDB wird diese Datei aus der Datenbank gelesen.}}&lt;br /&gt;
Pfad zur Sprach-Datei&lt;br /&gt;
Ist dieses Argument nicht gesetzt, wird ein Standard-Set an englischen Sätzen für die Sprachantworten verwendet.&lt;br /&gt;
Die Datei selbst muss ein gültiges JSON-File sein, dass sich nach der Struktur aus den englischen Standardwerten richtet.&lt;br /&gt;
Eine deutsche Beispiel-Datei ist im [https://svn.fhem.de/trac/browser/trunk/fhem/contrib/RHASSPY/rhasspy-de.cfg SVN] vorhanden. Man kann aber einfach ein Dump der englischen Struktur machen (replace RHASSPY by your device&#039;s name: &amp;lt;code&amp;gt;{toJSON($defs{RHASSPY}-&amp;gt;{helper}{lng})}&amp;lt;/code&amp;gt;, das Ergebnis dann bearbeiten und es als eigenes languageFile verwenden.&lt;br /&gt;
Im Standard-Set sind auch einige Variablen enthalten. Auch die können im eigenen File verwendet werden.&lt;br /&gt;
&#039;&#039;languageFile&#039;&#039; erlaubt auch eine Kombination aus vorhandenen und eigenen Sätzen. Dazu können die eigenen Sätzen einfach im Sub-Tree &#039;&#039;user&#039;&#039; abgelegt werden.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039; (vorausgesetzt, die Sprach-Datei ist im selben Verzeichnis wie fhem.pl):&lt;br /&gt;
&amp;lt;code&amp;gt;attr &amp;lt;rhasspyDevice&amp;gt; languageFile ./rhasspy-de.cfg&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====response====&lt;br /&gt;
{{Hinweis|Die Verwendung dieses Attributs ist nicht mehr empfohlen. Bessere Alternative ist die Sprach-Datei.}}&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Mit diesem Attribut können eigene Standardantworten definiert werden.&lt;br /&gt;
Mögliche Schlüsselwörter sind &amp;lt;code&amp;gt;DefaultError&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;NoActiveMediaDevice&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;DefaultConfirmation&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;DefaultError=&lt;br /&gt;
DefaultConfirmation=Klaro, mach ich&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===rhasspyHotwords===&lt;br /&gt;
Kann verwendet werden, um benutzerdefinierte Aktionen auszuführen, sobald ein bestimmtes Hotword erkannt wurde. Dazu sind keine speziellen Konfigurationsschritte in anderen FHEM Devices notwendig.&lt;br /&gt;
Wenn mittels Attribut oder DEF aktiviert, wird ein Reading &#039;&#039;hotword&#039;&#039; erstellt und mit dem erkannten Hotword und der siteId befüllt um ein Event-Handling zu ermöglichen.&lt;br /&gt;
{{Hinweis|Da bei den hotword messages für alle Teilnehmer dieselbe Topic-Structur verwendet wird, kann RHASSPY nicht unterscheiden, ob eine solche für diese Instanz relevant ist. Falls entsprechende Unterscheidungen gemacht werden sollen, muss dies vom User entsprechend konfiguriert werden, z.B. indem die subscriptions (am MQTT2_CLIENT) eingeschränkt werden oder indem nur jeweils andere hotword-Einträge für jede RHASSPY-Instanz genutzt werden.}}&lt;br /&gt;
Ein Hotword pro Zeile, Syntax entweder einfach oder erweitert&lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;&#039;Beispiele:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;bumblebee_linux = set amplifier2 mute on&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;porcupine_linux = livingroom=&amp;quot;set amplifier mute on&amp;quot; default={Log3($DEVICE,3,&amp;quot;device $DEVICE - room $ROOM - value $VALUE&amp;quot;)}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im ersten Beispiel wird der Befehl immer ausgeführt, wenn das Hotword &#039;&#039;bumblebee_linux&#039;&#039; erkannt wurde.&lt;br /&gt;
Im zweiten nur, wenn das Hotword &#039;&#039;porcupine_linux&#039;&#039; in der siteId &#039;&#039;livingroom&#039;&#039; erkannt wurde.&lt;br /&gt;
$DEVICE wird ausgewertet als der Name des RHASSPY Devices, $ROOM als siteId und $VALUE als das verwendete Hotword.&lt;br /&gt;
&lt;br /&gt;
===rhasspyIntents===&lt;br /&gt;
Definiert einen benutzerdefinierten Intent.&lt;br /&gt;
Ein Intent pro Zeile.&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;attr &amp;lt;rhasspyDevice&amp;gt; rhasspyIntents SetCustomIntentsTest=SetCustomIntentsTest(siteId,Type)&amp;lt;/code&amp;gt;&lt;br /&gt;
in Kombination mit folgendem myUtils-Code&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub SetCustomIntentsTest {&lt;br /&gt;
my $room = shift;&lt;br /&gt;
my $type = shift;&lt;br /&gt;
Log3(&#039;rhasspy&#039;,3 , &amp;quot;RHASSPY: Room $room, Type $type&amp;quot;);&lt;br /&gt;
return &amp;quot;RHASSPY: Room $room, Type $type&amp;quot;;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
schreibt einen Log-Eintrag nach jedem Aufruf dieses Intents.&lt;br /&gt;
&lt;br /&gt;
Die folgenden Argumente können dabei übergeben werden:&lt;br /&gt;
* NAME =&amp;gt; Name des RHASSPY-Devices&lt;br /&gt;
* DATA =&amp;gt; komplette JSON-$data (wie intern geparsed), in JSON kodiert&lt;br /&gt;
* siteId, Device etc. =&amp;gt; jedes Element, das in JSON-$data existiert&lt;br /&gt;
Wird von der Funktion ein einfacher Text zurück geliefert, wird dieser als &#039;&#039;response&#039;&#039; angesehen. Wenn der Rückgabewert nicht definiert ist, wird die Standard-&#039;&#039;response&#039;&#039; verwendet.&lt;br /&gt;
&lt;br /&gt;
Es kann aber auch ein &#039;&#039;&#039;HASH&#039;&#039;&#039; oder &#039;&#039;&#039;ARRAY&#039;&#039;&#039; übergeben werden.&lt;br /&gt;
* Im Falle eines &#039;&#039;&#039;ARRAY&#039;&#039;&#039;s wird das erste Element als &#039;&#039;response&#039;&#039; interpretiert und kann ein reiner Text sein, womit der Dialog beendet wird. &lt;br /&gt;
* Ist das erste Element ein &#039;&#039;&#039;HASH&#039;&#039;&#039; wird die Dialog-Session fortgesetzt. Eine offene Dialog-Session wird per Default nach 20 Sekunden beendet. Diese Zeitspanne kann aber auch geändert werden, in dem im ARRAY als zweiter Wert eine Zahl übergeben wird. Das zweite Element kann aber auch eine komma-getrennte Liste an Geräten sein, die geändert (geschalten) wurden. Das dient dazu, damit die Geräte auch Events liefern, was ansonsten nicht der Fall wäre. Siehe dazu den &amp;quot;d&amp;quot;-Parameter beim Attribut [[#rhasspyShortcuts|rhasspyShortcuts]].&lt;br /&gt;
Wird eine HASH-Datenstruktur (ggf. in $response innerhalb einer ARRAY-Struktur), um einen laufenden Dialog fortzusetzen, muss sichergestellt werden, dass alle erforderlichen Datenelemente enthalten sind, insbesondere &#039;&#039;intentFilter&#039;&#039;, falls die für den weiteren Dialog relevanten Intents eingeschränkt (oder erweitert) werden sollen. Dabei sollte möglichst der Intent &#039;&#039;CancelAction&#039;&#039; aktiv gehalten werden, damit der User die Option hat, den Dialog jederzeit aktiv zu beenden.&lt;br /&gt;
&lt;br /&gt;
Siehe dazu auch den Abschnitt [[#Eigene Intents erstellen|Eigene Intents erstellen]].&lt;br /&gt;
&lt;br /&gt;
===rhasspyShortcuts===&lt;br /&gt;
Hiermit können benutzerdefinierte Sätze erstellt werden ohne die sentences.ini in Rhasspy bearbeiten zu müssen.&lt;br /&gt;
Diese Shortcuts werden zu Rhasspy hochgeladen, sobald das &amp;lt;code&amp;gt;updateSlots&amp;lt;/code&amp;gt; [[#set-update|Set]]-Kommando ausgeführt wird.&lt;br /&gt;
Ein Shortcut pro Zeile, Syntax ist entweder einfach oder erweitert.&lt;br /&gt;
&#039;&#039;&#039;Beispiele:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;mute on=set amplifier2 mute on&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;lamp off={fhem(&amp;quot;set lampe1 off&amp;quot;)}&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;i=&amp;quot;du bist cool&amp;quot; f=&amp;quot;set $NAME speak siteId=&#039;livingroom&#039; text=&#039;danke dir! du bist noch viel cooler!&#039;&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;i=&amp;quot;schalte den ton aus&amp;quot; p={fhem (&amp;quot;set $NAME mute off&amp;quot;)} n=amplifier2 c=&amp;quot;soll ich den ton wirklich ausschalten?&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;i=&amp;quot;ich hab hunger&amp;quot; f=&amp;quot;set Herd on&amp;quot; d=&amp;quot;Herd&amp;quot; c=&amp;quot;möchtest du schweinsbraten?&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Erklärung zu den Abkürzungen:&lt;br /&gt;
* &amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt; =&amp;gt; intent&lt;br /&gt;
Zeilen, die mit &amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt; beginnen, werden als erweiterte Syntax interpretiert. Soll die erweiterte Syntax verwendet werden, ist das &amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt; also Pflicht!&lt;br /&gt;
* &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; =&amp;gt; FHEM Befehl&lt;br /&gt;
Syntax wie von der FHEM Kommandozeile gewohnt&lt;br /&gt;
* &amp;lt;code&amp;gt;p&amp;lt;/code&amp;gt; =&amp;gt; Perl Befehl&lt;br /&gt;
Syntax wie von der FHEM Kommandozeile gewohnt, eingerahmt in geschwungenen Klammern (&amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt;). &amp;lt;code&amp;gt;p&amp;lt;/code&amp;gt; hat Vorrang vor &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;d&amp;lt;/code&amp;gt; =&amp;gt; Device Name(en, Komma getrennt)&lt;br /&gt;
Device Name(n), die an fhem.pl als upgedated übergeben werden sollen. Das wird benötigt um weitere Aktionen in FHEM und das Longpolling zu triggern.&lt;br /&gt;
&lt;br /&gt;
Hinweis: Wenn Perl-Funktionen aufgerufen werden, wird der Rückgabewert dieser Funktion verwendet, sofern kein explizites Device angegeben ist.&lt;br /&gt;
* &amp;lt;code&amp;gt;r&amp;lt;/code&amp;gt; =&amp;gt; Response&lt;br /&gt;
Sprachanwort, die ausgegeben wird. Ist &amp;lt;code&amp;gt;r&amp;lt;/code&amp;gt; nicht gesetzt, wird der Rückgabewert der aufgerufenen Funktion verwendet.&lt;br /&gt;
In den Antwortsätze werden &#039;&#039;set magic&#039;&#039;-ähnliche Ersetzungen verarbeitet. Es ist also auch eine Zeile wie &amp;lt;code&amp;gt;i=&amp;quot;what&#039;s the time for sunrise&amp;quot; r=&amp;quot;at [Astro:SunRise] o&#039;clock&amp;quot;&amp;lt;/code&amp;gt; gültig.&lt;br /&gt;
&lt;br /&gt;
Mit den folgenden Abkürzungen kann auch nach einer Bestätigung für den Befehl gefragt werden:&lt;br /&gt;
* &amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt; =&amp;gt; Entweder Zahl oder Text. Wenn Zahl, wird sie als Timeout für den Abbruch des Dialogs behandelt. Wenn Text wird dieser als Sprachausgabe zur Bestätigung verwendet.&lt;br /&gt;
* &amp;lt;code&amp;gt;ct&amp;lt;/code&amp;gt; =&amp;gt; Numerischer Wert für das Timeout des Dialogs in Sekunden. Default ist &amp;lt;code&amp;gt;15&amp;lt;/code&amp;gt;.&lt;br /&gt;
Siehe [[#attr-rhasspytweaks-confirmintents|hier]] für weitere Informationen zu Bestätigungen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===rhasspyTweaks===&lt;br /&gt;
Mit diesen Einstellungen können benutzerdefinierte Optimierungen an RHASSPY vorgenommen werden.&lt;br /&gt;
&lt;br /&gt;
====timerLimits====&lt;br /&gt;
Wird verwendet um den Timer anzuweisen mit z.B. &amp;quot;gestellt auf 30 Minuten&amp;quot; oder &amp;quot;gestellt auf 10:30&amp;quot; zu antworten&lt;br /&gt;
:&amp;lt;code&amp;gt;timerLimits=90,300,3000,2*HOURSECONDS,50&amp;lt;/code&amp;gt;&lt;br /&gt;
Hierbei müssen fünf Werte gesetzt werden, die den Zeitgrenzen für Stufen in der Antwortstruktur &#039;&#039;timerSet&#039;&#039; entsprechen.&lt;br /&gt;
Obiges Beispiel also würde dazu führen, unter einer eingestellten Zeit von 90 Sekunden mit der Sekundenangabe geantwortet wird. In Minuten und Sekunden solange der Timer kürzer als 300 Sekunden ist. Usw. Der letzte Wert ist das Limit in Sekunden, wenn der Timer im &amp;quot;Uhrzeit&amp;quot;-Format gestellt ist.&lt;br /&gt;
&lt;br /&gt;
====timerSounds====&lt;br /&gt;
Standardmäßig antwortet der Timer mit einer Sprachnachricht, wenn er abgelaufen ist. Soll lieber eine WAV-Datei verwendet werden, kann das hier eingestellt werden.&lt;br /&gt;
:&amp;lt;code&amp;gt;timerSounds= default=./yourfile1.wav eier=3:20:./yourfile2.wav kartoffeln=5:./yourfile3.wav&amp;lt;/code&amp;gt;&lt;br /&gt;
Die Keys in dieser Code-Zeile sind Beispiele und deren Name - bis auf &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; frei wählbar. Der Name muss aber zu den &#039;&#039;Label&#039;&#039;-Tags für die Timer in den Rhasspy-Sentences passen.&lt;br /&gt;
&amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; ist optional. Wenn gesetzt, wird dieses WAV-File für alle benannten Timer verwendet, für die kein Keyword in der Konfiguration ist.&lt;br /&gt;
Die beiden Nummern sind optional. Die erste legt fest, wie oft die WAV-Datei wiederholt werden soll (Default: 5). Die zweite definiert die Pause in Sekunden zwischen den Wiederholungen (Default: 15). Ist nur eine Zahl gesetzt, wird diese als gewünschte Anzahl an Wiederholungen interpretiert.&lt;br /&gt;
&lt;br /&gt;
====updateSlots====&lt;br /&gt;
Ändert diverse Aspekte des Erstellens und Updatens von Slots&lt;br /&gt;
* &amp;lt;code&amp;gt;noEmptySlots=1&amp;lt;/code&amp;gt;&lt;br /&gt;
Per Default generiert RHASSPY einen zusätzlichen Slot für jeden &#039;&#039;genericDeviceType&#039;&#039;, der erkannt wird. Unabhängig davon, ob er bei einem Gerät gesetzt ist. Das kann zu leeren Slots führen.&lt;br /&gt;
Ist der Wert &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;, werden keine leeren Slots erstellt.&lt;br /&gt;
* &amp;lt;code&amp;gt;overwrite_all=false&amp;lt;/code&amp;gt;&lt;br /&gt;
RHASSPY überschreibt alle vorhandenen Slots wenn ein &amp;lt;code&amp;gt;updateSlots&amp;lt;/code&amp;gt; ausgeführt wird. Ist das nicht gewünscht, muss dieser Wert auf &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; gesetzt werden.&lt;br /&gt;
* &amp;lt;code&amp;gt;timeouts&amp;lt;/code&amp;gt;&lt;br /&gt;
Die Keywörter &amp;lt;code&amp;gt;confirm&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; können verwendet werden, um das Standard-Timeouts (15s/20s) für Dialoge zu ändern.&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;code&amp;gt;timeouts: confirm=25 default=30&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====confidenceMin====&lt;br /&gt;
Rhasspy ermittelt u.A. auch einen Indikator, anhand dem bestimmt werden kann, wie genau ein Satz erkannt wurde. Ist dieser &#039;&#039;confidence&#039;&#039;-Wert sehr bzw. zu niedrig, kann es erwünscht sein, die (falsch erkannte) Absicht des Sprechers nicht umzusetzen. RHASSPY nutzt daher standardmäßig einen Mindestwert von 0.66, bei allen darunter liegenden Werten wird das betreffende Kommando nicht ausgeführt. Dies kann über diesen Tweak global (key: default) oder feiner pro Intent festgelegt werden.&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;code&amp;gt;confidenceMin= default=0.6 SetMute=0.4 SetOnOffGroup=0.8 SetOnOff=0.8&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====confirmIntents====&lt;br /&gt;
Hiermit kann eingestellt werden, dass für bestimmte Intents immer ein Bestätigung erfragt wird. Unterstützt werden derzeit alle &amp;quot;set-&amp;quot;-Intents.&lt;br /&gt;
Dazu werden &amp;lt;code&amp;gt;Intent&amp;lt;/code&amp;gt;=&amp;lt;code&amp;gt;regex&amp;lt;/code&amp;gt;-Paare verwendet. &amp;lt;code&amp;gt;Intent&amp;lt;/code&amp;gt; ist der Name des gewünschten Intents, &amp;lt;code&amp;gt;regex&amp;lt;/code&amp;gt; ist eine Regex, die eine bestimmte Gruppe (für Gruppen-Intents) oder einen bestimmten Device-Namen beschreiben muss.&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;code&amp;gt;confirmIntents=SetOnOffGroup=light|blinds SetOnOff=blind.*&amp;lt;/code&amp;gt;&lt;br /&gt;
Befehle werden nur nach einer positiven Bestätigung ausgeführt. Das bedeutet, es wird eine Rückfrage ausgegeben, auf diese muss dann (innerhalb des gesetzten Timeouts) unbedingt ein &amp;lt;code&amp;gt;Mode:OK&amp;lt;/code&amp;gt;-Wert vom &#039;&#039;ConfirmAction&#039;&#039;-Intent gesendet werden. Jede andere Wert für &amp;lt;code&amp;gt;Mode&amp;lt;/code&amp;gt; wird als Abbruch gewertet. Es kann aber auch der eigene Intent &#039;&#039;CancelAction&#039;&#039; für den Abbruch verwendet werden.&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:ConfirmAction]&lt;br /&gt;
( yes, please do it | go on | that&#039;s ok | yes, please ){Mode:OK}&lt;br /&gt;
( don&#039;t do it after all ){Mode}&lt;br /&gt;
&lt;br /&gt;
[de.fhem:CancelAction]&lt;br /&gt;
( let it be | oh no | cancel | cancellation ){Mode:Cancel}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====confirmIntentResponses====&lt;br /&gt;
Üblicherweise ist die Bestätigungs-Frage ein &amp;quot;Echo&amp;quot; des ursprünglich gesprochenen Befehls. Dies kann für jeden Intent geändert werden,&lt;br /&gt;
Dies kann für jeden Intent individuell angepaßt werden, wobei die Variablen $target, ($rawInput) und $Value verwendet werden können.&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;code&amp;gt;confirmIntentResponses=SetOnOffGroup=&amp;quot;wirklich die Gruppe $target $Value schalten&amp;quot; SetOnOff=&amp;quot;bestätige dass $target $Value geschaltet werden soll&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;$Value&amp;lt;/code&amp;gt; wird dabei mit den defaults aus dem &#039;&#039;words&#039;&#039; key in der languageFile übersetz (falls vorhanden). Weitere Optionen für Ersetzungen von &amp;lt;code&amp;gt;$Value&amp;lt;/code&amp;gt; sind für einzelne Devices über den [[#attr-rhasspyspecials-confirmvaluemap|confirmValueMap]] key im Attribut &#039;&#039;rhasspySpecials&#039;&#039; verfügbar.&lt;br /&gt;
&lt;br /&gt;
====intentFilter====&lt;br /&gt;
Rhasspy aktiviert bei jedem Neustart alle ihm bekannten Intents. Da manche der von FHEM genutzten Intents nur in bestimmten Situationen (v.a. innerhalb offener Dialoge) benötigt werden, deaktiviert RHASSPY diese (derzeit: ConfirmAction, CancelAction, Choice, ChoiceRoom und ChoiceDevice beim Start, sowie jedes Mal, wenn erkannt wird, dass das Standardfiltering nicht wie erwartet funktioniert (was v.a. bei einem zwischenzeitlichen Rhasspy-Neustart der Fall sein kann). Über diesen Tweak können weitere Intents mit in diese automatisierte (De-) Aktivierung mit einbezogen werden. Entweder ist dabei einfach der Name (ohne die Zusätze aus &#039;&#039;language&#039;&#039; und &#039;&#039;fhemId&#039;&#039; anzugeben, oder eine explizite Anweisung zum ein- und Ausschalten (in der Form &amp;lt;code&amp;gt;intentname=true&amp;lt;/code&amp;gt;). Die 4 vorgenannten Standard-Intents können nicht über diesen Weg aktiviert werden. Details zur intern genutzten Rhasspy-Funktionalität sind in der [https://rhasspy.readthedocs.io/en/latest/reference/#dialogue-manager Rhasspy-Dokumentation] zu finden.&lt;br /&gt;
&lt;br /&gt;
====ignoreKeywords====&lt;br /&gt;
Da in manchen der von RHASSPY automatisch ausgewerteten Attribute häufig auch eher technisch motivierte Angaben zu finden sind, kann über diesen Schlüssel verhindert werden, dass derartige Angaben bei der slot-Erstellung übergangen werden. Dies betrifft z.B. häufig anzutreffende &#039;&#039;room&#039;&#039;-Werte wie &#039;&#039;MQTT&#039;&#039;, &#039;&#039;alexa&#039;&#039;, &#039;&#039;homebridge&#039;&#039; oder &#039;&#039;googleassistant&#039;&#039;. Die hier angegebenen key-value-Paare werden als Negativ-Filter für die angegebenen Werte verwendet (derzeit nur für &#039;&#039;rooms&#039;&#039; und &#039;&#039;group&#039;&#039;). &#039;&#039;value&#039;&#039; wird dabei als (case-insensitive) regex behandelt, verglichen wird auf exakten match (es müssen also ggf. vorne bzw. hinten &#039;&#039;.*&#039;&#039; angefügt werden).&lt;br /&gt;
Dieses &#039;&#039;&#039;Beispiel&#039;&#039;&#039; filtert daher die o.g. Räume aus und dazu noch die strukturierten Unterräume unterhalb &#039;&#039;Steuerung&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ignoreKeywords=rooms=mqtt.*|alexa|homebridge|googleassistant|steuerung-.&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====gdt2groups====&lt;br /&gt;
Dieser Eintrag ermöglicht es, alle Geräte eines generichDeviceType innerhalb der automatischen Erfassung automatisch einer oder mehreren Gruppen zuzuordnen. Die Vorgaben in diesem Eintrag werden nicht übernommen, wenn am jeweiligen Einzelgerät  das Attribut &#039;&#039;rhasspyGroup&#039;&#039; gesetzt ist.  Hier eine deutschsprachige Vorbelegung als &#039;&#039;&#039;Beispiel&#039;&#039;&#039;: &amp;lt;code&amp;gt;gdt2groups= blind=rollläden,rollladen thermostat=heizkörper light=lichter,leuchten&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====mappingOverwrite====&lt;br /&gt;
Wird diese Option aktiviert, wird bei gesetztem &#039;&#039;rhasspyMapping&#039;&#039;-Attribut an einem Device alles gelöscht, was die automatisierte mapping-Erkennung anhand des genericDeviceType erkannt hatte. Sonst ird jeweils nur überschrieben, was als Intent im &#039;&#039;rhasspyMapping&#039;&#039; dieses Geräts angegeben ist.&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
:mappingOverwrite=1&lt;br /&gt;
&lt;br /&gt;
====extrarooms====&lt;br /&gt;
Komma-separierte Liste von weiteren Räumen, die die aus der Generierung der Device-Map bekannten Räume erweitert. Dies kann z.B. für CustomIntents benötigt werden.&lt;br /&gt;
Diese werden in die Slots für &amp;lt;code&amp;gt;rooms&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;mainrooms&amp;lt;/code&amp;gt; integriert.&lt;br /&gt;
Beispiel:&lt;br /&gt;
:extrarooms= barn,music collection,cooking recipies&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Readings / Events==&lt;br /&gt;
;&amp;lt;code&amp;gt;IODev&amp;lt;/code&amp;gt;&lt;br /&gt;
:Das eingestellte IO-Device&lt;br /&gt;
;&amp;lt;code&amp;gt;intents&amp;lt;/code&amp;gt;&lt;br /&gt;
:Eine Liste der in Rhasspy vorhandenen Intents&lt;br /&gt;
;&amp;lt;code&amp;gt;lastIntentPayload&amp;lt;/code&amp;gt;&lt;br /&gt;
:Inhalt des letzten Intents der von FHEM empfangen wurde&lt;br /&gt;
;&amp;lt;code&amp;gt;lastIntentTopic&amp;lt;/code&amp;gt;&lt;br /&gt;
:Das MQTT-Topic des letzten Intents&lt;br /&gt;
;&amp;lt;code&amp;gt;listening_roomname&amp;lt;/code&amp;gt;&lt;br /&gt;
:Ein Reading für jeden Raum bzw. jede siteId&lt;br /&gt;
:Wechselt auf 1 sobald ein Hotword erkannt wurde und zurück auf 0, sobald die Dialog-Session beendet ist.&lt;br /&gt;
:Kann z.B. verwendet werden, um den Ton eines TVs auszuschalten, während Rhasspy auf ein Kommando hört.&lt;br /&gt;
;&amp;lt;code&amp;gt;mute_roomname&amp;lt;/code&amp;gt;&lt;br /&gt;
:Zeigt an, ob ein Raum / eine siteId vom Intent &#039;&#039;SetMute&#039;&#039; stumm geschalten wurde und somit keine Befehle ausführt.&lt;br /&gt;
:Jeweils ein Reading für jede siteId.&lt;br /&gt;
:Default ist 0.&lt;br /&gt;
;&amp;lt;code&amp;gt;responseType&amp;lt;/code&amp;gt;&lt;br /&gt;
:Der Typ der letzten Antwort (text/voice).&lt;br /&gt;
:voiceResponse and textResponse&lt;br /&gt;
:Antwort auf das letzte Sprach-/Text-Kommando.&lt;br /&gt;
;&amp;lt;code&amp;gt;siteIds&amp;lt;/code&amp;gt;&lt;br /&gt;
:Listet alle siteIds auf.&lt;br /&gt;
:Kann mit [[#set-fetchsiteids|fetchSiteIds]] aktualisiert werden.&lt;br /&gt;
;&amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;&lt;br /&gt;
:Zeigt an ob RHASSPY mit Rhasspy verbunden ist&lt;br /&gt;
;&amp;lt;code&amp;gt;training&amp;lt;/code&amp;gt;&lt;br /&gt;
:Letzte zurückgelieferte Antwort auf einen [[#set-trainrhasspy|trainRhasspy]]-Befehl.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
;&amp;lt;code&amp;gt;updateSentences&amp;lt;/code&amp;gt;&lt;br /&gt;
:Letzte zurückgelieferte Antwort nach einem [[#set-update-slots|updateSlots]]-Befehl.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
;&amp;lt;code&amp;gt;updateSlots&amp;lt;/code&amp;gt;&lt;br /&gt;
:Letzte zurückgelieferte Antwort nach einem [[#set-update-slots|updateSlots]]-Befehl.&lt;br /&gt;
;&amp;lt;code&amp;gt;hotword&amp;lt;/code&amp;gt;&lt;br /&gt;
:Wenn aktiviert, beinhaltet dieses Reading das letzte verwendete Hotword und von welcher siteId es aufgerufen wurde.&lt;br /&gt;
;&amp;lt;code&amp;gt;voiceResponse&amp;lt;/code&amp;gt;&lt;br /&gt;
:Letze Sprach-Antwort auf einen Sprach-Befehl&lt;br /&gt;
&lt;br /&gt;
=== Benutzerdefinierte Readings ===&lt;br /&gt;
Um das Verhalten von RHASSPY beeinflussen zu können, können neben den bei den Attributen verfügbaren &#039;&#039;Tweaks&#039;&#039; auch die folgenden Readings genutzt - und v.a. auch im laufenden Betrieb immer weider geändert - werden:&lt;br /&gt;
*&amp;lt;code&amp;gt;siteId2room_&amp;lt;/code&amp;gt; Falls keine explizite Raum-Information in den an RHASSPY weitergegebenen Daten enthalten ist, ermittelt das Modul den Raum in der Regel aus dem Namen der &#039;&#039;siteId&#039;&#039;. So werden z.B. alle raumlosen Anweisungen von einem Satelliten names &#039;&#039;schlafzimmer&#039;&#039;, im Raum &#039;&#039;schlafzimmer&#039;&#039; ausgeführt werden (wenn möglich). Die Gruppenfunktion von Rhasspy wird unterstützt, so wird z.B. &#039;&#039;wohnzimmer.vorne&#039;&#039; ebenfalls automatisch dem Raum &#039;&#039;wohnzimmer&#039;&#039; zugeordnet. Über passende Angaben in &#039;&#039;siteId2room-Readings&#039;&#039; kann dieses Verhalten modifiziert werden:  &amp;lt;code&amp;gt;setreading siteId2room_mobile_phone1 wohnzimmer&amp;lt;/code&amp;gt; wird RHASSPY veranlassen, den Satelliten  &#039;&#039;mobile_phone1&#039;&#039; dem Raum &#039;&#039;wohnzimmer&#039;&#039; zuzuweisen. Ein Beispiel, mit dem dies per Sprachkommando erfolgt, ist in &#039;&#039;contrib&#039;&#039; zu finden, mit der mobilen Satelliten per Funktionsaufruf in einem [[#rhasspyIntents|rhasspyIntent]] einem neuen Raum zugewiesen werden können.&lt;br /&gt;
*&amp;lt;code&amp;gt;siteId2doubleSpeak_&amp;lt;/code&amp;gt; RHASSPY antwortet immer über den Satelliten, von dem die jeweilige Sprachanweisung kam. Manchmal kann es erwünscht sein, zusätzliche Sprachrückmeldungen an einen weiteren Satelliten zu geben - z.B. weil der betreffende Lautsprecher (zeitweise) ausgeschaltet ist. Ist ein entsprechendes Reading gesetzt, erfolgen (zusätzliche!) Sprachausgaben an den dort als Readingwert angegebenen zweiten Satelliten; das Namensschema der Readings entspricht dem für site2room.&lt;br /&gt;
&lt;br /&gt;
== FHEM-Devices für die Verwendung mit Rhasspy konfigurieren ==&lt;br /&gt;
Um ein Gerät mit Rhasspy steuern zu können, muss Rhasspy einige Details über das Gerät kennen. Diese werden bekannt gemacht, in dem bei den Geräten Attribute gesetzt werden, die anschließend vom RHASSPY-Modul ausgewertet und an Rhasspy gesendet werden.&lt;br /&gt;
&lt;br /&gt;
Der einfachste - und empfohlene - Weg, dies zu erreichen, ist durch Setzen des Attributs &#039;&#039;&#039;&#039;&#039;genericDeviceType&#039;&#039;&#039;&#039;&#039;. Das Modul erkennt dann die möglichen Schalt - und Abfragemöglichkeiten des Gerätes automatisch.&lt;br /&gt;
&lt;br /&gt;
Sollte &#039;&#039;genericDeviceType&#039;&#039; (gDT) nicht ausreichen, gibt es noch weitere Attribute, die stattdessen oder ergänzend dazu verwendet werden können (z.b. rhasspyName, rhasspyRoom, ...). Die Namen dieser Attribute beginnen alle mit dem &#039;&#039;prefix&#039;&#039;, das in der DEF des RHASSPY-Moduls gesetzt wurde. Diese Dokumentation verwendet das Prefix &amp;lt;code&amp;gt;rhasspy&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Sind sowohl &#039;&#039;genericDeviceType&#039;&#039; als auch Spezial-Attribute vorhanden, werden die von gDT gesammelten Möglichkeiten durch die der Spezial-Attribute überschrieben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Wichtig:&#039;&#039;&#039;&lt;br /&gt;
*Nach JEDER Änderung (bzw. nach Abschluss aller Änderungen) an den folgenden Attributen muss ein &amp;lt;code&amp;gt;[[#update devicemap|update devicemap]]&amp;lt;/code&amp;gt; ausgeführt werden. In der Regel wird dies automatisch veranlasst, aber wenn dies deaktiviert sein sollte, würden sonst weder RHASSPY, noch Rhasspy von der Änderung erfahren.&lt;br /&gt;
*RHASSPY sammelt alle Informationen aus diesen Attributen in seinem eigenen Device-HASH. Dieser wird durch das &amp;lt;code&amp;gt;update devicemap&amp;lt;/code&amp;gt;-Kommando aktualisiert und kann mittels &amp;lt;code&amp;gt;[[List|list]]&amp;lt;/code&amp;gt;-Befehl angezeigt werden. Für diesen HASH werden alle Namen und sonstige &amp;quot;Labels&amp;quot; in Kleinbuchstaben umgewandelt. Falls man Slots händisch befüllt, muss also darauf geachtet werden, dass Rhasspy ebenfalls Werte in Kleinbuchstaben liefert.&lt;br /&gt;
*Die Mindestvoraussetzungen für ein FHEM Device um mit RHASSPY zusammenzuarbeiten sind:&lt;br /&gt;
**Das Device muss von der &#039;&#039;devspec&#039;&#039; im Define des RHASSPY-Devices abgedeckt werden&lt;br /&gt;
**Es muss mindestens eines der folgenden Attribute (im Normalfall &#039;&#039;genericDeviceType&#039;&#039;) im Device gesetzt sein.&lt;br /&gt;
*Die Mapping-Logik (für Namen, mögliche Schaltzustände, etc.) ist wie folgt:&lt;br /&gt;
**Sind RHASSPY-spezifische Attribute gesetzt, werden ausschließlich diese verwendet. Natürlich nur für den Zweck des gesetzten Attributs. Ein gesetzter &#039;&#039;rhasspyName&#039;&#039; z.B. wird also nicht verhindern, dass die durch &#039;&#039;genericDeviceType&#039;&#039; ermittelten möglichen Schaltzustände ebenfalls gespeichert werden.&lt;br /&gt;
**Je spezifischer ein Attribut ist, desto eher wird überschreiben, was weniger speziell ist. Ein gesetzter &#039;&#039;alias&#039;&#039; wird also verhindern, dass der (technische) Device-Name verwendet wird. Aber ein gesetztes Attribut &#039;&#039;alexaName&#039;&#039;, &#039;&#039;gassistantName&#039;&#039; oder &#039;&#039;siriName&#039;&#039; wird (auch) den &#039;&#039;alias&#039;&#039; überschreiben. Sind zwei &amp;quot;gleichwertige&amp;quot; Attribute vorhanden (z.B. &#039;&#039;siriName&#039;&#039; und &#039;&#039;alexaName&#039;&#039;), werden beide verwendet.&lt;br /&gt;
*Attribut-Werte werden typischerweise &amp;quot;Zeile für Zeile&amp;quot; gelesen. Wobei gilt, eine Zeile pro Wert/Befehl/Funktionalität. Zeilenumbrüche &#039;&#039;&#039;müssen&#039;&#039;&#039; also an den richtigen Stellen gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
=== genericDeviceType ===&lt;br /&gt;
Ist dieses Attribut gesetzt &#039;&#039;&#039;und&#039;&#039;&#039; entspricht der Devicename der devspec, wird RHASSPY das Mapping (und andere eventuell schon vorhandene Werte) automatisch ermitteln.&lt;br /&gt;
&lt;br /&gt;
Derzeit werden folgende Werte für das Attribut genericDeviceType unterstützt:&lt;br /&gt;
*switch&lt;br /&gt;
*light&lt;br /&gt;
*thermostat&lt;br /&gt;
*thermometer&lt;br /&gt;
*HumiditySensor&lt;br /&gt;
*blind/blinds/shutter&lt;br /&gt;
*media&lt;br /&gt;
*motion/contact/ContactSensor/lock/presence&lt;br /&gt;
&lt;br /&gt;
Wird &#039;&#039;genericDeviceType&#039;&#039; verwendet, werden unter anderem folgende Informationen gesammelt:&lt;br /&gt;
* der Name (&amp;lt;code&amp;gt;NAME&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;alias&amp;lt;/code&amp;gt;) des Devices&lt;br /&gt;
* der (FHEM-)Raum, in dem sich das Device befindet.&lt;br /&gt;
* die Gruppe, zu der das Device gehört (ggf. unter Beachtung des Schlüssels [[#gdt2groups|gdt2groups]] aus [[#rhasspyTweaks|rhasspyTweaks]])&lt;br /&gt;
* wie Informationen vom Gerät abgefragt werden können&lt;br /&gt;
* wie Werte/Status am Gerät gesetzt werden können&lt;br /&gt;
&lt;br /&gt;
Die Verwendung von &#039;&#039;genericDeviceType&#039;&#039; ist der einfachste Weg, wie man FHEM-Devices dazu bringen kann, mit RHASSPY zusammenzuarbeiten. Manchmal liefert genericDeviceType aber nicht ausreichende oder nicht passende Informationen. In so einem Fall können die folgenden Attribute (zusätzlich) verwendet werden.&lt;br /&gt;
&lt;br /&gt;
=== rhasspyName ===&lt;br /&gt;
Mit diesem Attribut kann der Name des Geräts eingestellt werden, mit dem es in einem Sprachbefehl angesprochen werden soll. Es können auch mehrere Namen - getrennt durch ein Komma - angegeben werden, der erste Wert in dieser Liste dient intern als Hauptname (&#039;&#039;alias&#039;&#039;), z.B. in Auswahldialogen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039; &amp;lt;code&amp;gt;attr &amp;lt;device&amp;gt; rhasspyName Lampe,Stehlampe,Wunderlicht&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es ist durchaus möglich, mehrere FHEM-Geräte mit dem selben Namen zu haben. Sie müssen dann nur in unterschiedlichen Räumen sein.&lt;br /&gt;
&lt;br /&gt;
=== rhasspyRoom ===&lt;br /&gt;
Dieses Attribut kann verwendet werden, um Rhasspy mitzuteilen, in welchem physischem (oder logischen) Raum sich das Gerät befindet.&lt;br /&gt;
&lt;br /&gt;
Ist es nicht vorhanden, wird &amp;lt;code&amp;gt;alexaRoom&amp;lt;/code&amp;gt; oder das FHEM-Attribut &amp;lt;room&amp;gt; verwendet. Sind auch diese nicht vergeben, gehört das Gerät zum &amp;quot;Standard-Raum&amp;quot;, der im Define des RHASSPY-Devices angegeben wurde.&lt;br /&gt;
&lt;br /&gt;
Das Attribut ist nützlich, wenn man Sprachbefehle ohne explizite Raumangabe verwenden will. Gibt es z.B. ein Gerät mit dem Namen &#039;&#039;Lampe&#039;&#039; und dessen rhasspyRoom-Attribut ist gleich, wie die &#039;&#039;siteId&#039;&#039; von der aus der Sprachbefehl abgesetzt wird, reicht es zu sagen &amp;quot;Lampe ein&amp;quot;. Der Raum muss also nicht extra dazu gesagt werden.&lt;br /&gt;
&lt;br /&gt;
Es ist auch möglich, mehrere Raum-Namen zu vergeben sofern diese durch ein Komma voneinander getrennt werden (der erste Wert ist wieder der &#039;&#039;Hauptraum&#039;&#039; für Auswahldialoge etc.).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039; &amp;lt;code&amp;gt;attr &amp;lt;device&amp;gt; rhasspyRoom livingroom&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hinweis: Wenn die &#039;&#039;siteId&#039;&#039; den Konventionen von Rhasspy zur Gruppierung von siteIds folgt (&#039;&#039;roomname.satellite&#039;&#039;), wird nur &amp;lt;code&amp;gt;roomname&amp;lt;/code&amp;gt; als Raum-Name angenommen. Beachte: Die automatisierte Zuweisung zu einem Raum kann durch &#039;&#039;siteId2room_.*&#039;&#039;-Readings modifiziert werden (s.o.). &lt;br /&gt;
&lt;br /&gt;
=== rhasspyGroup ===&lt;br /&gt;
Kommagetrennte Liste an Gruppen, zu denen das Gerät zugehörig ist&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039; &amp;lt;code&amp;gt;attr &amp;lt;device&amp;gt; rhasspyGroup Lampen,Beleuchtung Arbeitsfläche,Küchen Beleuchtung&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== rhasspyMapping ===&lt;br /&gt;
Wenn die automatische Erkennung des richtigen Intents für ein Gerät nicht funktioniert oder nicht das gewünschte Ergebnis liefert, kann mit diesem Attribut angegeben werden, mit welchem Intent das Gerät gesteuert werden kann.&lt;br /&gt;
&lt;br /&gt;
Es ist möglich, mehrere verschiedene Intents pro Gerät zu verwenden. Es muss nur einfach eine neue Zeile für ein weiteres Mapping verwendet werden.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr &amp;lt;device&amp;gt; rhasspyMapping SetOnOff:cmdOn=on,cmdOff=off,response=&amp;quot;Alles klar&amp;quot;&lt;br /&gt;
GetOnOff:currentVal=state,valueOff=off&lt;br /&gt;
GetNumeric:currentVal=pct,type=brightness&lt;br /&gt;
SetNumeric:currentVal=brightness,cmd=brightness,minVal=0,maxVal=255,map=percent,step=1,type=brightness&lt;br /&gt;
Status:response=Die Helligkeit in der Küche ist bei [&amp;lt;device&amp;gt;:pct]&lt;br /&gt;
MediaControls:cmdPlay=play,cmdPause=pause,cmdStop=stop,cmdBack=previous,cmdFwd=next&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Formatierung von Befehlen und Readings innerhalb eines rhasspyMappings ====&lt;br /&gt;
Manche Intents können FHEM-Kommandos oder -Readings verwenden, um Werte auszulesen oder zu setzen.&lt;br /&gt;
&lt;br /&gt;
Dabei gibt es drei Möglichkeiten, wie diese geschrieben werden können:&lt;br /&gt;
*Direktes Verwenden von SET-Kommando oder Reading des aktuellen Device:&lt;br /&gt;
:&amp;lt;code&amp;gt;cmd=on or currentReading=temperature&amp;lt;/code&amp;gt;&lt;br /&gt;
*Umleiten eines Kommando auf ein anderes Device oder Verwenden eines Readings aus einem anderen Gerät:&lt;br /&gt;
:&amp;lt;code&amp;gt;cmd=Otherdevice:on or currentReading=Otherdevice:temperature&amp;lt;/code&amp;gt;&lt;br /&gt;
*Perl-Code um einen Befehl auszuführen oder einen Wert zu setzen:&lt;br /&gt;
:Das ermöglicht sehr komplexe Anfragen.&lt;br /&gt;
:Der Code muss in geschwungenen Klammern sein.&lt;br /&gt;
:&amp;lt;code&amp;gt;{currentVal={ReadingsVal($DEVICE,&amp;quot;state&amp;quot;,0)}&amp;lt;/code&amp;gt;&lt;br /&gt;
:oder&lt;br /&gt;
:&amp;lt;code&amp;gt; cmd={fhem(&amp;quot;set $DEVICE dim $VALUE&amp;quot;)}&amp;lt;/code&amp;gt;&lt;br /&gt;
:$DEVICE ist das aktuelle FHEM-device. Der SetNumeric-Intent kann $VALUE für den Wert verwenden, der gesetzt werden soll.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== rhasspySpecials ===&lt;br /&gt;
Dieses Attribut wirkt ähnlich wie [[#rhasspyTweaks| rhasspyTweaks]], verändert allerdings nur jeweils das Verhalten des Geräts, bei dem es gesetzt ist. Auch dieses Attribut wird zeilenweise eingelesen, es können ein oder mehrere der folgenden Optionen gesetzt werden:&lt;br /&gt;
&lt;br /&gt;
==== group ====&lt;br /&gt;
::Wird dieser Schlüssel gesetzt, wird das Gerät bei Gruppenaktionen nicht direkt adressiert, sondern die hier angegebene Gruppe. Details hierzu sind in [[RHASSPY/Vertiefung#Timing-Aspekte| Vertiefung - Timing-Aspekte]] zu finden.&lt;br /&gt;
&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;attr lamp1 rhasspySpecials group:async_delay=100 prio=1 group=lights&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== numericValueMap ====&lt;br /&gt;
::Ermöglicht es, statt der allgemeinen Methode zum Umgang mit numerischen Werten einzelnen Werten spezielle Kommandos zuzuweisen. Dies kann z.B. hilfreich sein, um spezielle Positionen für Rollladengeräte anzusteuern.&lt;br /&gt;
::&#039;&#039;&#039;Beispiel&#039;&#039;&#039;:&lt;br /&gt;
::&amp;lt;code&amp;gt;attr blind1 rhasspySpecials numericValueMap:10=&#039;Event Slit&#039; 50=&#039;myPosition&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
::führt dazu, dass ein numerischer Wert von 10 (im {Value}-key) das Kommando &amp;lt;code&amp;gt;set blind1 Event Slit&amp;lt;/code&amp;gt; ausführt.&lt;br /&gt;
&lt;br /&gt;
==== venetianBlind ====&lt;br /&gt;
Siehe [[RHASSPY/Vertiefung#Jalousien|Vertiefung - Jalousien]]&lt;br /&gt;
&lt;br /&gt;
==== colorCommandMap ====&lt;br /&gt;
Sowie **colorTempMap** und **colorForceHue2rgb**&lt;br /&gt;
Siehe [[RHASSPY/Vertiefung#Farben|Vertiefung - Farben]]&lt;br /&gt;
&lt;br /&gt;
==== priority ====&lt;br /&gt;
Ermöglicht es, Rückfragen zu vermeiden, wenn mehrere Geräte für bestimmte Aktionen in Frage kommen. Siehe [[RHASSPY/Vertiefung#Einer_statt_alle|Einer statt alle]]&lt;br /&gt;
&lt;br /&gt;
==== confirm ====&lt;br /&gt;
Ist eine Möglichkeit, Geräte nur nach Rückfrage und Bestätigung zu schalten (ähnlich wie &#039;&#039;confirmIntents&#039;&#039; in &#039;&#039;rhasspyTweaks&#039;&#039;). Es können entweder einfach nur Intent-Namen angegeben werden, oder Paare von **Intent** und zugehöriger **response**:&lt;br /&gt;
 SetOnOff=&amp;quot;Soll $target wirklich $Value geschaltet werden&amp;quot; SetScene&lt;br /&gt;
&lt;br /&gt;
==== confirmValueMap ====&lt;br /&gt;
Kann spezielle Übersetzungen für $Value enthalten, z.B. für Rollladen-Geräte:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;confirm: SetOnOff=&amp;quot;wirklich $Value $target&amp;quot;&lt;br /&gt;
confirmValueMap: on=öffnen off=schließen&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== scenes ====&lt;br /&gt;
Wird bei der automatisierten Erfassung erkannt, dass ein Gerät das Setzen von Szenen unterstützt, werden die erkannten Szenen-Namen an Rhasspy übergeben. Da diese häufig technischer Natur sind, eignen sie sich nicht für eine Spracherkennung. Über diesen Schlüssel können daher sprechbare Namen für jede Szene vergeben werden, und/oder einzelne bzw. alle Szenen von der Erkennung ausgenommen werden. Der Kenner &#039;&#039;none&#039;&#039; löscht die Szene von der Liste der übermittelten Szenen, wird die Kombination &#039;&#039;all=none&#039;&#039; angegeben, wird dieses Gerät insgesamt von der Vorbereitung für den Intent &#039;&#039;SetScene&#039;&#039; ausgeschlossen.&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;attr lamp1 rhasspySpecials scenes:scene2=&amp;quot;Kino zu zweit&amp;quot; scene3=Musik scene1=none scene4=none&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Siehe auch [[RHASSPY/Vertiefung#echte_Szenen|Vertiefung - echte Szenen]]. &lt;br /&gt;
&lt;br /&gt;
=== Veraltete Attribute ===&lt;br /&gt;
In der Regel sollte es ausreichen, die zu steuernden Devices über die oben genannten Attribute zu konfigurieren. Es gibt jedoch noch zwei ältere Methoden. Um diese zu verwenden, muss zuerst jeweils ein entsprechendes User-Attribut im FHEM-Device, das damit gesteuert werden soll, angelegt werden.&lt;br /&gt;
&lt;br /&gt;
==== rhasspyChannels ====&lt;br /&gt;
Das Attribut wird vom Intent &#039;&#039;MediaControls&#039;&#039; verwendet. Es informiert den Intent darüber, welche (Medien-)Kanäle vorhanden sind und welcher FHEM-Befehl oder Perl-Code auszuführen ist, wenn auf diesen Kanal geschaltet werden soll.&lt;br /&gt;
&lt;br /&gt;
In diesem Attribut muss eine Zeile pro (Medien-)Kanal verwendet werden.&lt;br /&gt;
&lt;br /&gt;
Um rhasspyChannels zu verwenden, muss zuerst ein neues User-Attribut im FHEM-Device, das damit gesteuert werden soll, angelegt werden. Dafür kann z.B. dieses Beispiel verwendet werden: &amp;lt;code&amp;gt;attr &amp;lt;deviceName&amp;gt; userattr rhasspyChannels:textField-long&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr &amp;lt;device&amp;gt; rhasspyChannels orf eins=channel 201&lt;br /&gt;
orf zwei=channel 202&lt;br /&gt;
orf drei=channel 203&lt;br /&gt;
netflix=launchApp Netflix&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== rhasspyColors ====&lt;br /&gt;
Ältere Methode, die verwendet werden kann, um Lichtfarben zu wechseln. Es wird nachdrücklich empfohlen, die neueren Methoden über die (nummerisch zu übergebenden) allgemeinen Farbwerte und/oder ein &#039;&#039;colorCommandMap&#039;&#039; oder &#039;&#039;colorTempMap&#039;&#039; (siehe &#039;&#039;rhasspySpecials&#039;&#039;) zu konfigurieren!&lt;br /&gt;
&lt;br /&gt;
Um das Mapping zu verwenden, muss zuerst ein User-Attribut am zu steuernden Gerät angelegt werden. Z.B. &amp;lt;code&amp;gt;attr &amp;lt;deviceName&amp;gt; userattr rhasspyChannels:textField-long&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Eine Zeile pro Farbe&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr lamp1 rhasspyColors rot=rgb FF0000&lt;br /&gt;
grün=rgb 008000&lt;br /&gt;
blau=rgb 0000FF&lt;br /&gt;
gelb=rgb FFFF00&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Intents ==&lt;br /&gt;
Intents werden verwendet um FHEM zu sagen, was es nach einem erhaltenen Sprach-/Textkommand unternehmen soll. Dieses Modul stellt einige Intents bereit.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Wichtig&lt;br /&gt;
:*Bei Tags (&amp;lt;code&amp;gt;Value&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;, etc.) ist die Schreibweise sehr wichtig! Die sind case-sensitive. Bitte daher genau so schreiben, wie sie in dieser Dokumentation vorkommen.&lt;br /&gt;
:*RHASSPY erstellt bei einem &amp;lt;code&amp;gt;update slots&amp;lt;/code&amp;gt; auch Slots je nach Möglichkeiten der Geräte oder Gruppen. Unterstützt ein Gerät zum Beispiel den Intent &#039;&#039;GetNumeric&#039;&#039;, wird auch ein Slot &amp;lt;code&amp;gt;de.fhem.Device-GetNumeric&amp;lt;/code&amp;gt; erstellt. Ein Gerät, dass ein- und ausgeschalten werden kann, wird im Slot &amp;lt;code&amp;gt;de.fhem.Device-SetOnOff&amp;lt;/code&amp;gt; untergebracht. Ein einzelnes Gerät kann sich auch in mehreren Slots befinden. Um eine möglichst genaue Spracherkennung zu gewährleisten, ist &#039;&#039;&#039;empfohlen&#039;&#039;&#039;, diese &#039;&#039;&#039;spezifischen Slots&#039;&#039;&#039; - statt einfach nur &amp;lt;code&amp;gt;de.fhem.Device&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;de.fhem.Group&amp;lt;/code&amp;gt; - &#039;&#039;&#039;zu verwenden&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetOnOff ===&lt;br /&gt;
Intent um Geräte zwischen zwei Zuständen (ein/aus, auf/zu, start/stop) zu schalten.&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
SetOnOff:cmdOn=on,cmdOff=off&lt;br /&gt;
SetOnOff:cmdOn=on,cmdOff=off,response=&amp;quot;Sir yes Sir&amp;quot;&lt;br /&gt;
SetOnOff:cmdOn=on,cmdOff=off,response=&amp;quot;$DEVICE now [$DEVICE:state]&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Argumente:&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdOn&amp;lt;/code&amp;gt; Befehl um das Gerät einzuschalten. Siehe [[#Formatierung von Befehlen und Readings innerhalb eines rhasspyMappings|Formatierung von Befehlen und Readings innerhalb eines rhasspyMappings]].&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdOff&amp;lt;/code&amp;gt; Befehl um das Gerät auszuschalten. Siehe [[#Formatierung von Befehlen und Readings innerhalb eines rhasspyMappings|Formatierung von Befehlen und Readings innerhalb eines rhasspyMappings]].&lt;br /&gt;
&lt;br /&gt;
Optionale Argumente:&lt;br /&gt;
*&amp;lt;code&amp;gt;response&amp;lt;/code&amp;gt; Eine benutzerdefinierte Antwort auf den Befehl&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
schalten das licht ein&lt;br /&gt;
schließe den rollladen im schlafzimmer&lt;br /&gt;
starte die kaffeemaschine&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetOnOff]&lt;br /&gt;
(schalte|schalt|mache|mach|stelle|stell|starte) [den|die|das] $de.fhem.Device-SetOnOff{Device} [[(im|in dem|auf dem|in der|auf der)] $de.fhem.Room{Room}] (an|ein){Value:on}&lt;br /&gt;
(schalte|schalt|mache|mach|stelle|stell) [den|die|das] $de.fhem.Device-SetOnOff{Device} [[(im|in dem|auf dem|in der|auf der)] $de.fhem.Room{Room}] aus{Value:off}&lt;br /&gt;
(fahre|fahr) [den|die|das] $de.fhem.Device-blind{Device} [[(im|in dem|auf dem|in der|auf der)] $de.fhem.Room{Room}] ((hoch|auf){Value:on}|(zu|runter){Value:off})&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verpflichtende Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Value:on&amp;lt;/code&amp;gt; und/oder &amp;lt;code&amp;gt;Value:off&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetOnOffGroup ===&lt;br /&gt;
Intent um Gruppen von Geräte zwischen zwei Zuständen zu schalten.&lt;br /&gt;
&lt;br /&gt;
Dafür ist ein SetOnOff-Mapping benötigt und alle gewünschten Geräte müssen (ggf. u.A. auch) der gewählten Gruppe angehören (einzustellen über das Attribut &amp;lt;code&amp;gt;group&amp;lt;/code&amp;gt; bzw. &amp;lt;code&amp;gt;rhasspyGroup&amp;lt;/code&amp;gt;, oder allgemein kommend aus rhasspyTweaks - gdt2groups).&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
schalte die lampen in der küche aus&lt;br /&gt;
schließe alle rollläden im schlafzimmer&lt;br /&gt;
schalte sämtliche lampen aus&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetOnOffGroup]&lt;br /&gt;
\[(schalt|mach)] (die | alle | sämtliche ) $de.fhem.Group-SetOnOff{Group} [[in|im|in der|auf der] [( überall:global | $de.fhem.Room ){Room}] ein{Value:on}&lt;br /&gt;
\[(schalt|mach)] (die | alle | sämtliche ) $de.fhem.Group-SetOnOff{Group} [[in|im|in der|auf der] [( überall:global | $de.fhem.Room ){Room}] aus{Value:off}&lt;br /&gt;
(öffne{Value:on}|schließe{Value:off}) (alle | sämtliche ) $de.fhem.Group-blind{Group} [[in|im|in der|auf der] [( überall:global{Room:global} | $de.fhem.Room{Room} )] &lt;br /&gt;
(fahr|fahre|mach|mache) [den|die|das] $de.fhem.Group-blind{Group} [[(im|in dem|in der)] ( überall:global{Room:global} | $de.fhem.Room{Room} )] ( auf{Value:on} | hoch{Value:on} | zu{Value:off} | runter{Value:off} )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verpflichtende Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Value:on&amp;lt;/code&amp;gt; und/oder &amp;lt;code&amp;gt;Value:off&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Group&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== SetTimedOnOff ===&lt;br /&gt;
Intent um Geräte für eine bestimmte Zeitspanne in einen bestimmten Zustand zu versetzten.&lt;br /&gt;
&lt;br /&gt;
Device muss ein SetOnOff-Mapping haben und die {{Link2CmdRef|Anker=setExtensions|Lang=de|Label=SetExtentions}} unterstützen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
schalte das licht für eine minute und dreißig sekunden aus&lt;br /&gt;
schalte die musik im bad bis zwei uhr ein&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetTimedOnOff]&lt;br /&gt;
schalte $de.fhem.Device-SetOnOff{Device} [$de.fhem.Room{Room}] für ([(1..60){Hour!int} (stunde|stunden)] [und] [(1..60){Min!int} (minute|minuten)] [und] [(1..60){Sec!int} (sekunde|sekunden)]) (ein{Value:on}|aus{Value:off})&lt;br /&gt;
schalte $de.fhem.Device-SetOnOff{Device} [$de.fhem.Room{Room}] bis (0..24){Hourabs!int} [(1..60){Min!int}] (ein{Value:on}|aus{Value:off})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verpflichtende Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Value&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Hour&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Min&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Sec&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Hourabs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetTimedOnOffGroup ===&lt;br /&gt;
Intent um eine Gruppe von Geräten für eine bestimmte Zeit zu schalten.&lt;br /&gt;
&lt;br /&gt;
Devices müssen ein SetOnOff-Mapping haben, in einer Gruppe sein und die {{Link2CmdRef|Anker=setExtensions|Lang=de|Label=SetExtentions}} unterstützen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
schalte alle lichter in der küche für fünfzig sekunden ein&lt;br /&gt;
schalte alle licher bis zwei uhr ein&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetTimedOnOffGroup]&lt;br /&gt;
schalte $de.fhem.Group-SetOnOff{Group} [$de.fhem.Room{Room}] für ([(1..60){Hour!int} (stunde|stunden)] [und] [(1..60){Min!int} (minute|minuten)] [und] [(1..60){Sec!int} (sekunde|sekunden)]) (ein{Value:on}|aus{Value:off})&lt;br /&gt;
schalte $de.fhem.Group-SetOnOff{Group} [$de.fhem.Room{Room}] bis (0..24){Hourabs!int} [(1..60){Min!int}] (ein{Value:on}|aus{Value:off})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verpflichtende Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Value&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Group&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Hour&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Min&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Sec&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Hourabs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GetOnOff ===&lt;br /&gt;
Intent um den aktuellen Zustand eines Gerätes zu erfragen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
GetOnOff:currentVal=state,valueOff=closed&lt;br /&gt;
GetOnOff:currentVal=state,valueOn=on&lt;br /&gt;
GetOnOff:currentVal=pct,valueOff=0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Argumente:&lt;br /&gt;
Hinweis: nur &amp;lt;code&amp;gt;valueOn&amp;lt;/code&amp;gt; ODER &amp;lt;code&amp;gt;valueOff&amp;lt;/code&amp;gt; müssen gesetzt werden. Der jeweils andere Wert bekommt den anderen Status.&lt;br /&gt;
*&amp;lt;code&amp;gt;currentVal&amp;lt;/code&amp;gt; Reading aus dem der aktuelle Status hervorgeht&lt;br /&gt;
*&amp;lt;code&amp;gt;valueOff&amp;lt;/code&amp;gt; Wert, der den Zustand &#039;&#039;aus&#039;&#039; beschreibt&lt;br /&gt;
*&amp;lt;code&amp;gt;valueOn&amp;lt;/code&amp;gt; Wert, der den Zustand &#039;&#039;an&#039;&#039; beschreibt&lt;br /&gt;
&lt;br /&gt;
Optionale Argumente:&lt;br /&gt;
*&amp;lt;code&amp;gt;response&amp;lt;/code&amp;gt; Eine benutzerdefinierte Antwort auf den Befehl&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
ist das licht im bad ein&lt;br /&gt;
ist das fenster im wohnzimmer geöffnet&lt;br /&gt;
läuft die waschmaschine&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[en.fhem:GetOnOff]&lt;br /&gt;
ist $de.fhem.Device-GetOnOff{Device} [$de.fhem.Room{Room}] (ein|geöffnet){State:on}&lt;br /&gt;
ist $de.fhem.Device-GetOnOff{Device} [$de.fhem.Room{Room}] (aus|geschlossen){State:off}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zustände &#039;&#039;ein&#039;&#039; und &#039;&#039;aus&#039;&#039; sollten in unterschiedlichen Sentences sein und müssen &amp;lt;code&amp;gt;{State:on}&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;{State:off}&amp;lt;/code&amp;gt; beinhalten.&lt;br /&gt;
&lt;br /&gt;
Verpflichtende Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;State:on&amp;lt;/code&amp;gt; und/oder &amp;lt;code&amp;gt;State:off&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetNumeric ===&lt;br /&gt;
Intent, um Lampen zu dimmen, Rollladengeräte zu positionieren, Lautstärken oder Solltemperaturen zu ändern, usw.. &lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
SetNumeric:currentVal=pct,cmd=dim,minVal=0,maxVal=99,step=25,type=brightness&lt;br /&gt;
SetNumeric:currentVal=volume,cmd=volume,minVal=0,maxVal=99,step=10,type=volume&lt;br /&gt;
SetNumeric:currentVal=brightness,cmd=brightness,minVal=0,maxVal=255,map=percent,step=1,type=brightness&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Argumente:&lt;br /&gt;
*&amp;lt;code&amp;gt;currentVal&amp;lt;/code&amp;gt; Reading, in dem der aktuelle Wert zu finden ist (wird zwingend benötigt).&lt;br /&gt;
*&amp;lt;code&amp;gt;part&amp;lt;/code&amp;gt; Kann genutzt werden, um den Wert aus **currentVal** in mehrere Teile zu zerlegen (getrennt wird am Leerzeichen). Z.B. wenn currentVal 23 C ist, wird **part=0** **23** ergeben. Optionaler Parameter.&lt;br /&gt;
*&amp;lt;code&amp;gt;cmd&amp;lt;/code&amp;gt; Das **Set**-Kommando des Geräts, das in Folge des Sprachkommandos ausgeführt werden soll. (Notwendiger Parameter).&lt;br /&gt;
*&amp;lt;code&amp;gt;minVal&amp;lt;/code&amp;gt; Niedrigster zugelassener Wert, optional.&lt;br /&gt;
*&amp;lt;code&amp;gt;maxVal&amp;lt;/code&amp;gt; Höchster zugelassener Wert, optional.&lt;br /&gt;
*&amp;lt;code&amp;gt;step&amp;lt;/code&amp;gt; Schrittweite für relative Änderungen wie &amp;lt;code&amp;gt;mach lauter&amp;lt;/code&amp;gt;. Optional. Default: 10.&lt;br /&gt;
*&amp;lt;code&amp;gt;map&amp;lt;/code&amp;gt; Derzeit wird ausschließlich die Angabe **percent** ausgewertet. Optionaler Parameter, der bewirkt, dass alle Angaben als Prozentwert (zwischen minVal und maxVal) interpretiert werden und entsprechend gerechnet wird. So wird z.B. eine Leuchte mit **minVal=0** und **maxVal=255** beim Befehl &amp;quot;stelle das Licht auf 50&amp;quot; dies so verstehen, als wäre die Anweisung &amp;quot;stelle das Licht auf 50 Prozent&amp;quot; gewesen. Das Licht wird daher auf 127 gestellt, und nicht auf (absolut) 50.&lt;br /&gt;
*&amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; Zur Unterscheidung, falls mehrere SetNumeric-Intents für das Gerät möglich sind. Empfohlener Parameter.&lt;br /&gt;
&lt;br /&gt;
Gut zu wissen:&lt;br /&gt;
Um Kommandos wie **lauter** oder **leiser** ohne Angabe eines Gerätes ausführen zu können, muss RHASSPY zunächst ermitteln, welches Gerät gerade überhaupt etwas wiedergibt ist. Daher nutzt es die GetOnOff-Mappings, um festzustellen, welches Gerät vom **type=volume** überhaupt angeschaltet ist. Dabei wird wie üblich zunächst im aktuellen rhasspyRoom gesucht, bevor die Suche außerhalb fortgesetzt wird.&lt;br /&gt;
Setzt man also Mappings manuell, ist es ratsam, auch ein **GetOnOff**-Mapping zu setzen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zulässige Typen sind:&lt;br /&gt;
*&amp;lt;code&amp;gt;brightness&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;setTarget&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;temperature&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;volume&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
Stelle das Licht auf 30 Prozent&lt;br /&gt;
Mach das Radio leiser&lt;br /&gt;
Stell die Temperatur im Wohnzimmer 2 Grad wärmer&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
(Beachte: Wenn wie hier im Beispiel reele Zahlen (mit Komma) ermöglicht werden sollen (&amp;quot;acht Komma fünf&amp;quot;), wird ein [[#Custom Converter für reelle Zahlen| Custom Converter für reelle Zahlen]] benötigt)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetNumeric]&lt;br /&gt;
den=(den|die|das)&lt;br /&gt;
cmdmulti=(schalte|schalt|mache|mach|stelle|stell)&lt;br /&gt;
rooms=([(im|in dem|auf dem|in der|auf der)] $de.fhem.Room{Room})&lt;br /&gt;
&amp;lt;cmdmulti&amp;gt; [&amp;lt;den&amp;gt;] $de.fhem.Device-SetNumeric{Device} auf (0..100){Value!int} [Prozent{Unit:percent}]&lt;br /&gt;
\[&amp;lt;cmdmulti&amp;gt;] [die Lautstärke [an|am]] [dem|&amp;lt;den&amp;gt;] $de.fhem.Device-media{Device} [&amp;lt;rooms&amp;gt;] [um] [(0..10){Value!float}] [dezibel{Unit:decibel}|Prozent{Unit:percent}] ( lauter:volUp | leiser:volDown ){Change}&lt;br /&gt;
&amp;lt;cmdmulti&amp;gt; [die Lautstärke [an|am]] [dem|&amp;lt;den&amp;gt;] [$de.fhem.Device-media{Device}] [&amp;lt;rooms&amp;gt;] [um] [(0..10){Value!float}] [dezibel{Unit:decibel}|Prozent{Unit:percent}] ( lauter:volUp | leiser:volDown ){Change}&lt;br /&gt;
&amp;lt;cmdmulti&amp;gt; [&amp;lt;den&amp;gt;] $de.fhem.Device-thermostat{Device} [&amp;lt;rooms&amp;gt;] [um] [(0..10){Value!int}] [Grad{Unit.degree}] ( wärmer:tempUp | kälter:tempDown ){Change}&lt;br /&gt;
&amp;lt;cmdmulti&amp;gt; [&amp;lt;den&amp;gt;] $de.fhem.Device-light{Device} [&amp;lt;rooms&amp;gt;] [um] [(0..30 [Komma:. 1..9]){Value!customFloat}] [Prozent{Unit:percent}] ( heller:lightUp | dunkler:lightDown){Change}&lt;br /&gt;
&amp;lt;cmdmulti&amp;gt; [&amp;lt;den&amp;gt;] ( $de.fhem.Device-light | $de.fhem.Device-media |$de.fhem.Device-blind){Device}  [&amp;lt;rooms&amp;gt;] auf [(0..30 [Komma:. 1..9]){Value!customFloat}]&lt;br /&gt;
\[deutlich{Factor:2}] ( mehr{Change:lightUp} | weniger{Change:lightDown} ) $de.fhem.Device-light{Device} [&amp;lt;de.fhem:SetOnOff.rooms&amp;gt;]&lt;br /&gt;
( halte | stoppe | stop ) [&amp;lt;den&amp;gt;] $de.fhem.Device-blind{Device} [&amp;lt;de.fhem:SetOnOff.rooms&amp;gt;] [an] {Change:cmdStop}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Derzeit werden folgende Typen für das Feld &amp;lt;code&amp;gt;{Change}&amp;lt;/code&amp;gt; ausgewertet:&lt;br /&gt;
*&amp;lt;code&amp;gt;tempUp&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;tempDown&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;volUp&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;volDown&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;lightUp&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;lightDown&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;setUp&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;setDown&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notwendig sind:&lt;br /&gt;
*&amp;lt;code&amp;gt;Change&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Type&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Value&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Change&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Unit&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Factor&amp;lt;/code&amp;gt; Dieser Wert wird mit der Standard-Schrittweite (&amp;lt;code&amp;gt;step&amp;lt;/code&amp;gt; im Mapping) multipliziert&lt;br /&gt;
&lt;br /&gt;
=== SetNumericGroup ===&lt;br /&gt;
Intent, um Lampen zu dimmen, Rollladengeräte zu positionieren, Lautstärken oder Solltemperaturen zu ändern, usw.. Die Funktionsweise entspricht dabei dem des Intents &#039;&#039;SetNumeric&#039;&#039;, wobei eben statt eines einzelnen Devices eben ein oder mehrere Geräte über ihren Gruppennamen angesprochen werden. Statt des optionalen Tags &amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt; ist daher der Tag &amp;lt;code&amp;gt;Group&amp;lt;/code&amp;gt; zu übergeben.&lt;br /&gt;
Aus der Adressierung mehrerer Geräte ergeben sich einige Besonderheiten, die in der [[RHASSPY/Vertiefung]], dort speziell auch im Punkt [[RHASSPY/Vertiefung#Beispiel_SetOnOffGroup|Beispiel SetOnOffGroup]] näher erläutert sind. Wesentliche zu beachtende Aspekte sind:&lt;br /&gt;
* Vermeidung von Funk-Überschneidungen (&#039;&#039;Specials&#039;&#039; &#039;&#039;partOf&#039;&#039; und &#039;&#039;async_delay&#039;&#039;)&lt;br /&gt;
* Begrenzung der Gruppenzugehörigkeit durch die Raumzugehörigkeit (und die Aufhebung dieser Beschränkung durch die Übergabe des speziellen Raums &#039;&#039;global&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
=== GetNumeric ===&lt;br /&gt;
Intent, mit dem man Werte erfragen kann, wie z.B. die aktuelle Temperatur, Helligkeit, Lautstärke, ...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
GetNumeric:currentVal=temperature,part=1,type=temperature&lt;br /&gt;
GetNumeric:currentVal=pct,map=percent,minVal=0,maxVal=100,type=brightness&lt;br /&gt;
GetNumeric:currentVal=volume,type=volume&lt;br /&gt;
GetNumeric:currentVal=humidity,part=0,type=humidity&lt;br /&gt;
GetNumeric:currentVal=batteryPercent,type=battery&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Argumente:&lt;br /&gt;
*&amp;lt;code&amp;gt;currentVal&amp;lt;/code&amp;gt; Das Reading, das den abzufragenden Wert enthält&lt;br /&gt;
*&amp;lt;code&amp;gt;part&amp;lt;/code&amp;gt; Teile aus currentVal ableiten, indem am Leerzeichen getrennt wird. Ist &#039;&#039;currentVal&#039;&#039; beispielsweise &#039;&#039;23 C&#039;&#039;, entspricht &#039;&#039;part=1&#039;&#039; dem Wert &#039;&#039;23&#039;&#039;&lt;br /&gt;
*&amp;lt;code&amp;gt;map&amp;lt;/code&amp;gt; Die Funktionswiese entspricht dem &#039;&#039;SetNumeric&#039;&#039; Intent. Wandelt den vorhandenen Wert in eine Prozent-Angabe um.&lt;br /&gt;
*&amp;lt;code&amp;gt;minVal&amp;lt;/code&amp;gt; Niedrigster zulässiger Wert (nur benötigt, wenn &#039;&#039;map&#039;&#039; angegeben ist).&lt;br /&gt;
*&amp;lt;code&amp;gt;maxVal&amp;lt;/code&amp;gt; Höchster zulässiger Wert  (nur benötigt, wenn &#039;&#039;map&#039;&#039; angegeben ist).&lt;br /&gt;
*&amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; Dient der Unterscheidung zwischen mehreren GetNumeric-Anfragemöglichkeiten für dasselbe Gerät (auch relevant für SetNumeric-Anweisungen).&lt;br /&gt;
&lt;br /&gt;
Mögliche Abfragetypen:&lt;br /&gt;
*&amp;lt;code&amp;gt;humidity&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;battery&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;brightness&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;desired-temp&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;setTarget&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;soilMoisture&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;temperature&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;volume&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;waterLevel&amp;lt;/code&amp;gt;&lt;br /&gt;
Aus dem Abfragetypen ergibt sich die von RHASSPY ausgewählte Antwort.&lt;br /&gt;
&lt;br /&gt;
Beispiel Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
what is the temperature in the living room&lt;br /&gt;
how bright is the floor lamp&lt;br /&gt;
what is the volume of the tv&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
[en.fhem:GetNumeric]&lt;br /&gt;
#actual temperature&lt;br /&gt;
(what is|how high is) the temperature{Type:temperature} [$de.fhem.Device-GetNumeric{Device}] [$de.fhem.Room{Room}]&lt;br /&gt;
&lt;br /&gt;
#desired-temperature&lt;br /&gt;
\[what is the|how high is the] (desired temperature){Type:desired-temp} [$de.fhem.Device-GetNumeric{Device}] [$de.fhem.Room{Room}]&lt;br /&gt;
&lt;br /&gt;
#volume&lt;br /&gt;
(what is the|how high is the) volume{Type:volume} $de.fhem.Device-GetNumeric{Device} [$de.fhem.Room{Room}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Type&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional tags&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== GetState ===&lt;br /&gt;
Intent to get specific information of a device. The respone can be defined.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
GetState:response=&amp;quot;Temperature is [$DEVICE:temp] degree at [Thermo:hum] percent humidity&amp;quot;&lt;br /&gt;
GetState:response={my $value=ReadingsVal(&amp;quot;$DEVICE&amp;quot;,&amp;quot;brightness&amp;quot;,&amp;quot;&amp;quot;); return &amp;quot;Brightness is $value&amp;quot;;}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Options:&lt;br /&gt;
*&amp;lt;code&amp;gt;response&amp;lt;/code&amp;gt; Text for the response Rhassyp will give.&lt;br /&gt;
:To use values from FHEM use format [Device:Reading].&lt;br /&gt;
:A comma within the response has to be escaped (\, instead of ,).&lt;br /&gt;
:Or you can use Perl-code enclosed in curley brackets to define the response.&lt;br /&gt;
:Mixing text and Perl-code is not supported.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
How is the state of the thermostat in the kitchen&lt;br /&gt;
state light in livingroom&lt;br /&gt;
state washer&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:GetState]&lt;br /&gt;
\[how is the] (state) $de.fhem.Device{Device} [$de.fhem.Room{Room}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== MediaControls ===&lt;br /&gt;
Intent to control media devices&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mapping:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
MediaControls:cmdPlay=play,cmdPause=pause,cmdStop=stop,cmdBack=previous,cmdFwd=next&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Options:&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdPlay&amp;lt;/code&amp;gt; Play command of the device. See chapter Formatting Commands and Readings inside a rhasspyMapping.&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdPause&amp;lt;/code&amp;gt; Command to pause the device.&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdStop&amp;lt;/code&amp;gt; Command to stop the device.&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdFwd&amp;lt;/code&amp;gt; Command to skip to the next track/channel/etc.&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdBack&amp;lt;/code&amp;gt; Command to skip to the previous track/channel/etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note on issuing a voice-command without a room-name:&lt;br /&gt;
As described in the SetNumeric-Intent, it is recommended to define a GetOnOff-Mapping to use the MediaControls-Intent without a room name.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
skip to next track on the radio&lt;br /&gt;
pause&lt;br /&gt;
skip video on the dvd player&lt;br /&gt;
stop playback&lt;br /&gt;
next&lt;br /&gt;
previous&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:MediaControls]&lt;br /&gt;
(start){Command:cmdPlay} the playback [$de.fhem.Device-MediaControls{Device}]&lt;br /&gt;
(stop){Command:cmdStop} the playback [$de.fhem.Device-MediaControls{Device}]&lt;br /&gt;
(pause){Command:cmdPause} the playback [$de.fhem.Device-MediaControls{Device}]&lt;br /&gt;
(next){Command:Fwd} (song|title) [$de.fhem.Device-MediaControls{Device}]&lt;br /&gt;
(previous){Command:Back} (song|title) [$de.fhem.Device-MediaControls{Device}] [$de.fhem.Room{Room}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Command&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== MediaChannels ===&lt;br /&gt;
Intent to change radio-/tv channels, favorites, playlists, lightscenes, ...&lt;br /&gt;
&lt;br /&gt;
Instead of using the attribute rhasspyMapping, this intent is configured with an own attribute [[#rhasspyChannels]] in the respective device. Reason is the multiple-line-configuration.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
SWR3=favorite s_w_r_3&lt;br /&gt;
SWR1=favorite s_w_r_1&lt;br /&gt;
ARD=channel 204&lt;br /&gt;
Netflix=launchApp Netflix&lt;br /&gt;
Leselicht=set lightSceneWz scene Leselicht&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Notice on using the commands without a device name:&lt;br /&gt;
To start playback on a device without specifying the device name in the voice command, the module needs to know, which device should be used. Therefor it searches the attribute rhasspyChannels for suitable one. Devices in the actual or spoken room are preferred.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
play CNN on the radio in my office&lt;br /&gt;
switch to HBO&lt;br /&gt;
change channel on radio to BBC news&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[en.fhem:MediaChannels]&lt;br /&gt;
\[(play|switch to|change to)] ($de.fhem.MediaChannels){Channel} [($de.fhem.Device){Device}] [($de.fhem.Room){Room}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Channel&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetColor ===&lt;br /&gt;
Intent to change light colors&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Because of the multi-line settings, instead of configuring this intent with the attribute rhasspyMapping, a separate user-attribute [[#rhasspyColors]] is used.&lt;br /&gt;
&lt;br /&gt;
The content of the rhasspyColors uses the following format:&lt;br /&gt;
&amp;lt;code&amp;gt;Colorname=cmd&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Settings:&lt;br /&gt;
*&amp;lt;code&amp;gt;Colorname&amp;lt;/code&amp;gt; The name of the color you want to use in a voice-command&lt;br /&gt;
*&amp;lt;code&amp;gt;cmd&amp;lt;/code&amp;gt; The FHEM-command&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
red=rgb FF0000&lt;br /&gt;
green=rgb 00FF00&lt;br /&gt;
blue=rgb 0000FF&lt;br /&gt;
white=ct 3000&lt;br /&gt;
warm white=ct 2700&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
change light to green&lt;br /&gt;
lightstrip blue&lt;br /&gt;
color the light in the sleeping room white&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[en.fhem:SetColor]&lt;br /&gt;
\[change|color] $de.fhem.Device{Device} [$de.fhem.Room{Room}] $de.fhem.Color{Color}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Color&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional tags&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetColorGroup ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetScene ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GetTime ===&lt;br /&gt;
Intent um die Uhrzeit zu erfragen.&lt;br /&gt;
&lt;br /&gt;
Es werden keine Konfigurationen in FHEM benötigt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
wie spät ist es?&lt;br /&gt;
sag mir die uhrzeit&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:GetTime]&lt;br /&gt;
wie spät [ist es]&lt;br /&gt;
sag mir die uhrzeit&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GetDate ===&lt;br /&gt;
Intent um das aktuelle Datum zu erfragen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Keine FHEM Einstellungen nötig.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Satz:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
welcher tag ist heute&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:GetDate]&lt;br /&gt;
welcher tag ist heute&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetTimer ===&lt;br /&gt;
Intent to create a timer/countdown/alarm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This intent creates an AT-command in FHEM with the given time and - currently - speaks the sentences &amp;quot;timer expired&amp;quot; when it has expired.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
No FHEM-settings needed&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
Set timer in bedroom to five minutes&lt;br /&gt;
Set countdown in the kitchen to two hours&lt;br /&gt;
set timer to five and a half hours&lt;br /&gt;
set alarm to 5 o&#039; clock&lt;br /&gt;
set timer to 3 hours and 20 minutes&lt;br /&gt;
set timer to 1 hour, 30 minutes and 15 seconds&lt;br /&gt;
stop the timer in bedroom&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentence:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetTimer]&lt;br /&gt;
labels=(alarm|teetimer|countdown|timer)&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in) [((1..60){Hour!int} (hour|hours))] [and] [((1..60){Min!int} (minute|minutes))] [and] [((1..60){Sec!int} (second|seconds))]&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in) (1..60){Hour!int} and (a quarter{Min:15}|a half{Min:30}|three quarters{Min:45}) (hour|hours)&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in) (1..60){Min!int} and (a quarter{Sec:15}|a half{Sec:30}|three quarters{Sec:45}) (minute|minutes)&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in) ((the fourth){Min:15}|(half a){Min:30}|(three fourth){Min:45}) (hour)&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in) ((the fourth){Min:15}|(half a){Min:30}|(three fourth){Min:45}) (minute)&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in|at) (1..24){Hourabs!int} [(1..60){Min!int}] o clock&lt;br /&gt;
&lt;br /&gt;
(cancel|remove|stop|delete){CancelTimer} [&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags to set a timer:&lt;br /&gt;
*&amp;lt;code&amp;gt;Label&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Hour&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Hourabs&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Min&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Sec&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags to cancel a timer:&lt;br /&gt;
*&amp;lt;code&amp;gt;Label&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
rhasspyTweaks for Timer:&lt;br /&gt;
*&amp;lt;code&amp;gt;[[#attr-rhasspytweaks-timerlimits|timerLimits]]&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;[[#attr-rhasspytweaks-timersounds|timerSounds]]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetMute ===&lt;br /&gt;
Intent to disable/enable the processing of intents on a specific siteId. Rhasspy will still listen to the wakeword but will not process any intents.&lt;br /&gt;
&lt;br /&gt;
This intents creates a Reading &amp;lt;code&amp;gt;mute_siteId&amp;lt;/code&amp;gt; for every siteId it get&#039;s a voice-command from.&lt;br /&gt;
&lt;br /&gt;
No FHEM-settings needed&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
good night&lt;br /&gt;
be quiet&lt;br /&gt;
good morning&lt;br /&gt;
make noise&lt;br /&gt;
start listening&lt;br /&gt;
stop listening&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel für Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetMute]&lt;br /&gt;
(good night|be quiet){Value:on}&lt;br /&gt;
(good morning|make noise){Value:off}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hinweis: Die Felder &amp;lt;code&amp;gt;{Value:on}&amp;lt;/code&amp;gt; bzw. &amp;lt;code&amp;gt;{Value:off}&amp;lt;/code&amp;gt; sind verpflichtend und &#039;&#039;case sensitive&#039;&#039;, der Wert &#039;&#039;on&#039;&#039; bzw. &#039;&#039;off&#039;&#039; ist in Englisch anzugeben!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ConfirmAction ===&lt;br /&gt;
Dies ist - wie die folgenden Intents &#039;&#039;CancelAction&#039;&#039; und &#039;&#039;Choice&#039;&#039; (bzw. die überholten Varianten &#039;&#039;ChoiceRoom&#039;&#039; und &#039;&#039;ChoiceDevice&#039;&#039;) auch - ein Intent, der im Rahmen von Dialogen benötigt wird. Siehe dazu auch [[RHASSPY/Vertiefung#Dialoge|Vertiefung - Dialoge]].&lt;br /&gt;
Um eine Aktion tatsächlich auszuführen, ist als Rückgabe zwingend &amp;lt;code&amp;gt;{Mode}&amp;lt;/code&amp;gt; mit dem Wert &#039;&#039;OK&#039;&#039; erforderlich, alles andere wird so behandelt, als wäre der Intent &#039;&#039;CancelAction&#039;&#039; ausgewählt worden, was zur Beendigung des Dialogs ohne Aktion führt.&lt;br /&gt;
&lt;br /&gt;
=== CancelAction ===&lt;br /&gt;
Siehe &#039;&#039;ConfirmAction&#039;&#039;. Dieser Intent muss nicht zwingend existieren, es kann auch ein unpassender Rückgabewert in &#039;&#039;ConfirmAction&#039;&#039; angegeben werden, um die Abbruch-Routinen für Dialoge zu starten.&lt;br /&gt;
&lt;br /&gt;
=== Choice ===&lt;br /&gt;
Siehe &#039;&#039;ConfirmAction&#039;&#039;. Dient im Rahmen von Dialogen der Auswahl von einem oder mehreren der folgenden Elemente:&lt;br /&gt;
&amp;lt;code&amp;gt;{Device}&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;{Room}&amp;lt;/code&amp;gt; und/oder &amp;lt;code&amp;gt;{Scene}&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Beispiel für Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:Choice]&lt;br /&gt;
den=(den|die|das)&lt;br /&gt;
choose= ( nimm [bitte] | [bitte] nimm | ich hätte gerne | [ich] (wähle|nehme) )&lt;br /&gt;
&lt;br /&gt;
&amp;lt;choose&amp;gt; [ &amp;lt;den&amp;gt; [( Gerät | $de.fhem.Aliases{Device} )] ] ( aus ( dem | der ) | im | den | die ) $de.fhem.MainRooms{Room}&lt;br /&gt;
&amp;lt;choose&amp;gt; [ &amp;lt;den&amp;gt; ] $de.fhem.Aliases{Device} [ ( aus ( dem | der ) | im | den | die ) $de.fhem.MainRooms{Room} ]&lt;br /&gt;
&amp;lt;choose&amp;gt; [ ( die Szene | den Modus ) ] $de.fhem.Scenes [Modus] [ [( am | vom )] $de.fhem.Aliases{Device} ] [( aus ( dem | der ) | im | den | die ) $de.fhem.MainRooms{Room} ] [bitte]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== ChoiceRoom ====&lt;br /&gt;
Veralteter Intent. Diente im Rahmen von Dialogen der Auswahl eines Raums, wird heute pauschal nach &#039;&#039;Choice&#039;&#039; umgeleitet und sollte nicht mehr verwendet werden!&lt;br /&gt;
&lt;br /&gt;
==== ChoiceDevice ====&lt;br /&gt;
Veralteter Intent. Diente im Rahmen von Dialogen der Auswahl eines Gerätes, wird heute pauschal nach &#039;&#039;Choice&#039;&#039; umgeleitet und sollte nicht mehr verwendet werden!&lt;br /&gt;
&lt;br /&gt;
=== ReSpeak ===&lt;br /&gt;
Wiederholt den letzten Satz, den Rhasspy gesprochen hat. Um genauer zu sein: Spricht den Inhalt des FHEM Readings &amp;lt;code&amp;gt;voiceResponse&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Keine Einstellungen in FHEM benötigt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
was hast du gesagt&lt;br /&gt;
kannst du das wiederholen&lt;br /&gt;
ich habe dich nicht verstanden&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:ReSpeak]&lt;br /&gt;
was hast du gesagt&lt;br /&gt;
kannst du das [bitte] wiederholen&lt;br /&gt;
ich habe dich nicht verstanden&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Eigene Intents erstellen ==&lt;br /&gt;
Es ist auch möglich, eigene Intents zu erstellen, sollten die hier vorgestellten nicht reichen. Dafür gibt es zwei Wege: Für kleinere Intents können die Möglichkeiten von FHEMs [[99_myUtils_anlegen|99_myUtils.pm]] genutzt werden. Aufwendigere Intents können in jeweils eigenen Dateien abgelegt werden, die dann von RHASSPY ausgelesen werden.&lt;br /&gt;
=== Intents in 99_myUtils.pm ===&lt;br /&gt;
&lt;br /&gt;
Hier ein (veraltetes, siehe oben) Beispiel, mit dem die letzte &#039;&#039;voice response&#039;&#039; wiederholt werden kann.&lt;br /&gt;
&lt;br /&gt;
Ergänze deine 99_myUtils.pm mit folgender Funktion:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub Respeak(){&lt;br /&gt;
  #Credits to JensS&lt;br /&gt;
  my $name = &amp;quot;Rhasspy&amp;quot;; #Replace &amp;quot;Rhasspy&amp;quot; with the name of your RHASSPY-Device&lt;br /&gt;
  my $response = ReadingsVal($name,&amp;quot;voiceResponse&amp;quot;,&amp;quot;Ich kann mich leider nicht erinnern&amp;quot;);&lt;br /&gt;
  return $response;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ergänze im Attribut &#039;&#039;rhasspyIntents&#039;&#039; folgende Zeile (je Intent muss eine eigene Zeile verwendet werden):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
Respeak=Respeak()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ergänze einen neuen Intent in deinen &#039;&#039;sentence.ini&#039;&#039; an der Rhasspy base:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:Respeak]&lt;br /&gt;
was hast du gesagt&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Intents in eigenen Dateien ===&lt;br /&gt;
Beispiele: https://github.com/fhem/fhem-rhasspy/blob/main/FHEM/99_RHASSPY_Utils_Demo.pm&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: Raumwechsel ====&lt;br /&gt;
Erforderlichen Code in das Modulverzeichnis holen und laden: &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;{ Svn_GetFile(&#039;contrib/RHASSPY/99_RHASSPY_Utils_siteId2room.pm&#039;, &#039;FHEM/99_RHASSPY_Utils_siteId2room.pm&#039;,sub(){ RHASSPY_Utils_siteId2room_Initialize() }) }&amp;lt;/syntaxhighlight&amp;gt;Ergänze im Attribut &#039;&#039;rhasspyIntents&#039;&#039; folgende Zeile (je Intent muss eine eigene Zeile verwendet werden):&lt;br /&gt;
&amp;lt;syntaxhighlight  lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
siteId2room=RHASSPY::siteId2room::siteId2room(NAME,DATA)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Ergänze einen neuen Intent in deinen &#039;&#039;sentence.ini&#039;&#039; an der Rhasspy base:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:siteId2room]&lt;br /&gt;
( Ortswechsel  | begib dich ) ( ins | in den ) $de.fhem.Room{Room}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tipps &amp;amp; Tricks ==&lt;br /&gt;
===Custom Converter für reelle Zahlen===&lt;br /&gt;
{{Randnotiz|RNTyp=g|RNText=RHASSPY enthält für &amp;lt;code&amp;gt;{Value}&amp;lt;/code&amp;gt; nunmehr auch einen Konverter, der Leerzeichen aus Zahlenwerten entfernt. Enthält dieses Datenfeld bei der Übergabe aus Rhasspy z.B. &amp;lt;code&amp;gt;- 10 .5&amp;lt;/code&amp;gt;, wird dies automatisch in &amp;lt;code&amp;gt;-10.5&amp;lt;/code&amp;gt; umgewandelt.}}&lt;br /&gt;
Rhasspy kann (derzeit) keine gesprochenen reellen Nummern (z.B. 22,5) als Nummer erkennen. Stattdessen interpretiert es die Zahl als zwei Nummern und einen Punkt.&lt;br /&gt;
&lt;br /&gt;
Um reelle Nummern richtig zu verwenden, muss ein [https://rhasspy.readthedocs.io/en/latest/training/#converters Custom Converter] erstellt und in der sentences.ini verwendet werden.&lt;br /&gt;
&lt;br /&gt;
So ein Konverter kann erstellt werden, in dem unter &amp;lt;code&amp;gt;&amp;lt;profile&amp;gt;/converters&amp;lt;/code&amp;gt; ein neues File mit beliebigem Namen angelegt wird. Der Name muss aber dann auch genau so als Converter in der sentences.ini verwendet werden. Anschließend muss die Datei noch ausführbar gemacht werden.&lt;br /&gt;
&lt;br /&gt;
Z.B.:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
touch .config/rhasspy/profile/en/converters/customFloat&lt;br /&gt;
chmod +x .config/rhasspy/profile/en/converters/customFloat&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Folgender Beispiel-Code kann danach in die Datei geschrieben werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python3&lt;br /&gt;
import sys&lt;br /&gt;
import json&lt;br /&gt;
&lt;br /&gt;
# von Rhasspy als JSON übergebene/n Wert/e einlesen&lt;br /&gt;
args = json.load(sys.stdin)&lt;br /&gt;
&lt;br /&gt;
# wenn im deserialisierten JSON nur ein Wert ist, wird der als Ergebnis genommen&lt;br /&gt;
# sind mehrere Werte vorhanden (z.B. 22,.,5), werden die zu einem einzelnen String zusammen gesetzt&lt;br /&gt;
if type(args) == int:&lt;br /&gt;
    num = args&lt;br /&gt;
else:&lt;br /&gt;
    num = &amp;quot;&amp;quot;.join(str(s).strip() for s in args)&lt;br /&gt;
&lt;br /&gt;
# Ergebnis wird an Rhasspy übergeben&lt;br /&gt;
print(num)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nach einem Neustart von Rhasspy kann dieser Converter dann verwendet werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem.SetNumeric]&lt;br /&gt;
stelle die heizung auf (0..30 [komma:. 0..99]){Value!customFloat}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Rhasspy speaks actual state of device after switching it===&lt;br /&gt;
JensS wrote a short script to let Rhasspy speak the actual state of a FHEM-device after switching it with a voice-command.&lt;br /&gt;
Add the following to your 99_myUtils.pm&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub ResponseOnOff($){&lt;br /&gt;
  my ($dev) = @_;&lt;br /&gt;
  my $room;&lt;br /&gt;
  my $state = lc(ReadingsVal($dev,&amp;quot;state&amp;quot;,&amp;quot;in unknown state&amp;quot;));&lt;br /&gt;
  my $name = (split(/,/,AttrVal($dev,&amp;quot;rhasspyName&amp;quot;,&amp;quot;error&amp;quot;)))[0];&lt;br /&gt;
  if (AttrVal($dev,&amp;quot;rhasspyRoom&amp;quot;,&amp;quot;&amp;quot;)){$room = &amp;quot; in &amp;quot;.(split(/,/,AttrVal($dev,&amp;quot;rhasspyRoom&amp;quot;,&amp;quot;&amp;quot;)))[0]};&lt;br /&gt;
  $state=~s/.*on/turned on/;&lt;br /&gt;
  $state=~s/.*off/turned off/;&lt;br /&gt;
  return &amp;quot;Ok - &amp;quot;.$name.$room.&amp;quot; is now &amp;quot;.$state&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
and add a response to the SetOnOff-Mapping of a device&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
SetOnOff:cmdOn=on,cmdOff=off,response={ResponseOnOff($DEVICE)}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [https://rhasspy.readthedocs.io/en/latest/ offizielle Rhasspy Doku-Seite]&lt;br /&gt;
* [https://community.rhasspy.org/ Offizielles Rhasspy Forum]&lt;br /&gt;
* [https://github.com/fhem/fhem-rhasspy fhem-rhasspy Modul auf GitHub]&lt;br /&gt;
* [https://github.com/Romkabouter/ESP32-Rhasspy-Satellite ESP32-basierte Hardware als Satelliten]&lt;br /&gt;
* [https://github.com/razzo04/rhasspy-mobile-app App für Android-Satelliten]&lt;br /&gt;
* [https://www.youtube.com/watch?v=sWVl0ZoXZEo Video zu sentences.ini]&lt;br /&gt;
[[Kategorie:Sprachsteuerung]]&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=RHASSPY&amp;diff=37536</id>
		<title>RHASSPY</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=RHASSPY&amp;diff=37536"/>
		<updated>2022-09-07T10:05:25Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: Hinweis auf GitHub entfernt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
Diese Seite beschreibt die Konfiguration und Verwendung des Moduls 10_RHASSPY.pm. &lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=Anbindung von FHEM an den Rhasspy Sprachassistenten&lt;br /&gt;
|ModType=contrib&lt;br /&gt;
|ModCmdRef=RHASSPY&lt;br /&gt;
|ModForumArea=Frontends/Sprachsteuerung&lt;br /&gt;
|ModFTopic=119447&lt;br /&gt;
|ModTechName=10_RHASSPY.pm&lt;br /&gt;
|ModOwner=Beta-User ({{Link2FU|9229|Forum}}/[[Benutzer Diskussion:Beta-User|Wiki]]), drhirn ({{Link2FU|15727|Forum}}/[[Benutzer Diskussion:Drhirn|Wiki]])&lt;br /&gt;
}}&lt;br /&gt;
[[File:Rhasspy_fhem.png|thumb|right|Schematische Darstellung von Rhasspy und FHEM/RHASSPY]]&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
[https://github.com/rhasspy/rhasspy Rhasspy] ist eine Open Source Server-Lösung für Spracherkennung und Sprachsteuerung, welche auf einem RaspBerry Pi oder einem anderen Debian-basierten Serversystem lauffähig ist. Es handelt sich dabei um eine Sammlung von Programmen (=Skripten in der Python-Sprechweise), die unter einer einheitlichen und sehr  flexiblen Benutzungsoberfläche zusammengefasst sind. Die Besonderheit an Rhasspy ist, dass es nach der Installation komplett offline betrieben werden kann. Es werden also keine Daten an einen Server im Internet geschickt, und für den Betrieb nur für FHEM werden nur moderate Hardwareanforderungen gestellt - ein aktueller Raspberry Pi ab Modell 3B+ sollte in der Regel genügen.&lt;br /&gt;
&lt;br /&gt;
Die Anbindung weiterer Räume ist über sogenannte &amp;quot;Satelliten&amp;quot; möglich. Dies kann z.B. ein Pi Zero mit Mikro und Lautsprecher sein, ein ESP32 mit entsprechender Hardware oder ein Mobiltelefon mit Android und der entsprechenden App.&lt;br /&gt;
&lt;br /&gt;
Rhasspy besteht aus vielen unterschiedlichen Modulen (Hot-Word Erkennung, Text-to-Speech, Speech-to-Text, Intent Erkennung, etc.). Alle diese Module kommunizieren miteinander über das [[MQTT|MQTT]]-Protokoll.&lt;br /&gt;
&lt;br /&gt;
Das Modul [[RHASSPY]] prüft Teile des MQTT-Traffics, konvertiert diese JSON-Nachrichten in FHEM-Befehle und sendet Nachrichten zurück an Rhasspy um z.B. Antworten über Text-to-Speech auszugeben.&lt;br /&gt;
&lt;br /&gt;
RHASSPY verwendet das Modul 00_MQTT2_CLIENT.pm um Nachrichten zu empfangen und zu senden. Daher ist es notwendig, eine Instanz dieses Moduls als FHEM-Device zu erstellen, bevor RHASSPY verwendet werden kann.&lt;br /&gt;
&lt;br /&gt;
Hervorgegangen ist RHASSPY aus dem Snips-Modul, nachdem Snips an Sonos verkauft und anschließend eingestellt wurde. Danke also an Thyraz, der die grundlegenden Arbeiten erledigt hat!&lt;br /&gt;
&lt;br /&gt;
=== Konventionen ===&lt;br /&gt;
{{Hinweis| In diesem Artikel und der CommandRef werden folgende Schreibweisen verwendet:&lt;br /&gt;
* &#039;&#039;&#039;[[RHASSPY]]&#039;&#039;&#039; bezieht sich auf das FHEM-Modul&lt;br /&gt;
* &#039;&#039;&#039;rhasspy&#039;&#039;&#039; bezieht sich auf das das FHEM-Device&lt;br /&gt;
* &#039;&#039;&#039;Rhasspy&#039;&#039;&#039; bezeichnet die (zentrale) Serverinstallation}}&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|Dialoge werden in RHASSPY verwaltet wie [https://rhasspy.readthedocs.io/en/latest/reference/#dialogue-manager hier] beschrieben. Dialoge werden also nicht funktionieren, sobald für das Dialogue-Management etwas anderes als &#039;&#039;RHASSPY&#039;&#039; eingestellt ist}}&lt;br /&gt;
&lt;br /&gt;
=== Erste Schritte ===&lt;br /&gt;
Die Installation und Erstinbetriebnahme von Rhasspy wird in einer Schnellstart-Anleitung erklärt: [[RHASSPY/Schnellstart]] Diese Anleitung sollte auch befolgt werden, wenn man sich sehr gut mit FHEM auskennt. Wer dies erfolgreich absolviert hat, kann gleich zu Abschnitt [[#Set-Befehle_.28SET.29|Set-Befehle (SET)]] weiterspringen, und/oder die [[RHASSPY/Vertiefung|Vertiefung]] durcharbeiten.&lt;br /&gt;
&lt;br /&gt;
=== Details zur Verwaltung des RHASSPY Moduls ===&lt;br /&gt;
Das Modul ist derzeit nicht in der &amp;quot;offiziellen&amp;quot; FHEM Distribution enthalten und muss daher manuell installiert werden. Dafür gibt es zwei Möglichkeiten.&lt;br /&gt;
&lt;br /&gt;
*Im Subversion Repository, kurz SVN von FHEM ist die jeweils aktuelle &amp;quot;stable&amp;quot; Version des Moduls im &#039;&#039;contrib&#039;&#039;-Zweig zu finden. Diese kann mit folgendem Befehl, der im FHEM Befehls-Eingabefeld einzugeben ist, heruntergeladen werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;{ Svn_GetFile(&#039;contrib/RHASSPY/10_RHASSPY.pm&#039;, &#039;FHEM/10_RHASSPY.pm&#039;) }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Genauere Informationen zu dieser Vorgangsweise finden sich unter [[Update#Einzelne_Dateien_aus_dem_SVN_holen]]. Nach Installation des Moduls muss FHEM neu gestartet werden.&lt;br /&gt;
&lt;br /&gt;
Nach Installation des Moduls muss FHEM neu gestartet werden.&lt;br /&gt;
&lt;br /&gt;
== Einrichtung MQTT2_CLIENT ==&lt;br /&gt;
Rhasspy kommuniziert hauptsächlich über das [[MQTT]]-Protokoll. Und zwar sowohl Rhasspy-intern, wie auch mit FHEM. Da dies auch für die übertragene Sprache und Audio-Dateien gilt und es daher zu sehr viel MQTT-Verkehr kommt, sollte der Rhasspy-interne MQTT-Server verwendet werden. Daher ist die Einrichtung eines [[MQTT2_CLIENT]]-Devices notwendig, um die für FHEM relevanten Daten zu beziehen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zuerst muss ein MQTT2_CLIENT Device erstellt werden, welches sich mit dem MQTT-Server (Mosquitto) von Rhasspy verbindet:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;define &amp;lt;deviceName&amp;gt; MQTT2_CLIENT &amp;lt;ip-oder-hostname-des-mqtt-servers&amp;gt;:&amp;lt;port&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anschließend wird die &#039;&#039;clientOrder&#039;&#039; gesetzt, um die richtige Benachrichtigungsreihenfolge einzustellen. Wird das MQTT2_CLIENT Device nur für RHASSPY verwendet, reicht hier die Angabe &amp;lt;code&amp;gt;RHASSPY&amp;lt;/code&amp;gt;. Ansonsten müssen noch alle anderen Devices (z.B. &amp;lt;code&amp;gt;MQTT_GENERIC_BRIDGE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;MQTT2_DEVICE&amp;lt;/code&amp;gt;) angegeben werden.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;attr &amp;lt;deviceName&amp;gt; clientOrder RHASSPY [device2] [device3]&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Um die Topics einzuschränken, die das Device abonniert, müssen diese angegeben werden. Wird der MQTT-Server nur für RHASSPY verwendet, reicht die Angabe &amp;lt;code&amp;gt;setByTheProgram&amp;lt;/code&amp;gt;. Ansonsten müssen alle für RHASSPY notwendigen Topics eingefügt werden.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;attr &amp;lt;deviceName&amp;gt; subscriptions setByTheProgram&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
bzw.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;attr &amp;lt;deviceName&amp;gt; subscriptions hermes/intent/+ hermes/dialogueManager/sessionStarted hermes/dialogueManager/sessionEnded hermes/nlu/intentNotRecognized hermes/hotword/+/detected hermes/hotword/toggleOn     hermes/hotword/toggleOff hermes/tts/say&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Beispiele&lt;br /&gt;
* Rhasspy-interner MQTT-Server wird mit seinem Standard-Port verwendet. Rhasspy läuft auf der selben Maschine wie FHEM. MQTT2_CLIENT wird nur für RHASSPY verwendet.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod rhasspyMQTT2 MQTT2_CLIENT localhost:12183&lt;br /&gt;
attr rhasspyMQTT2 clientOrder RHASSPY&lt;br /&gt;
attr rhasspyMQTT2 subscriptions setByTheProgram&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* Rhasspy läuft auf einem eigenen Server und verwendet einen externen MQTT Server mit eigener Port-Einstellung. MQTT2_CLIENT wird für RHASSPY, aber auch MQTT_GENERIC_BRIDGE und MQTT2_DEVICE verwendet.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod rhasspyMQTT2 MQTT2_CLIENT 192.168.1.122:1884&lt;br /&gt;
attr rhasspyMQTT2 clientOrder RHASSPY MQTT_GENERIC_BRIDGE MQTT2_DEVICE&lt;br /&gt;
attr rhasspyMQTT2 subscriptions hermes/intent/+ hermes/dialogueManager/sessionStarted hermes/dialogueManager/sessionEnded hermes/nlu/intentNotRecognized hermes/hotword/+/detected hermes/hotword/toggleOn hermes/hotword/toggleOff hermes/tts/say [zusätzliche Subscriptions für andere MQTT-Module]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Definition von RHASSPY (DEF)==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;define &amp;lt;name&amp;gt; RHASSPY &amp;lt;baseUrl&amp;gt; &amp;lt;devspec&amp;gt; &amp;lt;defaultRoom&amp;gt; &amp;lt;siteId&amp;gt; &amp;lt;language&amp;gt; &amp;lt;fhemId&amp;gt; &amp;lt;prefix&amp;gt; &amp;lt;useGenericAttrs&amp;gt; &amp;lt;handleHotword&amp;gt; &amp;lt;autoTraining&amp;gt; &amp;lt;encoding&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
{{Randnotiz|RNTyp=Info|RNText=RHASSPY verwendet sehr oft &amp;lt;parseParams&amp;gt;. Nicht nur im Define, sondern z.B. auch, um Attribut-Werte auszuwerten. Es sollten also alle Parameter im Define in der Form key=value angegeben werden.).}}{{Randnotiz|RNTyp=Info|RNText=RHASSPY führt jede Menge Daten aus unterschiedlichen Quellen zusammen um seine Funktion erfüllen zu können. Die endgültige Daten-Struktur, die RHASSPY verwendet, kann mittels des [[List|list]]-Kommandos angezeigt werden. Es wird empfohlen, sich diese Daten-Struktur auf jeden Fall anzusehen. Vor allem dann, wenn etwas nicht wie gewünscht funktioniert.}}&lt;br /&gt;
Alle Parameter sind &#039;&#039;&#039;optional&#039;&#039;&#039;. Die meisten werden im Normalfall gar nicht benötigt (z.B. &amp;lt;code&amp;gt;fhemId&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;prefix&amp;lt;/code&amp;gt;), oder können auf den automatisch vergebenen Werten belassen werden. Sollten sie aber verwendet und später geändert werden, kann es zu unvorhergesehenem Verhalten kommen. Speziell beim Einstieg in das Thema RHASSPY sollten nicht mehr, als die ersten drei verwendet werden. Ausgenommen eventuell noch &amp;lt;code&amp;gt;language&amp;lt;/code&amp;gt;, möchte man eine andere Sprache als Englisch oder Deutsch verwenden und &amp;lt;code&amp;gt;siteId&amp;lt;/code&amp;gt;, das für Tests und andere Text-Eingabemöglichkeiten wichtig ist.&lt;br /&gt;
&lt;br /&gt;
=== baseUrl ===&lt;br /&gt;
Die URL zum Rhasspy-Webservice. Sollten eine Base und mehrere Satelliten verwendet werden, die URL zur Base. Bitte sicherstellen, dass die Adresse richtig ist (IP und Port)! Default ist &amp;lt;code&amp;gt;baseUrl=http://127.0.0.1:12101&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== devspec ===&lt;br /&gt;
&#039;&#039;devspec&#039;&#039; der Geräte, die mit Rhasspy gesteuert werden sollen. Wenn der &#039;&#039;genericDeviceType&#039;&#039;-Support aktiviert ist, ist der Default &amp;lt;code&amp;gt;devspec=genericDeviceType=.+&amp;lt;/code&amp;gt;, sonst wird &amp;lt;code&amp;gt;devspec=room=Rhasspy&amp;lt;/code&amp;gt; verwendet. Ohne ein passendes Match in der devspec wird kein Gerät mit dem Modul interagieren, egal, ob sonst irgendwelche RHASSPY-spezifischen Attribute beim Gerät gesetzt sind. Genauere Informationen, wie z.B. eine Liste von Geräten oder Kombinationen aus Geräten und Räumen (z.B. &amp;lt;code&amp;gt;devspec=room=livingroom,room=bathroom,bedroomlamp&amp;lt;/code&amp;gt;) verwendet werden können, finden sich in der [https://commandref.fhem.de/commandref.html#devspec CommandRef].&lt;br /&gt;
&lt;br /&gt;
=== defaultRoom ===&lt;br /&gt;
Der Name des Standard-Raumes, der verwendet wird, wenn im Sprachkommando kein Raum enthalten ist und auch kein passender für das Device gefunden werden kann. Default ist &amp;lt;code&amp;gt;defaultRoom=default&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== language ===&lt;br /&gt;
Sprache, in der mit Rhasspy gesprochen wird. Der Standard-Wert hängt vom &#039;&#039;global&#039;&#039;-Device ab. Dieser ist standardmäßig &amp;lt;code&amp;gt;language=en&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== fhemId ===&lt;br /&gt;
Wird verwendet um auf MQTT-Seite zwischen mehreren Installationen des RHASSPY-Moduls zu unterscheiden. Ist auch ein Teil des Topic-Trees, auf den die jeweilige RHASSPY-Instanz hört. Default ist &amp;lt;code&amp;gt;fhemId=fhem&amp;lt;/code&amp;gt;.&lt;br /&gt;
{{Hinweis|Dialoge werden in RHASSPY verwaltet wie [https://rhasspy.readthedocs.io/en/latest/reference/#dialogue-manager hier] beschrieben. Dialoge werden also nicht funktionieren, sobald für das Dialogue-Management etwas anderes als &#039;&#039;RHASSPY&#039;&#039; eingestellt ist}}&lt;br /&gt;
&lt;br /&gt;
=== siteId ===&lt;br /&gt;
Wenn bestimmte Funktionen genutzt werden sollen, muss die RHASSPY-Instanz für Rhasspy als &#039;&#039;Satellit&#039;&#039; eigenständig angesprochen werden können. Hierzu muss dann eine eindeutige Kennung vergeben werden, und diese ist insbesondere dann auch in der für die Intent Recognition zuständigen Rhasspy-Komponente als Satellit anzugeben. Wird diese nicht explizit gesetzt, wird diese aus dem &#039;&#039;language&#039;&#039;-Kürzel und der &#039;&#039;fhemId&#039;&#039; zusammengesetzt.&lt;br /&gt;
{{Hinweis|Für die Funktionalitäten &#039;&#039;test_sentence&#039;&#039;, &#039;&#039;test_file&#039;&#039;, &#039;&#039;msgDialog&#039;&#039; und &#039;&#039;AMAD.*&#039;&#039; ist es &#039;&#039;&#039;zwingend erforderlich&#039;&#039;&#039;, die siteId in der Rhasspy-Intent-Recognition-Komponente einzutragen!}}&lt;br /&gt;
&lt;br /&gt;
=== prefix ===&lt;br /&gt;
Wird verwendet um auf FHEM-Seite zwischen mehreren Installationen des RHASSPY-Moduls zu unterscheiden. Praktisch, wenn man mehrere Instanzen von RHASSPY auf einer FHEM Installation laufen hat und z.B. verschiedene Bezeichner für Gruppen und Räume haben möchte (z.B. unterschiedliche Sprachen). Default ist &amp;lt;code&amp;gt;prefix=rhasspy&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== useGenericAttrs ===&lt;br /&gt;
Üblicherweise verwendet RHASSPY - wie auch einige andere FHEM Module für Sprachassistenten - das Attribut &#039;&#039;genericDeviceType&#039;&#039; um Schaltmöglichkeiten von Geräten automatisch zu erkennen. Dieser Parameter fügt das Attribut &#039;&#039;genericDeviceType&#039;&#039; zur globalen Attributliste hinzu. Der Wert 0 verhindert dieses hinzufügen und die automatisierte Eigenschaftenerkennung. Default ist &amp;lt;code&amp;gt;useGenericAttrs=1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== encoding ===&lt;br /&gt;
Sollte es Probleme mit Umlauten geben, kann das Character-Encoding geändert werden. Default ist &amp;lt;code&amp;gt;encoding=utf8&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== handleHotword ===&lt;br /&gt;
Triggert das Reading &#039;&#039;hotword&#039;&#039;, wenn ein Hotword erkannt wurde (und erstellt das Reading, falls noch nicht vorhanden). Weitere Informationen dazu stehen beim Attribut [[#rhasspyHotwords|&#039;&#039;rhasspyHotwords&#039;&#039;]]. Default ist &amp;lt;code&amp;gt;handleHotword=0&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== autoTraining ===&lt;br /&gt;
Da Änderungen auf der FHEM-Seite (z.B. bei Änderungen der rhasspyNames) auch Rhasspy bekannt gemacht werden müssen und anschließend ein Training erfolgen muss, damit Rhasspy diese Änderugnen ebenfalls berücksichtigt, übergibt RHASSPY derartige Änderungen nach Ablauf von einer Minute seit der letzten Änderung an Rhasspy und initiiert dann ein Training. Setzt man diesen Schlüssel auf &amp;quot;0&amp;quot;, wird diese Funktion deaktiviert, alle anderen numerischen Werte werden als Änderung dieses Timeouts (in Sekunden) interpretiert&lt;br /&gt;
Default ist &amp;lt;code&amp;gt;autoTraining=60&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|Nach dem Definieren eines RHASSPY-Modules sollte das IODev manuell gesetzt werden um ein automatische IO-Zuweisung zu verhindern. Z.B. &amp;lt;code&amp;gt;attr &amp;lt;deviceName&amp;gt; IODev &amp;lt;m2client&amp;gt;&amp;lt;/code&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
;Beispiele:&lt;br /&gt;
Läuft Rhasspy auf der selben Maschine wie FHEM, die Sprache ist im &#039;&#039;global&#039;&#039;-Device bereits richtig eingestellt und der Standardraum entspricht der siteId, die in Rhasspy vergeben wurde:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;define Rhasspy RHASSPY&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Läuft Rhasspy auf einem anderen System wie FHEM, der Standard-Raum enspricht nicht dem, was Rhasspy liefert, die Sprache soll auch anders sein und es sollen sowohl Geräte mit vorhandenem &#039;&#039;genericDeviceType&#039;&#039; Attribut, als auch die Geräte &#039;&#039;device_a1&#039;&#039; und &#039;&#039;device_xy&#039;&#039; gesteuert werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;define Rhasspy RHASSPY baseUrl=http://192.168.1.210:12101 defaultRoom=&amp;quot;Büro Lisa&amp;quot; language=de devspec=genericDeviceType=.+,device_a1,device_xy handleHotword=1&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Set-Befehle (SET) ==&lt;br /&gt;
&lt;br /&gt;
=== customSlot ===&lt;br /&gt;
Erstellt einen neuen - oder überschreibt einen alten - Slot in Rhasspy&lt;br /&gt;
* &amp;lt;code&amp;gt;slotname&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;slotdata&amp;lt;/code&amp;gt; sind verpflichtend&lt;br /&gt;
* &amp;lt;code&amp;gt;overwrite&amp;lt;/code&amp;gt; ist optional. Default ist &amp;lt;code&amp;gt;overwrite=true&amp;lt;/code&amp;gt;. Das Setzen eines anderes Wertes verhindert das Überschreiben einen bereits bestehenden Slot mit gleichem Namen.&lt;br /&gt;
* &amp;lt;code&amp;gt;training&amp;lt;/code&amp;gt; ist optional. Default ist &amp;lt;code&amp;gt;training=true&amp;lt;/code&amp;gt;. Das Setzen eines anderen Wertes verhindert ein Training von Rhasspy nach dem Speichern des Slots.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiele:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; customSlot mySlot a,b,c overwrite training&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; customSlot slotname=mySlot slotdata=a,b,c overwrite=false&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== fetchSiteIds ===&lt;br /&gt;
Liest alle in Rhasspy vorhandenen siteIDs aus und speichert sie im Reading &#039;&#039;siteIds&#039;&#039;. Wird z.B. verwendet, um festzustellen, auf welchem Satelliten der User über das Ende eines Timers benachrichtigt werden soll.&lt;br /&gt;
Muss immer ausgeführt werden, wenn eine neue siteId in Rhasspy hinzugefügt wird (neuer Satellit z.B.).&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; fetchSiteIds&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== play ===&lt;br /&gt;
Sendet eine WAV Datei an Rhasspy, &amp;lt;code&amp;gt;siteId&amp;lt;/code&amp;gt; und &amp;lt;path&amp;gt; sind verpflichtend!&lt;br /&gt;
&lt;br /&gt;
Optional kann die Anzahl der Wiederholungen (Default: 1) und die Dauer der Pause zwischen den jeweiligen Wiederholungen (Default: 15) angeben werden.&lt;br /&gt;
&#039;&#039;Beispiele:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; play siteId=&amp;quot;default&amp;quot; path=&amp;quot;/opt/fhem/test.wav&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; play siteId=&amp;quot;default&amp;quot; path=&amp;quot;./test.wav&amp;quot; repeats=3 wait=20&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== speak ===&lt;br /&gt;
Sendet einen Text an das TTS-Sytem, welches ihn dann als Sprache ausgibt.&lt;br /&gt;
&lt;br /&gt;
Beide Argumente &amp;lt;code&amp;gt;siteId&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;text&amp;lt;/code&amp;gt; sind verpflichtend!&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; speak siteId=&amp;quot;wohnzimmer&amp;quot; text=&amp;quot;This is a test&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== textCommand ===&lt;br /&gt;
Sendet ein Text-Kommando an Rhasspy.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; textCommand schalte das licht ein&amp;lt;/code&amp;gt;&lt;br /&gt;
Mangels siteId erfolgt hier keine Rückmeldung zum ausgeführten Kommando.&lt;br /&gt;
&lt;br /&gt;
=== trainRhasspy ===&lt;br /&gt;
Startet das Training von Rhasspy.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; trainRhasspy&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== update ===&lt;br /&gt;
&#039;&#039;update&#039;&#039; kennt diverse Abstufungen:&lt;br /&gt;
&lt;br /&gt;
==== update devicemap ====&lt;br /&gt;
Wenn an der Konfiguration von RHASSPY oder an den von ihm gesteuerten Geräten etwas geändert wurde, muss dieser Befehl ausgeführt werden, um die Datenstruktur von RHASSPY zu aktualisieren, Rhasspy von den Änderungen zu informieren (Slots z.B.) und ein Training zu starten. Wenn [[#autoTraining|autoTraining]] nicht deaktiviert wurde, erfolgt dies bei Änderungen an relevanten Attributen nach einiger Zeit zwar automatisch, über diesen Befehl kann aber sichergestellt werden, dass dies unmittelbar und ohne Vergleich mit Alt-Daten erfolgt.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update devicemap&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== update devicemap_only ====&lt;br /&gt;
Aktualisiert die Datenstruktur von RHASSPY. Es werden weder Slots in Rhasspy geändert, noch das Training gestartet.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update devicemap_only&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== update slots ====&lt;br /&gt;
Aktualisiert (bzw. erstellt) alle Slots in Rhasspy mit den aktuellen Geräten, Räumen, usw.&lt;br /&gt;
&lt;br /&gt;
Erstellte/Aktualisierte Slots sind z.B.:&lt;br /&gt;
* de.fhem.AllKeywords  (Hinweis: Die ersten beiden Teile &#039;&#039;de&#039;&#039; und &#039;&#039;fhem&#039;&#039; hängen von der DEF des RHASSPY-Devices ab)&lt;br /&gt;
* de.fhem.Device&lt;br /&gt;
* de.fhem.Device-&#039;&#039;genericDeviceType&#039;&#039;&lt;br /&gt;
* de.fhem.Device-&#039;&#039;Intent&#039;&#039;&lt;br /&gt;
* de.fhem.Group&lt;br /&gt;
* de.fhem.Room&lt;br /&gt;
* de.fhem.MediaChannels&lt;br /&gt;
* de.fhem.Color&lt;br /&gt;
* de.fhem.NumericType&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update slots&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== slots_no_training ====&lt;br /&gt;
Wie &amp;lt;code&amp;gt;slots&amp;lt;/code&amp;gt;, aber ohne Training nach dem Update.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update slots_no_training&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== update language ====&lt;br /&gt;
Liest das das Sprach-File (&#039;&#039;languageFile&#039;&#039;) neu ein.&lt;br /&gt;
&lt;br /&gt;
Muss immer ausgeführt werden, wenn in diesem File oder dem Attribut &#039;&#039;languageFile&#039;&#039; etwas geändert wurde!&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update language&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== update intent_filter ====&lt;br /&gt;
Setzt die Intent Filter, die vom Rhasspy Dialogue Manger verwendet werden zurück. Details dazu bei [[#intentFilter|intentFilter]] im &#039;&#039;rhasspyTweaks&#039;&#039;-Attribut.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update intent_filter&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== update all ====&lt;br /&gt;
Aktualisiert die Devicemap und das languageFile&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update all&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== volume ===&lt;br /&gt;
Stellt die Lautstärke der gewünschten siteId auf einen Wert zwischen 0 and 1 (float). Beide Argumente &amp;lt;code&amp;gt;siteId&amp;lt;/code&amp;gt; &amp;lt;code&amp;gt;volume&amp;lt;/code&amp;gt; sind verpflichtend.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; siteId=&amp;quot;default&amp;quot; volume=&amp;quot;0.5&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|Bitte nicht vergessen, dass nach jeder Änderung an RHASSPY oder an einem von RHASSPY gesteuerten Gerät ein &amp;lt;code&amp;gt;update devicemap&amp;lt;/code&amp;gt; ausgeführt werden sollte, v.a. wenn das [[#autoTraining|autoTraining]] in der DEF deaktiviert wurde!}}&lt;br /&gt;
&lt;br /&gt;
== Get-Befehle (GET) ==&lt;br /&gt;
=== export_mapping ===&lt;br /&gt;
Liefert für das angegebene Device ein &amp;quot;klassisches&amp;quot; &#039;&#039;rhasspyMapping&#039;&#039;, das dann als Basis für eigene Weiterentwicklungen genutzt werden kann. Funktioniert ggf. nicht in allen Fällen (z.B. bei &#039;&#039;SetScene&#039;&#039; und dem Szenen-Format für &#039;&#039;HUEBridge&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
=== test_file ===&lt;br /&gt;
Anzugeben ist der Dateiname (einschl. Pfad)&lt;br /&gt;
&lt;br /&gt;
Die Datei wird zeilenweise eingelesen und an die Rhasspy-Komponente für die Intent-Erkennung übergeben. Das Ergebnis der Analyse wird in eine File geschrieben, die auf &#039;_result.txt&#039; endet. &#039;&#039;stop&#039;&#039; als Dateiname unterbricht einen laufenden Test. Die ggf. abgeleiteten Kommandos werden nicht ausgeführt, FHEM wird während eines laufende Tests auch keine anderen Kommandos von der Rhasspy-Seite her annehmen.&lt;br /&gt;
Für diese Funktion ist es zwingend erforderlich, dass die &#039;&#039;siteId&#039;&#039; der RHASSPY-Instanz bei der Intent-Recognition-Komponente in Rhasspy als Satellit angegeben wurde.&lt;br /&gt;
&lt;br /&gt;
=== test_sentence ===&lt;br /&gt;
Es kann ein beliebiger einzelner Satz eingegeben werden, die Ausgabe erfolgt dann in einem eigenen Dialogfeld, ansonsten gilt sinngemäß dasselbe wie bei &#039;&#039;test_file&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==Attribute (ATTR)==&lt;br /&gt;
Um RHASSPY zum Laufen zu bringen, müssen unterschiedliche Attribute gesetzt werden. Dabei gibt es&lt;br /&gt;
*Attribute, die im RHASSPY-Device selbst gesetzt werden müssen und&lt;br /&gt;
*Attribute, die in den Devices gesetzt werden müssen, die von RHASSPY kontrolliert werden sollen.&lt;br /&gt;
&lt;br /&gt;
Letztere werden im Abschnitt [[#FHEM-Devices für die Verwendung mit Rhasspy konfigurieren|FHEM-Devices für die Verwendung mit Rhasspy konfigurieren]] behandelt.&lt;br /&gt;
&lt;br /&gt;
In diesem Abschnitt werden die Attribute behandelt, die auf das RHASSPY-Device selbst wirken.&lt;br /&gt;
&lt;br /&gt;
===IODev===&lt;br /&gt;
Das MQTT2_CLIENT Device, welches die MQTT-Nachrichten für RHASSPY liefert.&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;code&amp;gt;attr &amp;lt;rhasspyDevice&amp;gt; IODev rhasspyMQTT2&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===forceNEXT===&lt;br /&gt;
Wenn dieses Attribut auf 1 gesetzt ist, leitet RHASSPY eingehende MQTT-Nachrichten an andere MQTT2-IO-Client Module wie MQTT2_DEVICE weiter, auch wenn das Topic zu einem von RHASSPY abonnierten passt.&lt;br /&gt;
Standardmäßig werden diese Nachrichten nicht weitergeleitet um eine bessere Kompatibilität mit dem &#039;&#039;autocreate&#039;&#039;-Feature des MQTT2_DEVICE sicher zu stellen.&lt;br /&gt;
Siehe dazu das {{Link2CmdRef|Anker=MQTT2_CLIENT-attr-clientOrder|Lang=en|Label=clientOrder}}-Attribut in der CommandRef zum MQTT2_CLIENT Device.&lt;br /&gt;
Das Setzen dieses Attributs in einer RHASSPY-Instanz kann auch andere eventuell vorhandene RHASSPY-Instanzen beinflussen.&lt;br /&gt;
Default ist &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;code&amp;gt;attr &amp;lt;rhasspyDevice&amp;gt; forceNext 1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===languageFile===&lt;br /&gt;
{{Randnotiz|RNTyp=g|RNText=Bei Nutzung von configDB wird diese Datei aus der Datenbank gelesen.}}&lt;br /&gt;
Pfad zur Sprach-Datei&lt;br /&gt;
Ist dieses Argument nicht gesetzt, wird ein Standard-Set an englischen Sätzen für die Sprachantworten verwendet.&lt;br /&gt;
Die Datei selbst muss ein gültiges JSON-File sein, dass sich nach der Struktur aus den englischen Standardwerten richtet.&lt;br /&gt;
Eine deutsche Beispiel-Datei ist im [https://svn.fhem.de/trac/browser/trunk/fhem/contrib/RHASSPY/rhasspy-de.cfg SVN] vorhanden. Man kann aber einfach ein Dump der englischen Struktur machen (replace RHASSPY by your device&#039;s name: &amp;lt;code&amp;gt;{toJSON($defs{RHASSPY}-&amp;gt;{helper}{lng})}&amp;lt;/code&amp;gt;, das Ergebnis dann bearbeiten und es als eigenes languageFile verwenden.&lt;br /&gt;
Im Standard-Set sind auch einige Variablen enthalten. Auch die können im eigenen File verwendet werden.&lt;br /&gt;
&#039;&#039;languageFile&#039;&#039; erlaubt auch eine Kombination aus vorhandenen und eigenen Sätzen. Dazu können die eigenen Sätzen einfach im Sub-Tree &#039;&#039;user&#039;&#039; abgelegt werden.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039; (vorausgesetzt, die Sprach-Datei ist im selben Verzeichnis wie fhem.pl):&lt;br /&gt;
&amp;lt;code&amp;gt;attr &amp;lt;rhasspyDevice&amp;gt; languageFile ./rhasspy-de.cfg&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====response====&lt;br /&gt;
{{Hinweis|Die Verwendung dieses Attributs ist nicht mehr empfohlen. Bessere Alternative ist die Sprach-Datei.}}&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Mit diesem Attribut können eigene Standardantworten definiert werden.&lt;br /&gt;
Mögliche Schlüsselwörter sind &amp;lt;code&amp;gt;DefaultError&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;NoActiveMediaDevice&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;DefaultConfirmation&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;DefaultError=&lt;br /&gt;
DefaultConfirmation=Klaro, mach ich&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===rhasspyHotwords===&lt;br /&gt;
Kann verwendet werden, um benutzerdefinierte Aktionen auszuführen, sobald ein bestimmtes Hotword erkannt wurde. Dazu sind keine speziellen Konfigurationsschritte in anderen FHEM Devices notwendig.&lt;br /&gt;
Wenn mittels Attribut oder DEF aktiviert, wird ein Reading &#039;&#039;hotword&#039;&#039; erstellt und mit dem erkannten Hotword und der siteId befüllt um ein Event-Handling zu ermöglichen.&lt;br /&gt;
{{Hinweis|Da bei den hotword messages für alle Teilnehmer dieselbe Topic-Structur verwendet wird, kann RHASSPY nicht unterscheiden, ob eine solche für diese Instanz relevant ist. Falls entsprechende Unterscheidungen gemacht werden sollen, muss dies vom User entsprechend konfiguriert werden, z.B. indem die subscriptions (am MQTT2_CLIENT) eingeschränkt werden oder indem nur jeweils andere hotword-Einträge für jede RHASSPY-Instanz genutzt werden.}}&lt;br /&gt;
Ein Hotword pro Zeile, Syntax entweder einfach oder erweitert&lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;&#039;Beispiele:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;bumblebee_linux = set amplifier2 mute on&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;porcupine_linux = livingroom=&amp;quot;set amplifier mute on&amp;quot; default={Log3($DEVICE,3,&amp;quot;device $DEVICE - room $ROOM - value $VALUE&amp;quot;)}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im ersten Beispiel wird der Befehl immer ausgeführt, wenn das Hotword &#039;&#039;bumblebee_linux&#039;&#039; erkannt wurde.&lt;br /&gt;
Im zweiten nur, wenn das Hotword &#039;&#039;porcupine_linux&#039;&#039; in der siteId &#039;&#039;livingroom&#039;&#039; erkannt wurde.&lt;br /&gt;
$DEVICE wird ausgewertet als der Name des RHASSPY Devices, $ROOM als siteId und $VALUE als das verwendete Hotword.&lt;br /&gt;
&lt;br /&gt;
===rhasspyIntents===&lt;br /&gt;
Definiert einen benutzerdefinierten Intent.&lt;br /&gt;
Ein Intent pro Zeile.&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;attr &amp;lt;rhasspyDevice&amp;gt; rhasspyIntents SetCustomIntentsTest=SetCustomIntentsTest(siteId,Type)&amp;lt;/code&amp;gt;&lt;br /&gt;
in Kombination mit folgendem myUtils-Code&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub SetCustomIntentsTest {&lt;br /&gt;
my $room = shift;&lt;br /&gt;
my $type = shift;&lt;br /&gt;
Log3(&#039;rhasspy&#039;,3 , &amp;quot;RHASSPY: Room $room, Type $type&amp;quot;);&lt;br /&gt;
return &amp;quot;RHASSPY: Room $room, Type $type&amp;quot;;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
schreibt einen Log-Eintrag nach jedem Aufruf dieses Intents.&lt;br /&gt;
&lt;br /&gt;
Die folgenden Argumente können dabei übergeben werden:&lt;br /&gt;
* NAME =&amp;gt; Name des RHASSPY-Devices&lt;br /&gt;
* DATA =&amp;gt; komplette JSON-$data (wie intern geparsed), in JSON kodiert&lt;br /&gt;
* siteId, Device etc. =&amp;gt; jedes Element, das in JSON-$data existiert&lt;br /&gt;
Wird von der Funktion ein einfacher Text zurück geliefert, wird dieser als &#039;&#039;response&#039;&#039; angesehen. Wenn der Rückgabewert nicht definiert ist, wird die Standard-&#039;&#039;response&#039;&#039; verwendet.&lt;br /&gt;
&lt;br /&gt;
Es kann aber auch ein &#039;&#039;&#039;HASH&#039;&#039;&#039; oder &#039;&#039;&#039;ARRAY&#039;&#039;&#039; übergeben werden.&lt;br /&gt;
* Im Falle eines &#039;&#039;&#039;ARRAY&#039;&#039;&#039;s wird das erste Element als &#039;&#039;response&#039;&#039; interpretiert und kann ein reiner Text sein, womit der Dialog beendet wird. &lt;br /&gt;
* Ist das erste Element ein &#039;&#039;&#039;HASH&#039;&#039;&#039; wird die Dialog-Session fortgesetzt. Eine offene Dialog-Session wird per Default nach 20 Sekunden beendet. Diese Zeitspanne kann aber auch geändert werden, in dem im ARRAY als zweiter Wert eine Zahl übergeben wird. Das zweite Element kann aber auch eine komma-getrennte Liste an Geräten sein, die geändert (geschalten) wurden. Das dient dazu, damit die Geräte auch Events liefern, was ansonsten nicht der Fall wäre. Siehe dazu den &amp;quot;d&amp;quot;-Parameter beim Attribut [[#rhasspyShortcuts|rhasspyShortcuts]].&lt;br /&gt;
Wird eine HASH-Datenstruktur (ggf. in $response innerhalb einer ARRAY-Struktur), um einen laufenden Dialog fortzusetzen, muss sichergestellt werden, dass alle erforderlichen Datenelemente enthalten sind, insbesondere &#039;&#039;intentFilter&#039;&#039;, falls die für den weiteren Dialog relevanten Intents eingeschränkt (oder erweitert) werden sollen. Dabei sollte möglichst der Intent &#039;&#039;CancelAction&#039;&#039; aktiv gehalten werden, damit der User die Option hat, den Dialog jederzeit aktiv zu beenden.&lt;br /&gt;
&lt;br /&gt;
Siehe dazu auch den Abschnitt [[#Eigene Intents erstellen|Eigene Intents erstellen]].&lt;br /&gt;
&lt;br /&gt;
===rhasspyShortcuts===&lt;br /&gt;
Hiermit können benutzerdefinierte Sätze erstellt werden ohne die sentences.ini in Rhasspy bearbeiten zu müssen.&lt;br /&gt;
Diese Shortcuts werden zu Rhasspy hochgeladen, sobald das &amp;lt;code&amp;gt;updateSlots&amp;lt;/code&amp;gt; [[#set-update|Set]]-Kommando ausgeführt wird.&lt;br /&gt;
Ein Shortcut pro Zeile, Syntax ist entweder einfach oder erweitert.&lt;br /&gt;
&#039;&#039;&#039;Beispiele:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;mute on=set amplifier2 mute on&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;lamp off={fhem(&amp;quot;set lampe1 off&amp;quot;)}&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;i=&amp;quot;du bist cool&amp;quot; f=&amp;quot;set $NAME speak siteId=&#039;livingroom&#039; text=&#039;danke dir! du bist noch viel cooler!&#039;&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;i=&amp;quot;schalte den ton aus&amp;quot; p={fhem (&amp;quot;set $NAME mute off&amp;quot;)} n=amplifier2 c=&amp;quot;soll ich den ton wirklich ausschalten?&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;i=&amp;quot;ich hab hunger&amp;quot; f=&amp;quot;set Herd on&amp;quot; d=&amp;quot;Herd&amp;quot; c=&amp;quot;möchtest du schweinsbraten?&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Erklärung zu den Abkürzungen:&lt;br /&gt;
* &amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt; =&amp;gt; intent&lt;br /&gt;
Zeilen, die mit &amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt; beginnen, werden als erweiterte Syntax interpretiert. Soll die erweiterte Syntax verwendet werden, ist das &amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt; also Pflicht!&lt;br /&gt;
* &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; =&amp;gt; FHEM Befehl&lt;br /&gt;
Syntax wie von der FHEM Kommandozeile gewohnt&lt;br /&gt;
* &amp;lt;code&amp;gt;p&amp;lt;/code&amp;gt; =&amp;gt; Perl Befehl&lt;br /&gt;
Syntax wie von der FHEM Kommandozeile gewohnt, eingerahmt in geschwungenen Klammern (&amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt;). &amp;lt;code&amp;gt;p&amp;lt;/code&amp;gt; hat Vorrang vor &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;d&amp;lt;/code&amp;gt; =&amp;gt; Device Name(en, Komma getrennt)&lt;br /&gt;
Device Name(n), die an fhem.pl als upgedated übergeben werden sollen. Das wird benötigt um weitere Aktionen in FHEM und das Longpolling zu triggern.&lt;br /&gt;
&lt;br /&gt;
Hinweis: Wenn Perl-Funktionen aufgerufen werden, wird der Rückgabewert dieser Funktion verwendet, sofern kein explizites Device angegeben ist.&lt;br /&gt;
* &amp;lt;code&amp;gt;r&amp;lt;/code&amp;gt; =&amp;gt; Response&lt;br /&gt;
Sprachanwort, die ausgegeben wird. Ist &amp;lt;code&amp;gt;r&amp;lt;/code&amp;gt; nicht gesetzt, wird der Rückgabewert der aufgerufenen Funktion verwendet.&lt;br /&gt;
In den Antwortsätze werden &#039;&#039;set magic&#039;&#039;-ähnliche Ersetzungen verarbeitet. Es ist also auch eine Zeile wie &amp;lt;code&amp;gt;i=&amp;quot;what&#039;s the time for sunrise&amp;quot; r=&amp;quot;at [Astro:SunRise] o&#039;clock&amp;quot;&amp;lt;/code&amp;gt; gültig.&lt;br /&gt;
&lt;br /&gt;
Mit den folgenden Abkürzungen kann auch nach einer Bestätigung für den Befehl gefragt werden:&lt;br /&gt;
* &amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt; =&amp;gt; Entweder Zahl oder Text. Wenn Zahl, wird sie als Timeout für den Abbruch des Dialogs behandelt. Wenn Text wird dieser als Sprachausgabe zur Bestätigung verwendet.&lt;br /&gt;
* &amp;lt;code&amp;gt;ct&amp;lt;/code&amp;gt; =&amp;gt; Numerischer Wert für das Timeout des Dialogs in Sekunden. Default ist &amp;lt;code&amp;gt;15&amp;lt;/code&amp;gt;.&lt;br /&gt;
Siehe [[#attr-rhasspytweaks-confirmintents|hier]] für weitere Informationen zu Bestätigungen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===rhasspyTweaks===&lt;br /&gt;
Mit diesen Einstellungen können benutzerdefinierte Optimierungen an RHASSPY vorgenommen werden.&lt;br /&gt;
&lt;br /&gt;
====timerLimits====&lt;br /&gt;
Wird verwendet um den Timer anzuweisen mit z.B. &amp;quot;gestellt auf 30 Minuten&amp;quot; oder &amp;quot;gestellt auf 10:30&amp;quot; zu antworten&lt;br /&gt;
:&amp;lt;code&amp;gt;timerLimits=90,300,3000,2*HOURSECONDS,50&amp;lt;/code&amp;gt;&lt;br /&gt;
Hierbei müssen fünf Werte gesetzt werden, die den Zeitgrenzen für Stufen in der Antwortstruktur &#039;&#039;timerSet&#039;&#039; entsprechen.&lt;br /&gt;
Obiges Beispiel also würde dazu führen, unter einer eingestellten Zeit von 90 Sekunden mit der Sekundenangabe geantwortet wird. In Minuten und Sekunden solange der Timer kürzer als 300 Sekunden ist. Usw. Der letzte Wert ist das Limit in Sekunden, wenn der Timer im &amp;quot;Uhrzeit&amp;quot;-Format gestellt ist.&lt;br /&gt;
&lt;br /&gt;
====timerSounds====&lt;br /&gt;
Standardmäßig antwortet der Timer mit einer Sprachnachricht, wenn er abgelaufen ist. Soll lieber eine WAV-Datei verwendet werden, kann das hier eingestellt werden.&lt;br /&gt;
:&amp;lt;code&amp;gt;timerSounds= default=./yourfile1.wav eier=3:20:./yourfile2.wav kartoffeln=5:./yourfile3.wav&amp;lt;/code&amp;gt;&lt;br /&gt;
Die Keys in dieser Code-Zeile sind Beispiele und deren Name - bis auf &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; frei wählbar. Der Name muss aber zu den &#039;&#039;Label&#039;&#039;-Tags für die Timer in den Rhasspy-Sentences passen.&lt;br /&gt;
&amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; ist optional. Wenn gesetzt, wird dieses WAV-File für alle benannten Timer verwendet, für die kein Keyword in der Konfiguration ist.&lt;br /&gt;
Die beiden Nummern sind optional. Die erste legt fest, wie oft die WAV-Datei wiederholt werden soll (Default: 5). Die zweite definiert die Pause in Sekunden zwischen den Wiederholungen (Default: 15). Ist nur eine Zahl gesetzt, wird diese als gewünschte Anzahl an Wiederholungen interpretiert.&lt;br /&gt;
&lt;br /&gt;
====updateSlots====&lt;br /&gt;
Ändert diverse Aspekte des Erstellens und Updatens von Slots&lt;br /&gt;
* &amp;lt;code&amp;gt;noEmptySlots=1&amp;lt;/code&amp;gt;&lt;br /&gt;
Per Default generiert RHASSPY einen zusätzlichen Slot für jeden &#039;&#039;genericDeviceType&#039;&#039;, der erkannt wird. Unabhängig davon, ob er bei einem Gerät gesetzt ist. Das kann zu leeren Slots führen.&lt;br /&gt;
Ist der Wert &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;, werden keine leeren Slots erstellt.&lt;br /&gt;
* &amp;lt;code&amp;gt;overwrite_all=false&amp;lt;/code&amp;gt;&lt;br /&gt;
RHASSPY überschreibt alle vorhandenen Slots wenn ein &amp;lt;code&amp;gt;updateSlots&amp;lt;/code&amp;gt; ausgeführt wird. Ist das nicht gewünscht, muss dieser Wert auf &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; gesetzt werden.&lt;br /&gt;
* &amp;lt;code&amp;gt;timeouts&amp;lt;/code&amp;gt;&lt;br /&gt;
Die Keywörter &amp;lt;code&amp;gt;confirm&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; können verwendet werden, um das Standard-Timeouts (15s/20s) für Dialoge zu ändern.&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;code&amp;gt;timeouts: confirm=25 default=30&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====confidenceMin====&lt;br /&gt;
Rhasspy ermittelt u.A. auch einen Indikator, anhand dem bestimmt werden kann, wie genau ein Satz erkannt wurde. Ist dieser &#039;&#039;confidence&#039;&#039;-Wert sehr bzw. zu niedrig, kann es erwünscht sein, die (falsch erkannte) Absicht des Sprechers nicht umzusetzen. RHASSPY nutzt daher standardmäßig einen Mindestwert von 0.66, bei allen darunter liegenden Werten wird das betreffende Kommando nicht ausgeführt. Dies kann über diesen Tweak global (key: default) oder feiner pro Intent festgelegt werden.&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;code&amp;gt;confidenceMin= default=0.6 SetMute=0.4 SetOnOffGroup=0.8 SetOnOff=0.8&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====confirmIntents====&lt;br /&gt;
Hiermit kann eingestellt werden, dass für bestimmte Intents immer ein Bestätigung erfragt wird. Unterstützt werden derzeit alle &amp;quot;set-&amp;quot;-Intents.&lt;br /&gt;
Dazu werden &amp;lt;code&amp;gt;Intent&amp;lt;/code&amp;gt;=&amp;lt;code&amp;gt;regex&amp;lt;/code&amp;gt;-Paare verwendet. &amp;lt;code&amp;gt;Intent&amp;lt;/code&amp;gt; ist der Name des gewünschten Intents, &amp;lt;code&amp;gt;regex&amp;lt;/code&amp;gt; ist eine Regex, die eine bestimmte Gruppe (für Gruppen-Intents) oder einen bestimmten Device-Namen beschreiben muss.&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;code&amp;gt;confirmIntents=SetOnOffGroup=light|blinds SetOnOff=blind.*&amp;lt;/code&amp;gt;&lt;br /&gt;
Befehle werden nur nach einer positiven Bestätigung ausgeführt. Das bedeutet, es wird eine Rückfrage ausgegeben, auf diese muss dann (innerhalb des gesetzten Timeouts) unbedingt ein &amp;lt;code&amp;gt;Mode:OK&amp;lt;/code&amp;gt;-Wert vom &#039;&#039;ConfirmAction&#039;&#039;-Intent gesendet werden. Jede andere Wert für &amp;lt;code&amp;gt;Mode&amp;lt;/code&amp;gt; wird als Abbruch gewertet. Es kann aber auch der eigene Intent &#039;&#039;CancelAction&#039;&#039; für den Abbruch verwendet werden.&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:ConfirmAction]&lt;br /&gt;
( yes, please do it | go on | that&#039;s ok | yes, please ){Mode:OK}&lt;br /&gt;
( don&#039;t do it after all ){Mode}&lt;br /&gt;
&lt;br /&gt;
[de.fhem:CancelAction]&lt;br /&gt;
( let it be | oh no | cancel | cancellation ){Mode:Cancel}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====confirmIntentResponses====&lt;br /&gt;
Üblicherweise ist die Bestätigungs-Frage ein &amp;quot;Echo&amp;quot; des ursprünglich gesprochenen Befehls. Dies kann für jeden Intent geändert werden,&lt;br /&gt;
Dies kann für jeden Intent individuell angepaßt werden, wobei die Variablen $target, ($rawInput) und $Value verwendet werden können.&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;code&amp;gt;confirmIntentResponses=SetOnOffGroup=&amp;quot;wirklich die Gruppe $target $Value schalten&amp;quot; SetOnOff=&amp;quot;bestätige dass $target $Value geschaltet werden soll&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;$Value&amp;lt;/code&amp;gt; wird dabei mit den defaults aus dem &#039;&#039;words&#039;&#039; key in der languageFile übersetz (falls vorhanden). Weitere Optionen für Ersetzungen von &amp;lt;code&amp;gt;$Value&amp;lt;/code&amp;gt; sind für einzelne Devices über den [[#attr-rhasspyspecials-confirmvaluemap|confirmValueMap]] key im Attribut &#039;&#039;rhasspySpecials&#039;&#039; verfügbar.&lt;br /&gt;
&lt;br /&gt;
====intentFilter====&lt;br /&gt;
Rhasspy aktiviert bei jedem Neustart alle ihm bekannten Intents. Da manche der von FHEM genutzten Intents nur in bestimmten Situationen (v.a. innerhalb offener Dialoge) benötigt werden, deaktiviert RHASSPY diese (derzeit: ConfirmAction, CancelAction, Choice, ChoiceRoom und ChoiceDevice beim Start, sowie jedes Mal, wenn erkannt wird, dass das Standardfiltering nicht wie erwartet funktioniert (was v.a. bei einem zwischenzeitlichen Rhasspy-Neustart der Fall sein kann). Über diesen Tweak können weitere Intents mit in diese automatisierte (De-) Aktivierung mit einbezogen werden. Entweder ist dabei einfach der Name (ohne die Zusätze aus &#039;&#039;language&#039;&#039; und &#039;&#039;fhemId&#039;&#039; anzugeben, oder eine explizite Anweisung zum ein- und Ausschalten (in der Form &amp;lt;code&amp;gt;intentname=true&amp;lt;/code&amp;gt;). Die 4 vorgenannten Standard-Intents können nicht über diesen Weg aktiviert werden. Details zur intern genutzten Rhasspy-Funktionalität sind in der [https://rhasspy.readthedocs.io/en/latest/reference/#dialogue-manager Rhasspy-Dokumentation] zu finden.&lt;br /&gt;
&lt;br /&gt;
====ignoreKeywords====&lt;br /&gt;
Da in manchen der von RHASSPY automatisch ausgewerteten Attribute häufig auch eher technisch motivierte Angaben zu finden sind, kann über diesen Schlüssel verhindert werden, dass derartige Angaben bei der slot-Erstellung übergangen werden. Dies betrifft z.B. häufig anzutreffende &#039;&#039;room&#039;&#039;-Werte wie &#039;&#039;MQTT&#039;&#039;, &#039;&#039;alexa&#039;&#039;, &#039;&#039;homebridge&#039;&#039; oder &#039;&#039;googleassistant&#039;&#039;. Die hier angegebenen key-value-Paare werden als Negativ-Filter für die angegebenen Werte verwendet (derzeit nur für &#039;&#039;rooms&#039;&#039; und &#039;&#039;group&#039;&#039;). &#039;&#039;value&#039;&#039; wird dabei als (case-insensitive) regex behandelt, verglichen wird auf exakten match (es müssen also ggf. vorne bzw. hinten &#039;&#039;.*&#039;&#039; angefügt werden).&lt;br /&gt;
Dieses &#039;&#039;&#039;Beispiel&#039;&#039;&#039; filtert daher die o.g. Räume aus und dazu noch die strukturierten Unterräume unterhalb &#039;&#039;Steuerung&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ignoreKeywords=rooms=mqtt.*|alexa|homebridge|googleassistant|steuerung-.&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====gdt2groups====&lt;br /&gt;
Dieser Eintrag ermöglicht es, alle Geräte eines generichDeviceType innerhalb der automatischen Erfassung automatisch einer oder mehreren Gruppen zuzuordnen. Die Vorgaben in diesem Eintrag werden nicht übernommen, wenn am jeweiligen Einzelgerät  das Attribut &#039;&#039;rhasspyGroup&#039;&#039; gesetzt ist.  Hier eine deutschsprachige Vorbelegung als &#039;&#039;&#039;Beispiel&#039;&#039;&#039;: &amp;lt;code&amp;gt;gdt2groups= blind=rollläden,rollladen thermostat=heizkörper light=lichter,leuchten&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====mappingOverwrite====&lt;br /&gt;
Wird diese Option aktiviert, wird bei gesetztem &#039;&#039;rhasspyMapping&#039;&#039;-Attribut an einem Device alles gelöscht, was die automatisierte mapping-Erkennung anhand des genericDeviceType erkannt hatte. Sonst ird jeweils nur überschrieben, was als Intent im &#039;&#039;rhasspyMapping&#039;&#039; dieses Geräts angegeben ist.&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
:mappingOverwrite=1&lt;br /&gt;
&lt;br /&gt;
====extrarooms====&lt;br /&gt;
Komma-separierte Liste von weiteren Räumen, die die aus der Generierung der Device-Map bekannten Räume erweitert. Dies kann z.B. für CustomIntents benötigt werden.&lt;br /&gt;
Diese werden in die Slots für &amp;lt;code&amp;gt;rooms&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;mainrooms&amp;lt;/code&amp;gt; integriert.&lt;br /&gt;
Beispiel:&lt;br /&gt;
:extrarooms= barn,music collection,cooking recipies&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Readings / Events==&lt;br /&gt;
;&amp;lt;code&amp;gt;IODev&amp;lt;/code&amp;gt;&lt;br /&gt;
:Das eingestellte IO-Device&lt;br /&gt;
;&amp;lt;code&amp;gt;intents&amp;lt;/code&amp;gt;&lt;br /&gt;
:Eine Liste der in Rhasspy vorhandenen Intents&lt;br /&gt;
;&amp;lt;code&amp;gt;lastIntentPayload&amp;lt;/code&amp;gt;&lt;br /&gt;
:Inhalt des letzten Intents der von FHEM empfangen wurde&lt;br /&gt;
;&amp;lt;code&amp;gt;lastIntentTopic&amp;lt;/code&amp;gt;&lt;br /&gt;
:Das MQTT-Topic des letzten Intents&lt;br /&gt;
;&amp;lt;code&amp;gt;listening_roomname&amp;lt;/code&amp;gt;&lt;br /&gt;
:Ein Reading für jeden Raum bzw. jede siteId&lt;br /&gt;
:Wechselt auf 1 sobald ein Hotword erkannt wurde und zurück auf 0, sobald die Dialog-Session beendet ist.&lt;br /&gt;
:Kann z.B. verwendet werden, um den Ton eines TVs auszuschalten, während Rhasspy auf ein Kommando hört.&lt;br /&gt;
;&amp;lt;code&amp;gt;mute_roomname&amp;lt;/code&amp;gt;&lt;br /&gt;
:Zeigt an, ob ein Raum / eine siteId vom Intent &#039;&#039;SetMute&#039;&#039; stumm geschalten wurde und somit keine Befehle ausführt.&lt;br /&gt;
:Jeweils ein Reading für jede siteId.&lt;br /&gt;
:Default ist 0.&lt;br /&gt;
;&amp;lt;code&amp;gt;responseType&amp;lt;/code&amp;gt;&lt;br /&gt;
:Der Typ der letzten Antwort (text/voice).&lt;br /&gt;
:voiceResponse and textResponse&lt;br /&gt;
:Antwort auf das letzte Sprach-/Text-Kommando.&lt;br /&gt;
;&amp;lt;code&amp;gt;siteIds&amp;lt;/code&amp;gt;&lt;br /&gt;
:Listet alle siteIds auf.&lt;br /&gt;
:Kann mit [[#set-fetchsiteids|fetchSiteIds]] aktualisiert werden.&lt;br /&gt;
;&amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;&lt;br /&gt;
:Zeigt an ob RHASSPY mit Rhasspy verbunden ist&lt;br /&gt;
;&amp;lt;code&amp;gt;training&amp;lt;/code&amp;gt;&lt;br /&gt;
:Letzte zurückgelieferte Antwort auf einen [[#set-trainrhasspy|trainRhasspy]]-Befehl.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
;&amp;lt;code&amp;gt;updateSentences&amp;lt;/code&amp;gt;&lt;br /&gt;
:Letzte zurückgelieferte Antwort nach einem [[#set-update-slots|updateSlots]]-Befehl.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
;&amp;lt;code&amp;gt;updateSlots&amp;lt;/code&amp;gt;&lt;br /&gt;
:Letzte zurückgelieferte Antwort nach einem [[#set-update-slots|updateSlots]]-Befehl.&lt;br /&gt;
;&amp;lt;code&amp;gt;hotword&amp;lt;/code&amp;gt;&lt;br /&gt;
:Wenn aktiviert, beinhaltet dieses Reading das letzte verwendete Hotword und von welcher siteId es aufgerufen wurde.&lt;br /&gt;
;&amp;lt;code&amp;gt;voiceResponse&amp;lt;/code&amp;gt;&lt;br /&gt;
:Letze Sprach-Antwort auf einen Sprach-Befehl&lt;br /&gt;
&lt;br /&gt;
=== Benutzerdefinierte Readings ===&lt;br /&gt;
Um das Verhalten von RHASSPY beeinflussen zu können, können neben den bei den Attributen verfügbaren &#039;&#039;Tweaks&#039;&#039; auch die folgenden Readings genutzt - und v.a. auch im laufenden Betrieb immer weider geändert - werden:&lt;br /&gt;
*&amp;lt;code&amp;gt;siteId2room_&amp;lt;/code&amp;gt; Falls keine explizite Raum-Information in den an RHASSPY weitergegebenen Daten enthalten ist, ermittelt das Modul den Raum in der Regel aus dem Namen der &#039;&#039;siteId&#039;&#039;. So werden z.B. alle raumlosen Anweisungen von einem Satelliten names &#039;&#039;schlafzimmer&#039;&#039;, im Raum &#039;&#039;schlafzimmer&#039;&#039; ausgeführt werden (wenn möglich). Die Gruppenfunktion von Rhasspy wird unterstützt, so wird z.B. &#039;&#039;wohnzimmer.vorne&#039;&#039; ebenfalls automatisch dem Raum &#039;&#039;wohnzimmer&#039;&#039; zugeordnet. Über passende Angaben in &#039;&#039;siteId2room-Readings&#039;&#039; kann dieses Verhalten modifiziert werden:  &amp;lt;code&amp;gt;setreading siteId2room_mobile_phone1 wohnzimmer&amp;lt;/code&amp;gt; wird RHASSPY veranlassen, den Satelliten  &#039;&#039;mobile_phone1&#039;&#039; dem Raum &#039;&#039;wohnzimmer&#039;&#039; zuzuweisen. Ein Beispiel, mit dem dies per Sprachkommando erfolgt, ist in &#039;&#039;contrib&#039;&#039; zu finden, mit der mobilen Satelliten per Funktionsaufruf in einem [[#rhasspyIntents|rhasspyIntent]] einem neuen Raum zugewiesen werden können.&lt;br /&gt;
*&amp;lt;code&amp;gt;siteId2doubleSpeak_&amp;lt;/code&amp;gt; RHASSPY antwortet immer über den Satelliten, von dem die jeweilige Sprachanweisung kam. Manchmal kann es erwünscht sein, zusätzliche Sprachrückmeldungen an einen weiteren Satelliten zu geben - z.B. weil der betreffende Lautsprecher (zeitweise) ausgeschaltet ist. Ist ein entsprechendes Reading gesetzt, erfolgen (zusätzliche!) Sprachausgaben an den dort als Readingwert angegebenen zweiten Satelliten; das Namensschema der Readings entspricht dem für site2room.&lt;br /&gt;
&lt;br /&gt;
== FHEM-Devices für die Verwendung mit Rhasspy konfigurieren ==&lt;br /&gt;
Um ein Gerät mit Rhasspy steuern zu können, muss Rhasspy einige Details über das Gerät kennen. Diese werden bekannt gemacht, in dem bei den Geräten Attribute gesetzt werden, die anschließend vom RHASSPY-Modul ausgewertet und an Rhasspy gesendet werden.&lt;br /&gt;
&lt;br /&gt;
Der einfachste - und empfohlene - Weg, dies zu erreichen, ist durch Setzen des Attributs &#039;&#039;&#039;&#039;&#039;genericDeviceType&#039;&#039;&#039;&#039;&#039;. Das Modul erkennt dann die möglichen Schalt - und Abfragemöglichkeiten des Gerätes automatisch.&lt;br /&gt;
&lt;br /&gt;
Sollte &#039;&#039;genericDeviceType&#039;&#039; (gDT) nicht ausreichen, gibt es noch weitere Attribute, die stattdessen oder ergänzend dazu verwendet werden können (z.b. rhasspyName, rhasspyRoom, ...). Die Namen dieser Attribute beginnen alle mit dem &#039;&#039;prefix&#039;&#039;, das in der DEF des RHASSPY-Moduls gesetzt wurde. Diese Dokumentation verwendet das Prefix &amp;lt;code&amp;gt;rhasspy&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Sind sowohl &#039;&#039;genericDeviceType&#039;&#039; als auch Spezial-Attribute vorhanden, werden die von gDT gesammelten Möglichkeiten durch die der Spezial-Attribute überschrieben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Wichtig:&#039;&#039;&#039;&lt;br /&gt;
*Nach JEDER Änderung (bzw. nach Abschluss aller Änderungen) an den folgenden Attributen muss ein &amp;lt;code&amp;gt;[[#update devicemap|update devicemap]]&amp;lt;/code&amp;gt; ausgeführt werden. In der Regel wird dies automatisch veranlasst, aber wenn dies deaktiviert sein sollte, würden sonst weder RHASSPY, noch Rhasspy von der Änderung erfahren.&lt;br /&gt;
*RHASSPY sammelt alle Informationen aus diesen Attributen in seinem eigenen Device-HASH. Dieser wird durch das &amp;lt;code&amp;gt;update devicemap&amp;lt;/code&amp;gt;-Kommando aktualisiert und kann mittels &amp;lt;code&amp;gt;[[List|list]]&amp;lt;/code&amp;gt;-Befehl angezeigt werden. Für diesen HASH werden alle Namen und sonstige &amp;quot;Labels&amp;quot; in Kleinbuchstaben umgewandelt. Falls man Slots händisch befüllt, muss also darauf geachtet werden, dass Rhasspy ebenfalls Werte in Kleinbuchstaben liefert.&lt;br /&gt;
*Die Mindestvoraussetzungen für ein FHEM Device um mit RHASSPY zusammenzuarbeiten sind:&lt;br /&gt;
**Das Device muss von der &#039;&#039;devspec&#039;&#039; im Define des RHASSPY-Devices abgedeckt werden&lt;br /&gt;
**Es muss mindestens eines der folgenden Attribute (im Normalfall &#039;&#039;genericDeviceType&#039;&#039;) im Device gesetzt sein.&lt;br /&gt;
*Die Mapping-Logik (für Namen, mögliche Schaltzustände, etc.) ist wie folgt:&lt;br /&gt;
**Sind RHASSPY-spezifische Attribute gesetzt, werden ausschließlich diese verwendet. Natürlich nur für den Zweck des gesetzten Attributs. Ein gesetzter &#039;&#039;rhasspyName&#039;&#039; z.B. wird also nicht verhindern, dass die durch &#039;&#039;genericDeviceType&#039;&#039; ermittelten möglichen Schaltzustände ebenfalls gespeichert werden.&lt;br /&gt;
**Je spezifischer ein Attribut ist, desto eher wird überschreiben, was weniger speziell ist. Ein gesetzter &#039;&#039;alias&#039;&#039; wird also verhindern, dass der (technische) Device-Name verwendet wird. Aber ein gesetztes Attribut &#039;&#039;alexaName&#039;&#039;, &#039;&#039;gassistantName&#039;&#039; oder &#039;&#039;siriName&#039;&#039; wird (auch) den &#039;&#039;alias&#039;&#039; überschreiben. Sind zwei &amp;quot;gleichwertige&amp;quot; Attribute vorhanden (z.B. &#039;&#039;siriName&#039;&#039; und &#039;&#039;alexaName&#039;&#039;), werden beide verwendet.&lt;br /&gt;
*Attribut-Werte werden typischerweise &amp;quot;Zeile für Zeile&amp;quot; gelesen. Wobei gilt, eine Zeile pro Wert/Befehl/Funktionalität. Zeilenumbrüche &#039;&#039;&#039;müssen&#039;&#039;&#039; also an den richtigen Stellen gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
=== genericDeviceType ===&lt;br /&gt;
Ist dieses Attribut gesetzt &#039;&#039;&#039;und&#039;&#039;&#039; entspricht der Devicename der devspec, wird RHASSPY das Mapping (und andere eventuell schon vorhandene Werte) automatisch ermitteln.&lt;br /&gt;
&lt;br /&gt;
Derzeit werden folgende Werte für das Attribut genericDeviceType unterstützt:&lt;br /&gt;
*switch&lt;br /&gt;
*light&lt;br /&gt;
*thermostat&lt;br /&gt;
*thermometer&lt;br /&gt;
*HumiditySensor&lt;br /&gt;
*blind/blinds/shutter&lt;br /&gt;
*media&lt;br /&gt;
*motion/contact/ContactSensor/lock/presence&lt;br /&gt;
&lt;br /&gt;
Wird &#039;&#039;genericDeviceType&#039;&#039; verwendet, werden unter anderem folgende Informationen gesammelt:&lt;br /&gt;
* der Name (&amp;lt;code&amp;gt;NAME&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;alias&amp;lt;/code&amp;gt;) des Devices&lt;br /&gt;
* der (FHEM-)Raum, in dem sich das Device befindet.&lt;br /&gt;
* die Gruppe, zu der das Device gehört (ggf. unter Beachtung des Schlüssels [[#gdt2groups|gdt2groups]] aus [[#rhasspyTweaks|rhasspyTweaks]])&lt;br /&gt;
* wie Informationen vom Gerät abgefragt werden können&lt;br /&gt;
* wie Werte/Status am Gerät gesetzt werden können&lt;br /&gt;
&lt;br /&gt;
Die Verwendung von &#039;&#039;genericDeviceType&#039;&#039; ist der einfachste Weg, wie man FHEM-Devices dazu bringen kann, mit RHASSPY zusammenzuarbeiten. Manchmal liefert genericDeviceType aber nicht ausreichende oder nicht passende Informationen. In so einem Fall können die folgenden Attribute (zusätzlich) verwendet werden.&lt;br /&gt;
&lt;br /&gt;
=== rhasspyName ===&lt;br /&gt;
Mit diesem Attribut kann der Name des Geräts eingestellt werden, mit dem es in einem Sprachbefehl angesprochen werden soll. Es können auch mehrere Namen - getrennt durch ein Komma - angegeben werden, der erste Wert in dieser Liste dient intern als Hauptname (&#039;&#039;alias&#039;&#039;), z.B. in Auswahldialogen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039; &amp;lt;code&amp;gt;attr &amp;lt;device&amp;gt; rhasspyName Lampe,Stehlampe,Wunderlicht&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es ist durchaus möglich, mehrere FHEM-Geräte mit dem selben Namen zu haben. Sie müssen dann nur in unterschiedlichen Räumen sein.&lt;br /&gt;
&lt;br /&gt;
=== rhasspyRoom ===&lt;br /&gt;
Dieses Attribut kann verwendet werden, um Rhasspy mitzuteilen, in welchem physischem (oder logischen) Raum sich das Gerät befindet.&lt;br /&gt;
&lt;br /&gt;
Ist es nicht vorhanden, wird &amp;lt;code&amp;gt;alexaRoom&amp;lt;/code&amp;gt; oder das FHEM-Attribut &amp;lt;room&amp;gt; verwendet. Sind auch diese nicht vergeben, gehört das Gerät zum &amp;quot;Standard-Raum&amp;quot;, der im Define des RHASSPY-Devices angegeben wurde.&lt;br /&gt;
&lt;br /&gt;
Das Attribut ist nützlich, wenn man Sprachbefehle ohne explizite Raumangabe verwenden will. Gibt es z.B. ein Gerät mit dem Namen &#039;&#039;Lampe&#039;&#039; und dessen rhasspyRoom-Attribut ist gleich, wie die &#039;&#039;siteId&#039;&#039; von der aus der Sprachbefehl abgesetzt wird, reicht es zu sagen &amp;quot;Lampe ein&amp;quot;. Der Raum muss also nicht extra dazu gesagt werden.&lt;br /&gt;
&lt;br /&gt;
Es ist auch möglich, mehrere Raum-Namen zu vergeben sofern diese durch ein Komma voneinander getrennt werden (der erste Wert ist wieder der &#039;&#039;Hauptraum&#039;&#039; für Auswahldialoge etc.).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039; &amp;lt;code&amp;gt;attr &amp;lt;device&amp;gt; rhasspyRoom livingroom&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hinweis: Wenn die &#039;&#039;siteId&#039;&#039; den Konventionen von Rhasspy zur Gruppierung von siteIds folgt (&#039;&#039;roomname.satellite&#039;&#039;), wird nur &amp;lt;code&amp;gt;roomname&amp;lt;/code&amp;gt; als Raum-Name angenommen. Beachte: Die automatisierte Zuweisung zu einem Raum kann durch &#039;&#039;siteId2room_.*&#039;&#039;-Readings modifiziert werden (s.o.). &lt;br /&gt;
&lt;br /&gt;
=== rhasspyGroup ===&lt;br /&gt;
Kommagetrennte Liste an Gruppen, zu denen das Gerät zugehörig ist&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039; &amp;lt;code&amp;gt;attr &amp;lt;device&amp;gt; rhasspyGroup Lampen,Beleuchtung Arbeitsfläche,Küchen Beleuchtung&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== rhasspyMapping ===&lt;br /&gt;
Wenn die automatische Erkennung des richtigen Intents für ein Gerät nicht funktioniert oder nicht das gewünschte Ergebnis liefert, kann mit diesem Attribut angegeben werden, mit welchem Intent das Gerät gesteuert werden kann.&lt;br /&gt;
&lt;br /&gt;
Es ist möglich, mehrere verschiedene Intents pro Gerät zu verwenden. Es muss nur einfach eine neue Zeile für ein weiteres Mapping verwendet werden.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr &amp;lt;device&amp;gt; rhasspyMapping SetOnOff:cmdOn=on,cmdOff=off,response=&amp;quot;Alles klar&amp;quot;&lt;br /&gt;
GetOnOff:currentVal=state,valueOff=off&lt;br /&gt;
GetNumeric:currentVal=pct,type=brightness&lt;br /&gt;
SetNumeric:currentVal=brightness,cmd=brightness,minVal=0,maxVal=255,map=percent,step=1,type=brightness&lt;br /&gt;
Status:response=Die Helligkeit in der Küche ist bei [&amp;lt;device&amp;gt;:pct]&lt;br /&gt;
MediaControls:cmdPlay=play,cmdPause=pause,cmdStop=stop,cmdBack=previous,cmdFwd=next&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Formatierung von Befehlen und Readings innerhalb eines rhasspyMappings ====&lt;br /&gt;
Manche Intents können FHEM-Kommandos oder -Readings verwenden, um Werte auszulesen oder zu setzen.&lt;br /&gt;
&lt;br /&gt;
Dabei gibt es drei Möglichkeiten, wie diese geschrieben werden können:&lt;br /&gt;
*Direktes Verwenden von SET-Kommando oder Reading des aktuellen Device:&lt;br /&gt;
:&amp;lt;code&amp;gt;cmd=on or currentReading=temperature&amp;lt;/code&amp;gt;&lt;br /&gt;
*Umleiten eines Kommando auf ein anderes Device oder Verwenden eines Readings aus einem anderen Gerät:&lt;br /&gt;
:&amp;lt;code&amp;gt;cmd=Otherdevice:on or currentReading=Otherdevice:temperature&amp;lt;/code&amp;gt;&lt;br /&gt;
*Perl-Code um einen Befehl auszuführen oder einen Wert zu setzen:&lt;br /&gt;
:Das ermöglicht sehr komplexe Anfragen.&lt;br /&gt;
:Der Code muss in geschwungenen Klammern sein.&lt;br /&gt;
:&amp;lt;code&amp;gt;{currentVal={ReadingsVal($DEVICE,&amp;quot;state&amp;quot;,0)}&amp;lt;/code&amp;gt;&lt;br /&gt;
:oder&lt;br /&gt;
:&amp;lt;code&amp;gt; cmd={fhem(&amp;quot;set $DEVICE dim $VALUE&amp;quot;)}&amp;lt;/code&amp;gt;&lt;br /&gt;
:$DEVICE ist das aktuelle FHEM-device. Der SetNumeric-Intent kann $VALUE für den Wert verwenden, der gesetzt werden soll.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== rhasspySpecials ===&lt;br /&gt;
Dieses Attribut wirkt ähnlich wie [[#rhasspyTweaks| rhasspyTweaks]], verändert allerdings nur jeweils das Verhalten des Geräts, bei dem es gesetzt ist. Auch dieses Attribut wird zeilenweise eingelesen, es können ein oder mehrere der folgenden Optionen gesetzt werden:&lt;br /&gt;
&lt;br /&gt;
==== group ====&lt;br /&gt;
::Wird dieser Schlüssel gesetzt, wird das Gerät bei Gruppenaktionen nicht direkt adressiert, sondern die hier angegebene Gruppe. Details hierzu sind in [[RHASSPY/Vertiefung#Timing-Aspekte| Vertiefung - Timing-Aspekte]] zu finden.&lt;br /&gt;
&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;attr lamp1 rhasspySpecials group:async_delay=100 prio=1 group=lights&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== numericValueMap ====&lt;br /&gt;
::Ermöglicht es, statt der allgemeinen Methode zum Umgang mit numerischen Werten einzelnen Werten spezielle Kommandos zuzuweisen. Dies kann z.B. hilfreich sein, um spezielle Positionen für Rollladengeräte anzusteuern.&lt;br /&gt;
::&#039;&#039;&#039;Beispiel&#039;&#039;&#039;:&lt;br /&gt;
::&amp;lt;code&amp;gt;attr blind1 rhasspySpecials numericValueMap:10=&#039;Event Slit&#039; 50=&#039;myPosition&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
::führt dazu, dass ein numerischer Wert von 10 (im {Value}-key) das Kommando &amp;lt;code&amp;gt;set blind1 Event Slit&amp;lt;/code&amp;gt; ausführt.&lt;br /&gt;
&lt;br /&gt;
==== venetianBlind ====&lt;br /&gt;
Siehe [[RHASSPY/Vertiefung#Jalousien|Vertiefung - Jalousien]]&lt;br /&gt;
&lt;br /&gt;
==== colorCommandMap ====&lt;br /&gt;
Sowie **colorTempMap** und **colorForceHue2rgb**&lt;br /&gt;
Siehe [[RHASSPY/Vertiefung#Farben|Vertiefung - Farben]]&lt;br /&gt;
&lt;br /&gt;
==== priority ====&lt;br /&gt;
Ermöglicht es, Rückfragen zu vermeiden, wenn mehrere Geräte für bestimmte Aktionen in Frage kommen. Siehe [[RHASSPY/Vertiefung#Einer_statt_alle|Einer statt alle]]&lt;br /&gt;
&lt;br /&gt;
==== confirm ====&lt;br /&gt;
Ist eine Möglichkeit, Geräte nur nach Rückfrage und Bestätigung zu schalten (ähnlich wie &#039;&#039;confirmIntents&#039;&#039; in &#039;&#039;rhasspyTweaks&#039;&#039;). Es können entweder einfach nur Intent-Namen angegeben werden, oder Paare von **Intent** und zugehöriger **response**:&lt;br /&gt;
 SetOnOff=&amp;quot;Soll $target wirklich $Value geschaltet werden&amp;quot; SetScene&lt;br /&gt;
&lt;br /&gt;
==== confirmValueMap ====&lt;br /&gt;
Kann spezielle Übersetzungen für $Value enthalten, z.B. für Rollladen-Geräte:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;confirm: SetOnOff=&amp;quot;wirklich $Value $target&amp;quot;&lt;br /&gt;
confirmValueMap: on=öffnen off=schließen&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== scenes ====&lt;br /&gt;
Wird bei der automatisierten Erfassung erkannt, dass ein Gerät das Setzen von Szenen unterstützt, werden die erkannten Szenen-Namen an Rhasspy übergeben. Da diese häufig technischer Natur sind, eignen sie sich nicht für eine Spracherkennung. Über diesen Schlüssel können daher sprechbare Namen für jede Szene vergeben werden, und/oder einzelne bzw. alle Szenen von der Erkennung ausgenommen werden. Der Kenner &#039;&#039;none&#039;&#039; löscht die Szene von der Liste der übermittelten Szenen, wird die Kombination &#039;&#039;all=none&#039;&#039; angegeben, wird dieses Gerät insgesamt von der Vorbereitung für den Intent &#039;&#039;SetScene&#039;&#039; ausgeschlossen.&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;attr lamp1 rhasspySpecials scenes:scene2=&amp;quot;Kino zu zweit&amp;quot; scene3=Musik scene1=none scene4=none&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Siehe auch [[RHASSPY/Vertiefung#echte_Szenen|Vertiefung - echte Szenen]]. &lt;br /&gt;
&lt;br /&gt;
=== Veraltete Attribute ===&lt;br /&gt;
In der Regel sollte es ausreichen, die zu steuernden Devices über die oben genannten Attribute zu konfigurieren. Es gibt jedoch noch zwei ältere Methoden. Um diese zu verwenden, muss zuerst jeweils ein entsprechendes User-Attribut im FHEM-Device, das damit gesteuert werden soll, angelegt werden.&lt;br /&gt;
&lt;br /&gt;
==== rhasspyChannels ====&lt;br /&gt;
Das Attribut wird vom Intent &#039;&#039;MediaControls&#039;&#039; verwendet. Es informiert den Intent darüber, welche (Medien-)Kanäle vorhanden sind und welcher FHEM-Befehl oder Perl-Code auszuführen ist, wenn auf diesen Kanal geschaltet werden soll.&lt;br /&gt;
&lt;br /&gt;
In diesem Attribut muss eine Zeile pro (Medien-)Kanal verwendet werden.&lt;br /&gt;
&lt;br /&gt;
Um rhasspyChannels zu verwenden, muss zuerst ein neues User-Attribut im FHEM-Device, das damit gesteuert werden soll, angelegt werden. Dafür kann z.B. dieses Beispiel verwendet werden: &amp;lt;code&amp;gt;attr &amp;lt;deviceName&amp;gt; userattr rhasspyChannels:textField-long&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr &amp;lt;device&amp;gt; rhasspyChannels orf eins=channel 201&lt;br /&gt;
orf zwei=channel 202&lt;br /&gt;
orf drei=channel 203&lt;br /&gt;
netflix=launchApp Netflix&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== rhasspyColors ====&lt;br /&gt;
Ältere Methode, die verwendet werden kann, um Lichtfarben zu wechseln. Es wird nachdrücklich empfohlen, die neueren Methoden über die (nummerisch zu übergebenden) allgemeinen Farbwerte und/oder ein &#039;&#039;colorCommandMap&#039;&#039; oder &#039;&#039;colorTempMap&#039;&#039; (siehe &#039;&#039;rhasspySpecials&#039;&#039;) zu konfigurieren!&lt;br /&gt;
&lt;br /&gt;
Um das Mapping zu verwenden, muss zuerst ein User-Attribut am zu steuernden Gerät angelegt werden. Z.B. &amp;lt;code&amp;gt;attr &amp;lt;deviceName&amp;gt; userattr rhasspyChannels:textField-long&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Eine Zeile pro Farbe&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr lamp1 rhasspyColors rot=rgb FF0000&lt;br /&gt;
grün=rgb 008000&lt;br /&gt;
blau=rgb 0000FF&lt;br /&gt;
gelb=rgb FFFF00&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Intents ==&lt;br /&gt;
Intents werden verwendet um FHEM zu sagen, was es nach einem erhaltenen Sprach-/Textkommand unternehmen soll. Dieses Modul stellt einige Intents bereit.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Wichtig&lt;br /&gt;
:*Bei Tags (&amp;lt;code&amp;gt;Value&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;, etc.) ist die Schreibweise sehr wichtig! Die sind case-sensitive. Bitte daher genau so schreiben, wie sie in dieser Dokumentation vorkommen.&lt;br /&gt;
:*RHASSPY erstellt bei einem &amp;lt;code&amp;gt;update slots&amp;lt;/code&amp;gt; auch Slots je nach Möglichkeiten der Geräte oder Gruppen. Unterstützt ein Gerät zum Beispiel den Intent &#039;&#039;GetNumeric&#039;&#039;, wird auch ein Slot &amp;lt;code&amp;gt;de.fhem.Device-GetNumeric&amp;lt;/code&amp;gt; erstellt. Ein Gerät, dass ein- und ausgeschalten werden kann, wird im Slot &amp;lt;code&amp;gt;de.fhem.Device-SetOnOff&amp;lt;/code&amp;gt; untergebracht. Ein einzelnes Gerät kann sich auch in mehreren Slots befinden. Um eine möglichst genaue Spracherkennung zu gewährleisten, ist &#039;&#039;&#039;empfohlen&#039;&#039;&#039;, diese &#039;&#039;&#039;spezifischen Slots&#039;&#039;&#039; - statt einfach nur &amp;lt;code&amp;gt;de.fhem.Device&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;de.fhem.Group&amp;lt;/code&amp;gt; - &#039;&#039;&#039;zu verwenden&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetOnOff ===&lt;br /&gt;
Intent um Geräte zwischen zwei Zuständen (ein/aus, auf/zu, start/stop) zu schalten.&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
SetOnOff:cmdOn=on,cmdOff=off&lt;br /&gt;
SetOnOff:cmdOn=on,cmdOff=off,response=&amp;quot;Sir yes Sir&amp;quot;&lt;br /&gt;
SetOnOff:cmdOn=on,cmdOff=off,response=&amp;quot;$DEVICE now [$DEVICE:state]&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Argumente:&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdOn&amp;lt;/code&amp;gt; Befehl um das Gerät einzuschalten. Siehe [[#Formatierung von Befehlen und Readings innerhalb eines rhasspyMappings|Formatierung von Befehlen und Readings innerhalb eines rhasspyMappings]].&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdOff&amp;lt;/code&amp;gt; Befehl um das Gerät auszuschalten. Siehe [[#Formatierung von Befehlen und Readings innerhalb eines rhasspyMappings|Formatierung von Befehlen und Readings innerhalb eines rhasspyMappings]].&lt;br /&gt;
&lt;br /&gt;
Optionale Argumente:&lt;br /&gt;
*&amp;lt;code&amp;gt;response&amp;lt;/code&amp;gt; Eine benutzerdefinierte Antwort auf den Befehl&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
schalten das licht ein&lt;br /&gt;
schließe den rollladen im schlafzimmer&lt;br /&gt;
starte die kaffeemaschine&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetOnOff]&lt;br /&gt;
(schalte|schalt|mache|mach|stelle|stell|starte) [den|die|das] $de.fhem.Device-SetOnOff{Device} [[(im|in dem|auf dem|in der|auf der)] $de.fhem.Room{Room}] (an|ein){Value:on}&lt;br /&gt;
(schalte|schalt|mache|mach|stelle|stell) [den|die|das] $de.fhem.Device-SetOnOff{Device} [[(im|in dem|auf dem|in der|auf der)] $de.fhem.Room{Room}] aus{Value:off}&lt;br /&gt;
(fahre|fahr) [den|die|das] $de.fhem.Device-blind{Device} [[(im|in dem|auf dem|in der|auf der)] $de.fhem.Room{Room}] ((hoch|auf){Value:on}|(zu|runter){Value:off})&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verpflichtende Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Value:on&amp;lt;/code&amp;gt; und/oder &amp;lt;code&amp;gt;Value:off&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetOnOffGroup ===&lt;br /&gt;
Intent um Gruppen von Geräte zwischen zwei Zuständen zu schalten.&lt;br /&gt;
&lt;br /&gt;
Dafür ist ein SetOnOff-Mapping benötigt und alle gewünschten Geräte müssen (ggf. u.A. auch) der gewählten Gruppe angehören (einzustellen über das Attribut &amp;lt;code&amp;gt;group&amp;lt;/code&amp;gt; bzw. &amp;lt;code&amp;gt;rhasspyGroup&amp;lt;/code&amp;gt;, oder allgemein kommend aus rhasspyTweaks - gdt2groups).&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
schalte die lampen in der küche aus&lt;br /&gt;
schließe alle rollläden im schlafzimmer&lt;br /&gt;
schalte sämtliche lampen aus&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetOnOffGroup]&lt;br /&gt;
\[(schalt|mach)] (die | alle | sämtliche ) $de.fhem.Group-SetOnOff{Group} [[in|im|in der|auf der] [( überall:global | $de.fhem.Room ){Room}] ein{Value:on}&lt;br /&gt;
\[(schalt|mach)] (die | alle | sämtliche ) $de.fhem.Group-SetOnOff{Group} [[in|im|in der|auf der] [( überall:global | $de.fhem.Room ){Room}] aus{Value:off}&lt;br /&gt;
(öffne{Value:on}|schließe{Value:off}) (alle | sämtliche ) $de.fhem.Group-blind{Group} [[in|im|in der|auf der] [( überall:global{Room:global} | $de.fhem.Room{Room} )] &lt;br /&gt;
(fahr|fahre|mach|mache) [den|die|das] $de.fhem.Group-blind{Group} [[(im|in dem|in der)] ( überall:global{Room:global} | $de.fhem.Room{Room} )] ( auf{Value:on} | hoch{Value:on} | zu{Value:off} | runter{Value:off} )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verpflichtende Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Value:on&amp;lt;/code&amp;gt; und/oder &amp;lt;code&amp;gt;Value:off&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Group&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== SetTimedOnOff ===&lt;br /&gt;
Intent um Geräte für eine bestimmte Zeitspanne in einen bestimmten Zustand zu versetzten.&lt;br /&gt;
&lt;br /&gt;
Device muss ein SetOnOff-Mapping haben und die {{Link2CmdRef|Anker=setExtensions|Lang=de|Label=SetExtentions}} unterstützen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
schalte das licht für eine minute und dreißig sekunden aus&lt;br /&gt;
schalte die musik im bad bis zwei uhr ein&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetTimedOnOff]&lt;br /&gt;
schalte $de.fhem.Device-SetOnOff{Device} [$de.fhem.Room{Room}] für ([(1..60){Hour!int} (stunde|stunden)] [und] [(1..60){Min!int} (minute|minuten)] [und] [(1..60){Sec!int} (sekunde|sekunden)]) (ein{Value:on}|aus{Value:off})&lt;br /&gt;
schalte $de.fhem.Device-SetOnOff{Device} [$de.fhem.Room{Room}] bis (0..24){Hourabs!int} [(1..60){Min!int}] (ein{Value:on}|aus{Value:off})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verpflichtende Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Value&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Hour&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Min&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Sec&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Hourabs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetTimedOnOffGroup ===&lt;br /&gt;
Intent um eine Gruppe von Geräten für eine bestimmte Zeit zu schalten.&lt;br /&gt;
&lt;br /&gt;
Devices müssen ein SetOnOff-Mapping haben, in einer Gruppe sein und die {{Link2CmdRef|Anker=setExtensions|Lang=de|Label=SetExtentions}} unterstützen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
schalte alle lichter in der küche für fünfzig sekunden ein&lt;br /&gt;
schalte alle licher bis zwei uhr ein&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetTimedOnOffGroup]&lt;br /&gt;
schalte $de.fhem.Group-SetOnOff{Group} [$de.fhem.Room{Room}] für ([(1..60){Hour!int} (stunde|stunden)] [und] [(1..60){Min!int} (minute|minuten)] [und] [(1..60){Sec!int} (sekunde|sekunden)]) (ein{Value:on}|aus{Value:off})&lt;br /&gt;
schalte $de.fhem.Group-SetOnOff{Group} [$de.fhem.Room{Room}] bis (0..24){Hourabs!int} [(1..60){Min!int}] (ein{Value:on}|aus{Value:off})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verpflichtende Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Value&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Group&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Hour&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Min&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Sec&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Hourabs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GetOnOff ===&lt;br /&gt;
Intent um den aktuellen Zustand eines Gerätes zu erfragen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
GetOnOff:currentVal=state,valueOff=closed&lt;br /&gt;
GetOnOff:currentVal=state,valueOn=on&lt;br /&gt;
GetOnOff:currentVal=pct,valueOff=0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Argumente:&lt;br /&gt;
Hinweis: nur &amp;lt;code&amp;gt;valueOn&amp;lt;/code&amp;gt; ODER &amp;lt;code&amp;gt;valueOff&amp;lt;/code&amp;gt; müssen gesetzt werden. Der jeweils andere Wert bekommt den anderen Status.&lt;br /&gt;
*&amp;lt;code&amp;gt;currentVal&amp;lt;/code&amp;gt; Reading aus dem der aktuelle Status hervorgeht&lt;br /&gt;
*&amp;lt;code&amp;gt;valueOff&amp;lt;/code&amp;gt; Wert, der den Zustand &#039;&#039;aus&#039;&#039; beschreibt&lt;br /&gt;
*&amp;lt;code&amp;gt;valueOn&amp;lt;/code&amp;gt; Wert, der den Zustand &#039;&#039;an&#039;&#039; beschreibt&lt;br /&gt;
&lt;br /&gt;
Optionale Argumente:&lt;br /&gt;
*&amp;lt;code&amp;gt;response&amp;lt;/code&amp;gt; Eine benutzerdefinierte Antwort auf den Befehl&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
ist das licht im bad ein&lt;br /&gt;
ist das fenster im wohnzimmer geöffnet&lt;br /&gt;
läuft die waschmaschine&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[en.fhem:GetOnOff]&lt;br /&gt;
ist $de.fhem.Device-GetOnOff{Device} [$de.fhem.Room{Room}] (ein|geöffnet){State:on}&lt;br /&gt;
ist $de.fhem.Device-GetOnOff{Device} [$de.fhem.Room{Room}] (aus|geschlossen){State:off}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zustände &#039;&#039;ein&#039;&#039; und &#039;&#039;aus&#039;&#039; sollten in unterschiedlichen Sentences sein und müssen &amp;lt;code&amp;gt;{State:on}&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;{State:off}&amp;lt;/code&amp;gt; beinhalten.&lt;br /&gt;
&lt;br /&gt;
Verpflichtende Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;State:on&amp;lt;/code&amp;gt; und/oder &amp;lt;code&amp;gt;State:off&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetNumeric ===&lt;br /&gt;
Intent, um Lampen zu dimmen, Rollladengeräte zu positionieren, Lautstärken oder Solltemperaturen zu ändern, usw.. &lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
SetNumeric:currentVal=pct,cmd=dim,minVal=0,maxVal=99,step=25,type=brightness&lt;br /&gt;
SetNumeric:currentVal=volume,cmd=volume,minVal=0,maxVal=99,step=10,type=volume&lt;br /&gt;
SetNumeric:currentVal=brightness,cmd=brightness,minVal=0,maxVal=255,map=percent,step=1,type=brightness&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Argumente:&lt;br /&gt;
*&amp;lt;code&amp;gt;currentVal&amp;lt;/code&amp;gt; Reading, in dem der aktuelle Wert zu finden ist (wird zwingend benötigt).&lt;br /&gt;
*&amp;lt;code&amp;gt;part&amp;lt;/code&amp;gt; Kann genutzt werden, um den Wert aus **currentVal** in mehrere Teile zu zerlegen (getrennt wird am Leerzeichen). Z.B. wenn currentVal 23 C ist, wird **part=0** **23** ergeben. Optionaler Parameter.&lt;br /&gt;
*&amp;lt;code&amp;gt;cmd&amp;lt;/code&amp;gt; Das **Set**-Kommando des Geräts, das in Folge des Sprachkommandos ausgeführt werden soll. (Notwendiger Parameter).&lt;br /&gt;
*&amp;lt;code&amp;gt;minVal&amp;lt;/code&amp;gt; Niedrigster zugelassener Wert, optional.&lt;br /&gt;
*&amp;lt;code&amp;gt;maxVal&amp;lt;/code&amp;gt; Höchster zugelassener Wert, optional.&lt;br /&gt;
*&amp;lt;code&amp;gt;step&amp;lt;/code&amp;gt; Schrittweite für relative Änderungen wie &amp;lt;code&amp;gt;mach lauter&amp;lt;/code&amp;gt;. Optional. Default: 10.&lt;br /&gt;
*&amp;lt;code&amp;gt;map&amp;lt;/code&amp;gt; Derzeit wird ausschließlich die Angabe **percent** ausgewertet. Optionaler Parameter, der bewirkt, dass alle Angaben als Prozentwert (zwischen minVal und maxVal) interpretiert werden und entsprechend gerechnet wird. So wird z.B. eine Leuchte mit **minVal=0** und **maxVal=255** beim Befehl &amp;quot;stelle das Licht auf 50&amp;quot; dies so verstehen, als wäre die Anweisung &amp;quot;stelle das Licht auf 50 Prozent&amp;quot; gewesen. Das Licht wird daher auf 127 gestellt, und nicht auf (absolut) 50.&lt;br /&gt;
*&amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; Zur Unterscheidung, falls mehrere SetNumeric-Intents für das Gerät möglich sind. Empfohlener Parameter.&lt;br /&gt;
&lt;br /&gt;
Gut zu wissen:&lt;br /&gt;
Um Kommandos wie **lauter** oder **leiser** ohne Angabe eines Gerätes ausführen zu können, muss RHASSPY zunächst ermitteln, welches Gerät gerade überhaupt etwas wiedergibt ist. Daher nutzt es die GetOnOff-Mappings, um festzustellen, welches Gerät vom **type=volume** überhaupt angeschaltet ist. Dabei wird wie üblich zunächst im aktuellen rhasspyRoom gesucht, bevor die Suche außerhalb fortgesetzt wird.&lt;br /&gt;
Setzt man also Mappings manuell, ist es ratsam, auch ein **GetOnOff**-Mapping zu setzen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zulässige Typen sind:&lt;br /&gt;
*&amp;lt;code&amp;gt;brightness&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;setTarget&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;temperature&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;volume&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
Stelle das Licht auf 30 Prozent&lt;br /&gt;
Mach das Radio leiser&lt;br /&gt;
Stell die Temperatur im Wohnzimmer 2 Grad wärmer&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
(Beachte: Wenn wie hier im Beispiel reele Zahlen (mit Komma) ermöglicht werden sollen (&amp;quot;acht Komma fünf&amp;quot;), wird ein [[#Custom Converter für reelle Zahlen| Custom Converter für reelle Zahlen]] benötigt)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetNumeric]&lt;br /&gt;
den=(den|die|das)&lt;br /&gt;
cmdmulti=(schalte|schalt|mache|mach|stelle|stell)&lt;br /&gt;
rooms=([(im|in dem|auf dem|in der|auf der)] $de.fhem.Room{Room})&lt;br /&gt;
&amp;lt;cmdmulti&amp;gt; [&amp;lt;den&amp;gt;] $de.fhem.Device-SetNumeric{Device} auf (0..100){Value!int} [Prozent{Unit:percent}]&lt;br /&gt;
\[&amp;lt;cmdmulti&amp;gt;] [die Lautstärke [an|am]] [dem|&amp;lt;den&amp;gt;] $de.fhem.Device-media{Device} [&amp;lt;rooms&amp;gt;] [um] [(0..10){Value!float}] [dezibel{Unit:decibel}|Prozent{Unit:percent}] ( lauter:volUp | leiser:volDown ){Change}&lt;br /&gt;
&amp;lt;cmdmulti&amp;gt; [die Lautstärke [an|am]] [dem|&amp;lt;den&amp;gt;] [$de.fhem.Device-media{Device}] [&amp;lt;rooms&amp;gt;] [um] [(0..10){Value!float}] [dezibel{Unit:decibel}|Prozent{Unit:percent}] ( lauter:volUp | leiser:volDown ){Change}&lt;br /&gt;
&amp;lt;cmdmulti&amp;gt; [&amp;lt;den&amp;gt;] $de.fhem.Device-thermostat{Device} [&amp;lt;rooms&amp;gt;] [um] [(0..10){Value!int}] [Grad{Unit.degree}] ( wärmer:tempUp | kälter:tempDown ){Change}&lt;br /&gt;
&amp;lt;cmdmulti&amp;gt; [&amp;lt;den&amp;gt;] $de.fhem.Device-light{Device} [&amp;lt;rooms&amp;gt;] [um] [(0..30 [Komma:. 1..9]){Value!customFloat}] [Prozent{Unit:percent}] ( heller:lightUp | dunkler:lightDown){Change}&lt;br /&gt;
&amp;lt;cmdmulti&amp;gt; [&amp;lt;den&amp;gt;] ( $de.fhem.Device-light | $de.fhem.Device-media |$de.fhem.Device-blind){Device}  [&amp;lt;rooms&amp;gt;] auf [(0..30 [Komma:. 1..9]){Value!customFloat}]&lt;br /&gt;
\[deutlich{Factor:2}] ( mehr{Change:lightUp} | weniger{Change:lightDown} ) $de.fhem.Device-light{Device} [&amp;lt;de.fhem:SetOnOff.rooms&amp;gt;]&lt;br /&gt;
( halte | stoppe | stop ) [&amp;lt;den&amp;gt;] $de.fhem.Device-blind{Device} [&amp;lt;de.fhem:SetOnOff.rooms&amp;gt;] [an] {Change:cmdStop}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Derzeit werden folgende Typen für das Feld &amp;lt;code&amp;gt;{Change}&amp;lt;/code&amp;gt; ausgewertet:&lt;br /&gt;
*&amp;lt;code&amp;gt;tempUp&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;tempDown&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;volUp&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;volDown&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;lightUp&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;lightDown&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;setUp&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;setDown&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notwendig sind:&lt;br /&gt;
*&amp;lt;code&amp;gt;Change&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Type&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Value&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Change&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Unit&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Factor&amp;lt;/code&amp;gt; Dieser Wert wird mit der Standard-Schrittweite (&amp;lt;code&amp;gt;step&amp;lt;/code&amp;gt; im Mapping) multipliziert&lt;br /&gt;
&lt;br /&gt;
=== SetNumericGroup ===&lt;br /&gt;
Intent, um Lampen zu dimmen, Rollladengeräte zu positionieren, Lautstärken oder Solltemperaturen zu ändern, usw.. Die Funktionsweise entspricht dabei dem des Intents &#039;&#039;SetNumeric&#039;&#039;, wobei eben statt eines einzelnen Devices eben ein oder mehrere Geräte über ihren Gruppennamen angesprochen werden. Statt des optionalen Tags &amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt; ist daher der Tag &amp;lt;code&amp;gt;Group&amp;lt;/code&amp;gt; zu übergeben.&lt;br /&gt;
Aus der Adressierung mehrerer Geräte ergeben sich einige Besonderheiten, die in der [[RHASSPY/Vertiefung]], dort speziell auch im Punkt [[RHASSPY/Vertiefung#Beispiel_SetOnOffGroup|Beispiel SetOnOffGroup]] näher erläutert sind. Wesentliche zu beachtende Aspekte sind:&lt;br /&gt;
* Vermeidung von Funk-Überschneidungen (&#039;&#039;Specials&#039;&#039; &#039;&#039;partOf&#039;&#039; und &#039;&#039;async_delay&#039;&#039;)&lt;br /&gt;
* Begrenzung der Gruppenzugehörigkeit durch die Raumzugehörigkeit (und die Aufhebung dieser Beschränkung durch die Übergabe des speziellen Raums &#039;&#039;global&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
=== GetNumeric ===&lt;br /&gt;
Intent, mit dem man Werte erfragen kann, wie z.B. die aktuelle Temperatur, Helligkeit, Lautstärke, ...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
GetNumeric:currentVal=temperature,part=1,type=temperature&lt;br /&gt;
GetNumeric:currentVal=pct,map=percent,minVal=0,maxVal=100,type=brightness&lt;br /&gt;
GetNumeric:currentVal=volume,type=volume&lt;br /&gt;
GetNumeric:currentVal=humidity,part=0,type=humidity&lt;br /&gt;
GetNumeric:currentVal=batteryPercent,type=battery&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Argumente:&lt;br /&gt;
*&amp;lt;code&amp;gt;currentVal&amp;lt;/code&amp;gt; Das Reading, das den abzufragenden Wert enthält&lt;br /&gt;
*&amp;lt;code&amp;gt;part&amp;lt;/code&amp;gt; Teile aus currentVal ableiten, indem am Leerzeichen getrennt wird. Ist &#039;&#039;currentVal&#039;&#039; beispielsweise &#039;&#039;23 C&#039;&#039;, entspricht &#039;&#039;part=1&#039;&#039; dem Wert &#039;&#039;23&#039;&#039;&lt;br /&gt;
*&amp;lt;code&amp;gt;map&amp;lt;/code&amp;gt; Die Funktionswiese entspricht dem &#039;&#039;SetNumeric&#039;&#039; Intent. Wandelt den vorhandenen Wert in eine Prozent-Angabe um.&lt;br /&gt;
*&amp;lt;code&amp;gt;minVal&amp;lt;/code&amp;gt; Niedrigster zulässiger Wert (nur benötigt, wenn &#039;&#039;map&#039;&#039; angegeben ist).&lt;br /&gt;
*&amp;lt;code&amp;gt;maxVal&amp;lt;/code&amp;gt; Höchster zulässiger Wert  (nur benötigt, wenn &#039;&#039;map&#039;&#039; angegeben ist).&lt;br /&gt;
*&amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; Dient der Unterscheidung zwischen mehreren GetNumeric-Anfragemöglichkeiten für dasselbe Gerät (auch relevant für SetNumeric-Anweisungen).&lt;br /&gt;
&lt;br /&gt;
Mögliche Abfragetypen:&lt;br /&gt;
*&amp;lt;code&amp;gt;humidity&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;battery&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;brightness&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;desired-temp&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;setTarget&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;soilMoisture&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;temperature&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;volume&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;waterLevel&amp;lt;/code&amp;gt;&lt;br /&gt;
Aus dem Abfragetypen ergibt sich die von RHASSPY ausgewählte Antwort.&lt;br /&gt;
&lt;br /&gt;
Beispiel Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
what is the temperature in the living room&lt;br /&gt;
how bright is the floor lamp&lt;br /&gt;
what is the volume of the tv&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
[en.fhem:GetNumeric]&lt;br /&gt;
#actual temperature&lt;br /&gt;
(what is|how high is) the temperature{Type:temperature} [$de.fhem.Device-GetNumeric{Device}] [$de.fhem.Room{Room}]&lt;br /&gt;
&lt;br /&gt;
#desired-temperature&lt;br /&gt;
\[what is the|how high is the] (desired temperature){Type:desired-temp} [$de.fhem.Device-GetNumeric{Device}] [$de.fhem.Room{Room}]&lt;br /&gt;
&lt;br /&gt;
#volume&lt;br /&gt;
(what is the|how high is the) volume{Type:volume} $de.fhem.Device-GetNumeric{Device} [$de.fhem.Room{Room}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Type&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional tags&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== GetState ===&lt;br /&gt;
Intent to get specific information of a device. The respone can be defined.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
GetState:response=&amp;quot;Temperature is [$DEVICE:temp] degree at [Thermo:hum] percent humidity&amp;quot;&lt;br /&gt;
GetState:response={my $value=ReadingsVal(&amp;quot;$DEVICE&amp;quot;,&amp;quot;brightness&amp;quot;,&amp;quot;&amp;quot;); return &amp;quot;Brightness is $value&amp;quot;;}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Options:&lt;br /&gt;
*&amp;lt;code&amp;gt;response&amp;lt;/code&amp;gt; Text for the response Rhassyp will give.&lt;br /&gt;
:To use values from FHEM use format [Device:Reading].&lt;br /&gt;
:A comma within the response has to be escaped (\, instead of ,).&lt;br /&gt;
:Or you can use Perl-code enclosed in curley brackets to define the response.&lt;br /&gt;
:Mixing text and Perl-code is not supported.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
How is the state of the thermostat in the kitchen&lt;br /&gt;
state light in livingroom&lt;br /&gt;
state washer&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:GetState]&lt;br /&gt;
\[how is the] (state) $de.fhem.Device{Device} [$de.fhem.Room{Room}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== MediaControls ===&lt;br /&gt;
Intent to control media devices&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mapping:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
MediaControls:cmdPlay=play,cmdPause=pause,cmdStop=stop,cmdBack=previous,cmdFwd=next&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Options:&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdPlay&amp;lt;/code&amp;gt; Play command of the device. See chapter Formatting Commands and Readings inside a rhasspyMapping.&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdPause&amp;lt;/code&amp;gt; Command to pause the device.&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdStop&amp;lt;/code&amp;gt; Command to stop the device.&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdFwd&amp;lt;/code&amp;gt; Command to skip to the next track/channel/etc.&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdBack&amp;lt;/code&amp;gt; Command to skip to the previous track/channel/etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note on issuing a voice-command without a room-name:&lt;br /&gt;
As described in the SetNumeric-Intent, it is recommended to define a GetOnOff-Mapping to use the MediaControls-Intent without a room name.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
skip to next track on the radio&lt;br /&gt;
pause&lt;br /&gt;
skip video on the dvd player&lt;br /&gt;
stop playback&lt;br /&gt;
next&lt;br /&gt;
previous&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:MediaControls]&lt;br /&gt;
(start){Command:cmdPlay} the playback [$de.fhem.Device-MediaControls{Device}]&lt;br /&gt;
(stop){Command:cmdStop} the playback [$de.fhem.Device-MediaControls{Device}]&lt;br /&gt;
(pause){Command:cmdPause} the playback [$de.fhem.Device-MediaControls{Device}]&lt;br /&gt;
(next){Command:Fwd} (song|title) [$de.fhem.Device-MediaControls{Device}]&lt;br /&gt;
(previous){Command:Back} (song|title) [$de.fhem.Device-MediaControls{Device}] [$de.fhem.Room{Room}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Command&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== MediaChannels ===&lt;br /&gt;
Intent to change radio-/tv channels, favorites, playlists, lightscenes, ...&lt;br /&gt;
&lt;br /&gt;
Instead of using the attribute rhasspyMapping, this intent is configured with an own attribute [[#rhasspyChannels]] in the respective device. Reason is the multiple-line-configuration.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
SWR3=favorite s_w_r_3&lt;br /&gt;
SWR1=favorite s_w_r_1&lt;br /&gt;
ARD=channel 204&lt;br /&gt;
Netflix=launchApp Netflix&lt;br /&gt;
Leselicht=set lightSceneWz scene Leselicht&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Notice on using the commands without a device name:&lt;br /&gt;
To start playback on a device without specifying the device name in the voice command, the module needs to know, which device should be used. Therefor it searches the attribute rhasspyChannels for suitable one. Devices in the actual or spoken room are preferred.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
play CNN on the radio in my office&lt;br /&gt;
switch to HBO&lt;br /&gt;
change channel on radio to BBC news&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[en.fhem:MediaChannels]&lt;br /&gt;
\[(play|switch to|change to)] ($de.fhem.MediaChannels){Channel} [($de.fhem.Device){Device}] [($de.fhem.Room){Room}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Channel&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetColor ===&lt;br /&gt;
Intent to change light colors&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Because of the multi-line settings, instead of configuring this intent with the attribute rhasspyMapping, a separate user-attribute [[#rhasspyColors]] is used.&lt;br /&gt;
&lt;br /&gt;
The content of the rhasspyColors uses the following format:&lt;br /&gt;
&amp;lt;code&amp;gt;Colorname=cmd&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Settings:&lt;br /&gt;
*&amp;lt;code&amp;gt;Colorname&amp;lt;/code&amp;gt; The name of the color you want to use in a voice-command&lt;br /&gt;
*&amp;lt;code&amp;gt;cmd&amp;lt;/code&amp;gt; The FHEM-command&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
red=rgb FF0000&lt;br /&gt;
green=rgb 00FF00&lt;br /&gt;
blue=rgb 0000FF&lt;br /&gt;
white=ct 3000&lt;br /&gt;
warm white=ct 2700&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
change light to green&lt;br /&gt;
lightstrip blue&lt;br /&gt;
color the light in the sleeping room white&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[en.fhem:SetColor]&lt;br /&gt;
\[change|color] $de.fhem.Device{Device} [$de.fhem.Room{Room}] $de.fhem.Color{Color}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Color&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional tags&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetColorGroup ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetScene ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GetTime ===&lt;br /&gt;
Intent um die Uhrzeit zu erfragen.&lt;br /&gt;
&lt;br /&gt;
Es werden keine Konfigurationen in FHEM benötigt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
wie spät ist es?&lt;br /&gt;
sag mir die uhrzeit&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:GetTime]&lt;br /&gt;
wie spät [ist es]&lt;br /&gt;
sag mir die uhrzeit&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GetDate ===&lt;br /&gt;
Intent um das aktuelle Datum zu erfragen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Keine FHEM Einstellungen nötig.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Satz:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
welcher tag ist heute&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:GetDate]&lt;br /&gt;
welcher tag ist heute&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetTimer ===&lt;br /&gt;
Intent to create a timer/countdown/alarm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This intent creates an AT-command in FHEM with the given time and - currently - speaks the sentences &amp;quot;timer expired&amp;quot; when it has expired.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
No FHEM-settings needed&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
Set timer in bedroom to five minutes&lt;br /&gt;
Set countdown in the kitchen to two hours&lt;br /&gt;
set timer to five and a half hours&lt;br /&gt;
set alarm to 5 o&#039; clock&lt;br /&gt;
set timer to 3 hours and 20 minutes&lt;br /&gt;
set timer to 1 hour, 30 minutes and 15 seconds&lt;br /&gt;
stop the timer in bedroom&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentence:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetTimer]&lt;br /&gt;
labels=(alarm|teetimer|countdown|timer)&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in) [((1..60){Hour!int} (hour|hours))] [and] [((1..60){Min!int} (minute|minutes))] [and] [((1..60){Sec!int} (second|seconds))]&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in) (1..60){Hour!int} and (a quarter{Min:15}|a half{Min:30}|three quarters{Min:45}) (hour|hours)&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in) (1..60){Min!int} and (a quarter{Sec:15}|a half{Sec:30}|three quarters{Sec:45}) (minute|minutes)&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in) ((the fourth){Min:15}|(half a){Min:30}|(three fourth){Min:45}) (hour)&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in) ((the fourth){Min:15}|(half a){Min:30}|(three fourth){Min:45}) (minute)&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in|at) (1..24){Hourabs!int} [(1..60){Min!int}] o clock&lt;br /&gt;
&lt;br /&gt;
(cancel|remove|stop|delete){CancelTimer} [&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags to set a timer:&lt;br /&gt;
*&amp;lt;code&amp;gt;Label&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Hour&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Hourabs&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Min&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Sec&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags to cancel a timer:&lt;br /&gt;
*&amp;lt;code&amp;gt;Label&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
rhasspyTweaks for Timer:&lt;br /&gt;
*&amp;lt;code&amp;gt;[[#attr-rhasspytweaks-timerlimits|timerLimits]]&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;[[#attr-rhasspytweaks-timersounds|timerSounds]]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetMute ===&lt;br /&gt;
Intent to disable/enable the processing of intents on a specific siteId. Rhasspy will still listen to the wakeword but will not process any intents.&lt;br /&gt;
&lt;br /&gt;
This intents creates a Reading &amp;lt;code&amp;gt;mute_siteId&amp;lt;/code&amp;gt; for every siteId it get&#039;s a voice-command from.&lt;br /&gt;
&lt;br /&gt;
No FHEM-settings needed&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
good night&lt;br /&gt;
be quiet&lt;br /&gt;
good morning&lt;br /&gt;
make noise&lt;br /&gt;
start listening&lt;br /&gt;
stop listening&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel für Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetMute]&lt;br /&gt;
(good night|be quiet){Value:on}&lt;br /&gt;
(good morning|make noise){Value:off}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hinweis: Die Felder &amp;lt;code&amp;gt;{Value:on}&amp;lt;/code&amp;gt; bzw. &amp;lt;code&amp;gt;{Value:off}&amp;lt;/code&amp;gt; sind verpflichtend und &#039;&#039;case sensitive&#039;&#039;, der Wert &#039;&#039;on&#039;&#039; bzw. &#039;&#039;off&#039;&#039; ist in Englisch anzugeben!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ConfirmAction ===&lt;br /&gt;
Dies ist - wie die folgenden Intents &#039;&#039;CancelAction&#039;&#039; und &#039;&#039;Choice&#039;&#039; (bzw. die überholten Varianten &#039;&#039;ChoiceRoom&#039;&#039; und &#039;&#039;ChoiceDevice&#039;&#039;) auch - ein Intent, der im Rahmen von Dialogen benötigt wird. Siehe dazu auch [[RHASSPY/Vertiefung#Dialoge|Vertiefung - Dialoge]].&lt;br /&gt;
Um eine Aktion tatsächlich auszuführen, ist als Rückgabe zwingend &amp;lt;code&amp;gt;{Mode}&amp;lt;/code&amp;gt; mit dem Wert &#039;&#039;OK&#039;&#039; erforderlich, alles andere wird so behandelt, als wäre der Intent &#039;&#039;CancelAction&#039;&#039; ausgewählt worden, was zur Beendigung des Dialogs ohne Aktion führt.&lt;br /&gt;
&lt;br /&gt;
=== CancelAction ===&lt;br /&gt;
Siehe &#039;&#039;ConfirmAction&#039;&#039;. Dieser Intent muss nicht zwingend existieren, es kann auch ein unpassender Rückgabewert in &#039;&#039;ConfirmAction&#039;&#039; angegeben werden, um die Abbruch-Routinen für Dialoge zu starten.&lt;br /&gt;
&lt;br /&gt;
=== Choice ===&lt;br /&gt;
Siehe &#039;&#039;ConfirmAction&#039;&#039;. Dient im Rahmen von Dialogen der Auswahl von einem oder mehreren der folgenden Elemente:&lt;br /&gt;
&amp;lt;code&amp;gt;{Device}&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;{Room}&amp;lt;/code&amp;gt; und/oder &amp;lt;code&amp;gt;{Scene}&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Beispiel für Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:Choice]&lt;br /&gt;
den=(den|die|das)&lt;br /&gt;
choose= ( nimm [bitte] | [bitte] nimm | ich hätte gerne | [ich] (wähle|nehme) )&lt;br /&gt;
&lt;br /&gt;
&amp;lt;choose&amp;gt; [ &amp;lt;den&amp;gt; [( Gerät | $de.fhem.Aliases{Device} )] ] ( aus ( dem | der ) | im | den | die ) $de.fhem.MainRooms{Room}&lt;br /&gt;
&amp;lt;choose&amp;gt; [ &amp;lt;den&amp;gt; ] $de.fhem.Aliases{Device} [ ( aus ( dem | der ) | im | den | die ) $de.fhem.MainRooms{Room} ]&lt;br /&gt;
&amp;lt;choose&amp;gt; [ ( die Szene | den Modus ) ] $de.fhem.Scenes [Modus] [ [( am | vom )] $de.fhem.Aliases{Device} ] [( aus ( dem | der ) | im | den | die ) $de.fhem.MainRooms{Room} ] [bitte]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== ChoiceRoom ====&lt;br /&gt;
Veralteter Intent. Diente im Rahmen von Dialogen der Auswahl eines Raums, wird heute pauschal nach &#039;&#039;Choice&#039;&#039; umgeleitet und sollte nicht mehr verwendet werden!&lt;br /&gt;
&lt;br /&gt;
==== ChoiceDevice ====&lt;br /&gt;
Veralteter Intent. Diente im Rahmen von Dialogen der Auswahl eines Gerätes, wird heute pauschal nach &#039;&#039;Choice&#039;&#039; umgeleitet und sollte nicht mehr verwendet werden!&lt;br /&gt;
&lt;br /&gt;
=== ReSpeak ===&lt;br /&gt;
Wiederholt den letzten Satz, den Rhasspy gesprochen hat. Um genauer zu sein: Spricht den Inhalt des FHEM Readings &amp;lt;code&amp;gt;voiceResponse&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Keine Einstellungen in FHEM benötigt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
was hast du gesagt&lt;br /&gt;
kannst du das wiederholen&lt;br /&gt;
ich habe dich nicht verstanden&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:ReSpeak]&lt;br /&gt;
was hast du gesagt&lt;br /&gt;
kannst du das [bitte] wiederholen&lt;br /&gt;
ich habe dich nicht verstanden&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Eigene Intents erstellen ==&lt;br /&gt;
Es ist auch möglich, eigene Intents zu erstellen, sollten die hier vorgestellten nicht reichen. Dafür gibt es zwei Wege: Für kleinere Intents können die Möglichkeiten von FHEMs [[99_myUtils_anlegen|99_myUtils.pm]] genutzt werden. Aufwendigere Intents können in jeweils eigenen Dateien abgelegt werden, die dann von RHASSPY ausgelesen werden.&lt;br /&gt;
=== Intents in 99_myUtils.pm ===&lt;br /&gt;
&lt;br /&gt;
Hier ein (veraltetes, siehe oben) Beispiel, mit dem die letzte &#039;&#039;voice response&#039;&#039; wiederholt werden kann.&lt;br /&gt;
&lt;br /&gt;
Ergänze deine 99_myUtils.pm mit folgender Funktion:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub Respeak(){&lt;br /&gt;
  #Credits to JensS&lt;br /&gt;
  my $name = &amp;quot;Rhasspy&amp;quot;; #Replace &amp;quot;Rhasspy&amp;quot; with the name of your RHASSPY-Device&lt;br /&gt;
  my $response = ReadingsVal($name,&amp;quot;voiceResponse&amp;quot;,&amp;quot;Ich kann mich leider nicht erinnern&amp;quot;);&lt;br /&gt;
  return $response;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ergänze im Attribut &#039;&#039;rhasspyIntents&#039;&#039; folgende Zeile (je Intent muss eine eigene Zeile verwendet werden):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
Respeak=Respeak()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ergänze einen neuen Intent in deinen &#039;&#039;sentence.ini&#039;&#039; an der Rhasspy base:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:Respeak]&lt;br /&gt;
was hast du gesagt&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Intents in eigenen Dateien ===&lt;br /&gt;
Beispiele: https://github.com/fhem/fhem-rhasspy/blob/main/FHEM/99_RHASSPY_Utils_Demo.pm&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: Raumwechsel ====&lt;br /&gt;
Erforderlichen Code in das Modulverzeichnis holen und laden: &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;{ Svn_GetFile(&#039;contrib/RHASSPY/99_RHASSPY_Utils_siteId2room.pm&#039;, &#039;FHEM/99_RHASSPY_Utils_siteId2room.pm&#039;,sub(){ RHASSPY_Utils_siteId2room_Initialize() }) }&amp;lt;/syntaxhighlight&amp;gt;Ergänze im Attribut &#039;&#039;rhasspyIntents&#039;&#039; folgende Zeile (je Intent muss eine eigene Zeile verwendet werden):&lt;br /&gt;
&amp;lt;syntaxhighlight  lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
siteId2room=RHASSPY::siteId2room::siteId2room(NAME,DATA)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Ergänze einen neuen Intent in deinen &#039;&#039;sentence.ini&#039;&#039; an der Rhasspy base:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:siteId2room]&lt;br /&gt;
( Ortswechsel  | begib dich ) ( ins | in den ) $de.fhem.Room{Room}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tipps &amp;amp; Tricks ==&lt;br /&gt;
===Custom Converter für reelle Zahlen===&lt;br /&gt;
{{Randnotiz|RNTyp=g|RNText=RHASSPY enthält für &amp;lt;code&amp;gt;{Value}&amp;lt;/code&amp;gt; nunmehr auch einen Konverter, der Leerzeichen aus Zahlenwerten entfernt. Enthält dieses Datenfeld bei der Übergabe aus Rhasspy z.B. &amp;lt;code&amp;gt;- 10 .5&amp;lt;/code&amp;gt;, wird dies automatisch in &amp;lt;code&amp;gt;-10.5&amp;lt;/code&amp;gt; umgewandelt.}}&lt;br /&gt;
Rhasspy kann (derzeit) keine gesprochenen reellen Nummern (z.B. 22,5) als Nummer erkennen. Stattdessen interpretiert es die Zahl als zwei Nummern und einen Punkt.&lt;br /&gt;
&lt;br /&gt;
Um reelle Nummern richtig zu verwenden, muss ein [https://rhasspy.readthedocs.io/en/latest/training/#converters Custom Converter] erstellt und in der sentences.ini verwendet werden.&lt;br /&gt;
&lt;br /&gt;
So ein Konverter kann erstellt werden, in dem unter &amp;lt;code&amp;gt;&amp;lt;profile&amp;gt;/converters&amp;lt;/code&amp;gt; ein neues File mit beliebigem Namen angelegt wird. Der Name muss aber dann auch genau so als Converter in der sentences.ini verwendet werden. Anschließend muss die Datei noch ausführbar gemacht werden.&lt;br /&gt;
&lt;br /&gt;
Z.B.:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
touch .config/rhasspy/profile/en/converters/customFloat&lt;br /&gt;
chmod +x .config/rhasspy/profile/en/converters/customFloat&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Folgender Beispiel-Code kann danach in die Datei geschrieben werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python3&lt;br /&gt;
import sys&lt;br /&gt;
import json&lt;br /&gt;
&lt;br /&gt;
# von Rhasspy als JSON übergebene/n Wert/e einlesen&lt;br /&gt;
args = json.load(sys.stdin)&lt;br /&gt;
&lt;br /&gt;
# wenn im deserialisierten JSON nur ein Wert ist, wird der als Ergebnis genommen&lt;br /&gt;
# sind mehrere Werte vorhanden (z.B. 22,.,5), werden die zu einem einzelnen String zusammen gesetzt&lt;br /&gt;
if type(args) == int:&lt;br /&gt;
    num = args&lt;br /&gt;
else:&lt;br /&gt;
    num = &amp;quot;&amp;quot;.join(str(s).strip() for s in args)&lt;br /&gt;
&lt;br /&gt;
# Ergebnis wird an Rhasspy übergeben&lt;br /&gt;
print(num)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nach einem Neustart von Rhasspy kann dieser Converter dann verwendet werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem.SetNumeric]&lt;br /&gt;
stelle die heizung auf (0..30 [komma:. 0..99]){Value!customFloat}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Rhasspy speaks actual state of device after switching it===&lt;br /&gt;
JensS wrote a short script to let Rhasspy speak the actual state of a FHEM-device after switching it with a voice-command.&lt;br /&gt;
Add the following to your 99_myUtils.pm&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub ResponseOnOff($){&lt;br /&gt;
  my ($dev) = @_;&lt;br /&gt;
  my $room;&lt;br /&gt;
  my $state = lc(ReadingsVal($dev,&amp;quot;state&amp;quot;,&amp;quot;in unknown state&amp;quot;));&lt;br /&gt;
  my $name = (split(/,/,AttrVal($dev,&amp;quot;rhasspyName&amp;quot;,&amp;quot;error&amp;quot;)))[0];&lt;br /&gt;
  if (AttrVal($dev,&amp;quot;rhasspyRoom&amp;quot;,&amp;quot;&amp;quot;)){$room = &amp;quot; in &amp;quot;.(split(/,/,AttrVal($dev,&amp;quot;rhasspyRoom&amp;quot;,&amp;quot;&amp;quot;)))[0]};&lt;br /&gt;
  $state=~s/.*on/turned on/;&lt;br /&gt;
  $state=~s/.*off/turned off/;&lt;br /&gt;
  return &amp;quot;Ok - &amp;quot;.$name.$room.&amp;quot; is now &amp;quot;.$state&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
and add a response to the SetOnOff-Mapping of a device&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
SetOnOff:cmdOn=on,cmdOff=off,response={ResponseOnOff($DEVICE)}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [https://github.com/rhasspy/rhasspy Rhasspy auf Github]&lt;br /&gt;
* [https://rhasspy.readthedocs.io/en/latest/ offizielle Rhasspy Doku-Seite]&lt;br /&gt;
* [https://community.rhasspy.org/ Offizielles Rhasspy Forum]&lt;br /&gt;
* [https://github.com/fhem/fhem-rhasspy fhem-rhasspy Modul auf GitHub]&lt;br /&gt;
* [https://github.com/Romkabouter/ESP32-Rhasspy-Satellite ESP32-basierte Hardware als Satelliten]&lt;br /&gt;
* [https://github.com/razzo04/rhasspy-mobile-app App für Android-Satelliten]&lt;br /&gt;
* [https://www.youtube.com/watch?v=sWVl0ZoXZEo Video zu sentences.ini]&lt;br /&gt;
[[Kategorie:Sprachsteuerung]]&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=RHASSPY&amp;diff=37535</id>
		<title>RHASSPY</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=RHASSPY&amp;diff=37535"/>
		<updated>2022-09-07T10:04:30Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: Hinweis auf Installation/Update via GitHub entfernt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
Diese Seite beschreibt die Konfiguration und Verwendung des Moduls 10_RHASSPY.pm. &lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=Anbindung von FHEM an den Rhasspy Sprachassistenten&lt;br /&gt;
|ModType=contrib&lt;br /&gt;
|ModCmdRef=RHASSPY&lt;br /&gt;
|ModForumArea=Frontends/Sprachsteuerung&lt;br /&gt;
|ModFTopic=119447&lt;br /&gt;
|ModTechName=10_RHASSPY.pm&lt;br /&gt;
|ModOwner=Beta-User ({{Link2FU|9229|Forum}}/[[Benutzer Diskussion:Beta-User|Wiki]]), drhirn ({{Link2FU|15727|Forum}}/[[Benutzer Diskussion:Drhirn|Wiki]])&lt;br /&gt;
}}&lt;br /&gt;
[[File:Rhasspy_fhem.png|thumb|right|Schematische Darstellung von Rhasspy und FHEM/RHASSPY]]&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
[https://github.com/rhasspy/rhasspy Rhasspy] ist eine Open Source Server-Lösung für Spracherkennung und Sprachsteuerung, welche auf einem RaspBerry Pi oder einem anderen Debian-basierten Serversystem lauffähig ist. Es handelt sich dabei um eine Sammlung von Programmen (=Skripten in der Python-Sprechweise), die unter einer einheitlichen und sehr  flexiblen Benutzungsoberfläche zusammengefasst sind. Die Besonderheit an Rhasspy ist, dass es nach der Installation komplett offline betrieben werden kann. Es werden also keine Daten an einen Server im Internet geschickt, und für den Betrieb nur für FHEM werden nur moderate Hardwareanforderungen gestellt - ein aktueller Raspberry Pi ab Modell 3B+ sollte in der Regel genügen.&lt;br /&gt;
&lt;br /&gt;
Die Anbindung weiterer Räume ist über sogenannte &amp;quot;Satelliten&amp;quot; möglich. Dies kann z.B. ein Pi Zero mit Mikro und Lautsprecher sein, ein ESP32 mit entsprechender Hardware oder ein Mobiltelefon mit Android und der entsprechenden App.&lt;br /&gt;
&lt;br /&gt;
Rhasspy besteht aus vielen unterschiedlichen Modulen (Hot-Word Erkennung, Text-to-Speech, Speech-to-Text, Intent Erkennung, etc.). Alle diese Module kommunizieren miteinander über das [[MQTT|MQTT]]-Protokoll.&lt;br /&gt;
&lt;br /&gt;
Das Modul [[RHASSPY]] prüft Teile des MQTT-Traffics, konvertiert diese JSON-Nachrichten in FHEM-Befehle und sendet Nachrichten zurück an Rhasspy um z.B. Antworten über Text-to-Speech auszugeben.&lt;br /&gt;
&lt;br /&gt;
RHASSPY verwendet das Modul 00_MQTT2_CLIENT.pm um Nachrichten zu empfangen und zu senden. Daher ist es notwendig, eine Instanz dieses Moduls als FHEM-Device zu erstellen, bevor RHASSPY verwendet werden kann.&lt;br /&gt;
&lt;br /&gt;
Hervorgegangen ist RHASSPY aus dem Snips-Modul, nachdem Snips an Sonos verkauft und anschließend eingestellt wurde. Danke also an Thyraz, der die grundlegenden Arbeiten erledigt hat!&lt;br /&gt;
&lt;br /&gt;
=== Konventionen ===&lt;br /&gt;
{{Hinweis| In diesem Artikel und der CommandRef werden folgende Schreibweisen verwendet:&lt;br /&gt;
* &#039;&#039;&#039;[[RHASSPY]]&#039;&#039;&#039; bezieht sich auf das FHEM-Modul&lt;br /&gt;
* &#039;&#039;&#039;rhasspy&#039;&#039;&#039; bezieht sich auf das das FHEM-Device&lt;br /&gt;
* &#039;&#039;&#039;Rhasspy&#039;&#039;&#039; bezeichnet die (zentrale) Serverinstallation}}&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|Dialoge werden in RHASSPY verwaltet wie [https://rhasspy.readthedocs.io/en/latest/reference/#dialogue-manager hier] beschrieben. Dialoge werden also nicht funktionieren, sobald für das Dialogue-Management etwas anderes als &#039;&#039;RHASSPY&#039;&#039; eingestellt ist}}&lt;br /&gt;
&lt;br /&gt;
=== Erste Schritte ===&lt;br /&gt;
Die Installation und Erstinbetriebnahme von Rhasspy wird in einer Schnellstart-Anleitung erklärt: [[RHASSPY/Schnellstart]] Diese Anleitung sollte auch befolgt werden, wenn man sich sehr gut mit FHEM auskennt. Wer dies erfolgreich absolviert hat, kann gleich zu Abschnitt [[#Set-Befehle_.28SET.29|Set-Befehle (SET)]] weiterspringen, und/oder die [[RHASSPY/Vertiefung|Vertiefung]] durcharbeiten.&lt;br /&gt;
&lt;br /&gt;
=== Details zur Verwaltung des RHASSPY Moduls ===&lt;br /&gt;
Das Modul ist derzeit nicht in der &amp;quot;offiziellen&amp;quot; FHEM Distribution enthalten und muss daher manuell installiert werden. Dafür gibt es zwei Möglichkeiten.&lt;br /&gt;
&lt;br /&gt;
*Im Subversion Repository, kurz SVN von FHEM ist die jeweils aktuelle &amp;quot;stable&amp;quot; Version des Moduls im &#039;&#039;contrib&#039;&#039;-Zweig zu finden. Diese kann mit folgendem Befehl, der im FHEM Befehls-Eingabefeld einzugeben ist, heruntergeladen werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;{ Svn_GetFile(&#039;contrib/RHASSPY/10_RHASSPY.pm&#039;, &#039;FHEM/10_RHASSPY.pm&#039;) }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Genauere Informationen zu dieser Vorgangsweise finden sich unter [[Update#Einzelne_Dateien_aus_dem_SVN_holen]]. Nach Installation des Moduls muss FHEM neu gestartet werden.&lt;br /&gt;
&lt;br /&gt;
Nach Installation des Moduls muss FHEM neu gestartet werden.&lt;br /&gt;
&lt;br /&gt;
== Einrichtung MQTT2_CLIENT ==&lt;br /&gt;
Rhasspy kommuniziert hauptsächlich über das [[MQTT]]-Protokoll. Und zwar sowohl Rhasspy-intern, wie auch mit FHEM. Da dies auch für die übertragene Sprache und Audio-Dateien gilt und es daher zu sehr viel MQTT-Verkehr kommt, sollte der Rhasspy-interne MQTT-Server verwendet werden. Daher ist die Einrichtung eines [[MQTT2_CLIENT]]-Devices notwendig, um die für FHEM relevanten Daten zu beziehen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zuerst muss ein MQTT2_CLIENT Device erstellt werden, welches sich mit dem MQTT-Server (Mosquitto) von Rhasspy verbindet:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;define &amp;lt;deviceName&amp;gt; MQTT2_CLIENT &amp;lt;ip-oder-hostname-des-mqtt-servers&amp;gt;:&amp;lt;port&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anschließend wird die &#039;&#039;clientOrder&#039;&#039; gesetzt, um die richtige Benachrichtigungsreihenfolge einzustellen. Wird das MQTT2_CLIENT Device nur für RHASSPY verwendet, reicht hier die Angabe &amp;lt;code&amp;gt;RHASSPY&amp;lt;/code&amp;gt;. Ansonsten müssen noch alle anderen Devices (z.B. &amp;lt;code&amp;gt;MQTT_GENERIC_BRIDGE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;MQTT2_DEVICE&amp;lt;/code&amp;gt;) angegeben werden.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;attr &amp;lt;deviceName&amp;gt; clientOrder RHASSPY [device2] [device3]&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Um die Topics einzuschränken, die das Device abonniert, müssen diese angegeben werden. Wird der MQTT-Server nur für RHASSPY verwendet, reicht die Angabe &amp;lt;code&amp;gt;setByTheProgram&amp;lt;/code&amp;gt;. Ansonsten müssen alle für RHASSPY notwendigen Topics eingefügt werden.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;attr &amp;lt;deviceName&amp;gt; subscriptions setByTheProgram&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
bzw.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;attr &amp;lt;deviceName&amp;gt; subscriptions hermes/intent/+ hermes/dialogueManager/sessionStarted hermes/dialogueManager/sessionEnded hermes/nlu/intentNotRecognized hermes/hotword/+/detected hermes/hotword/toggleOn     hermes/hotword/toggleOff hermes/tts/say&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Beispiele&lt;br /&gt;
* Rhasspy-interner MQTT-Server wird mit seinem Standard-Port verwendet. Rhasspy läuft auf der selben Maschine wie FHEM. MQTT2_CLIENT wird nur für RHASSPY verwendet.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod rhasspyMQTT2 MQTT2_CLIENT localhost:12183&lt;br /&gt;
attr rhasspyMQTT2 clientOrder RHASSPY&lt;br /&gt;
attr rhasspyMQTT2 subscriptions setByTheProgram&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* Rhasspy läuft auf einem eigenen Server und verwendet einen externen MQTT Server mit eigener Port-Einstellung. MQTT2_CLIENT wird für RHASSPY, aber auch MQTT_GENERIC_BRIDGE und MQTT2_DEVICE verwendet.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod rhasspyMQTT2 MQTT2_CLIENT 192.168.1.122:1884&lt;br /&gt;
attr rhasspyMQTT2 clientOrder RHASSPY MQTT_GENERIC_BRIDGE MQTT2_DEVICE&lt;br /&gt;
attr rhasspyMQTT2 subscriptions hermes/intent/+ hermes/dialogueManager/sessionStarted hermes/dialogueManager/sessionEnded hermes/nlu/intentNotRecognized hermes/hotword/+/detected hermes/hotword/toggleOn hermes/hotword/toggleOff hermes/tts/say [zusätzliche Subscriptions für andere MQTT-Module]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Definition von RHASSPY (DEF)==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;define &amp;lt;name&amp;gt; RHASSPY &amp;lt;baseUrl&amp;gt; &amp;lt;devspec&amp;gt; &amp;lt;defaultRoom&amp;gt; &amp;lt;siteId&amp;gt; &amp;lt;language&amp;gt; &amp;lt;fhemId&amp;gt; &amp;lt;prefix&amp;gt; &amp;lt;useGenericAttrs&amp;gt; &amp;lt;handleHotword&amp;gt; &amp;lt;autoTraining&amp;gt; &amp;lt;encoding&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
{{Randnotiz|RNTyp=Info|RNText=RHASSPY verwendet sehr oft &amp;lt;parseParams&amp;gt;. Nicht nur im Define, sondern z.B. auch, um Attribut-Werte auszuwerten. Es sollten also alle Parameter im Define in der Form key=value angegeben werden.).}}{{Randnotiz|RNTyp=Info|RNText=RHASSPY führt jede Menge Daten aus unterschiedlichen Quellen zusammen um seine Funktion erfüllen zu können. Die endgültige Daten-Struktur, die RHASSPY verwendet, kann mittels des [[List|list]]-Kommandos angezeigt werden. Es wird empfohlen, sich diese Daten-Struktur auf jeden Fall anzusehen. Vor allem dann, wenn etwas nicht wie gewünscht funktioniert.}}&lt;br /&gt;
Alle Parameter sind &#039;&#039;&#039;optional&#039;&#039;&#039;. Die meisten werden im Normalfall gar nicht benötigt (z.B. &amp;lt;code&amp;gt;fhemId&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;prefix&amp;lt;/code&amp;gt;), oder können auf den automatisch vergebenen Werten belassen werden. Sollten sie aber verwendet und später geändert werden, kann es zu unvorhergesehenem Verhalten kommen. Speziell beim Einstieg in das Thema RHASSPY sollten nicht mehr, als die ersten drei verwendet werden. Ausgenommen eventuell noch &amp;lt;code&amp;gt;language&amp;lt;/code&amp;gt;, möchte man eine andere Sprache als Englisch oder Deutsch verwenden und &amp;lt;code&amp;gt;siteId&amp;lt;/code&amp;gt;, das für Tests und andere Text-Eingabemöglichkeiten wichtig ist.&lt;br /&gt;
&lt;br /&gt;
=== baseUrl ===&lt;br /&gt;
Die URL zum Rhasspy-Webservice. Sollten eine Base und mehrere Satelliten verwendet werden, die URL zur Base. Bitte sicherstellen, dass die Adresse richtig ist (IP und Port)! Default ist &amp;lt;code&amp;gt;baseUrl=http://127.0.0.1:12101&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== devspec ===&lt;br /&gt;
&#039;&#039;devspec&#039;&#039; der Geräte, die mit Rhasspy gesteuert werden sollen. Wenn der &#039;&#039;genericDeviceType&#039;&#039;-Support aktiviert ist, ist der Default &amp;lt;code&amp;gt;devspec=genericDeviceType=.+&amp;lt;/code&amp;gt;, sonst wird &amp;lt;code&amp;gt;devspec=room=Rhasspy&amp;lt;/code&amp;gt; verwendet. Ohne ein passendes Match in der devspec wird kein Gerät mit dem Modul interagieren, egal, ob sonst irgendwelche RHASSPY-spezifischen Attribute beim Gerät gesetzt sind. Genauere Informationen, wie z.B. eine Liste von Geräten oder Kombinationen aus Geräten und Räumen (z.B. &amp;lt;code&amp;gt;devspec=room=livingroom,room=bathroom,bedroomlamp&amp;lt;/code&amp;gt;) verwendet werden können, finden sich in der [https://commandref.fhem.de/commandref.html#devspec CommandRef].&lt;br /&gt;
&lt;br /&gt;
=== defaultRoom ===&lt;br /&gt;
Der Name des Standard-Raumes, der verwendet wird, wenn im Sprachkommando kein Raum enthalten ist und auch kein passender für das Device gefunden werden kann. Default ist &amp;lt;code&amp;gt;defaultRoom=default&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== language ===&lt;br /&gt;
Sprache, in der mit Rhasspy gesprochen wird. Der Standard-Wert hängt vom &#039;&#039;global&#039;&#039;-Device ab. Dieser ist standardmäßig &amp;lt;code&amp;gt;language=en&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== fhemId ===&lt;br /&gt;
Wird verwendet um auf MQTT-Seite zwischen mehreren Installationen des RHASSPY-Moduls zu unterscheiden. Ist auch ein Teil des Topic-Trees, auf den die jeweilige RHASSPY-Instanz hört. Default ist &amp;lt;code&amp;gt;fhemId=fhem&amp;lt;/code&amp;gt;.&lt;br /&gt;
{{Hinweis|Dialoge werden in RHASSPY verwaltet wie [https://rhasspy.readthedocs.io/en/latest/reference/#dialogue-manager hier] beschrieben. Dialoge werden also nicht funktionieren, sobald für das Dialogue-Management etwas anderes als &#039;&#039;RHASSPY&#039;&#039; eingestellt ist}}&lt;br /&gt;
&lt;br /&gt;
=== siteId ===&lt;br /&gt;
Wenn bestimmte Funktionen genutzt werden sollen, muss die RHASSPY-Instanz für Rhasspy als &#039;&#039;Satellit&#039;&#039; eigenständig angesprochen werden können. Hierzu muss dann eine eindeutige Kennung vergeben werden, und diese ist insbesondere dann auch in der für die Intent Recognition zuständigen Rhasspy-Komponente als Satellit anzugeben. Wird diese nicht explizit gesetzt, wird diese aus dem &#039;&#039;language&#039;&#039;-Kürzel und der &#039;&#039;fhemId&#039;&#039; zusammengesetzt.&lt;br /&gt;
{{Hinweis|Für die Funktionalitäten &#039;&#039;test_sentence&#039;&#039;, &#039;&#039;test_file&#039;&#039;, &#039;&#039;msgDialog&#039;&#039; und &#039;&#039;AMAD.*&#039;&#039; ist es &#039;&#039;&#039;zwingend erforderlich&#039;&#039;&#039;, die siteId in der Rhasspy-Intent-Recognition-Komponente einzutragen!}}&lt;br /&gt;
&lt;br /&gt;
=== prefix ===&lt;br /&gt;
Wird verwendet um auf FHEM-Seite zwischen mehreren Installationen des RHASSPY-Moduls zu unterscheiden. Praktisch, wenn man mehrere Instanzen von RHASSPY auf einer FHEM Installation laufen hat und z.B. verschiedene Bezeichner für Gruppen und Räume haben möchte (z.B. unterschiedliche Sprachen). Default ist &amp;lt;code&amp;gt;prefix=rhasspy&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== useGenericAttrs ===&lt;br /&gt;
Üblicherweise verwendet RHASSPY - wie auch einige andere FHEM Module für Sprachassistenten - das Attribut &#039;&#039;genericDeviceType&#039;&#039; um Schaltmöglichkeiten von Geräten automatisch zu erkennen. Dieser Parameter fügt das Attribut &#039;&#039;genericDeviceType&#039;&#039; zur globalen Attributliste hinzu. Der Wert 0 verhindert dieses hinzufügen und die automatisierte Eigenschaftenerkennung. Default ist &amp;lt;code&amp;gt;useGenericAttrs=1&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== encoding ===&lt;br /&gt;
Sollte es Probleme mit Umlauten geben, kann das Character-Encoding geändert werden. Default ist &amp;lt;code&amp;gt;encoding=utf8&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== handleHotword ===&lt;br /&gt;
Triggert das Reading &#039;&#039;hotword&#039;&#039;, wenn ein Hotword erkannt wurde (und erstellt das Reading, falls noch nicht vorhanden). Weitere Informationen dazu stehen beim Attribut [[#rhasspyHotwords|&#039;&#039;rhasspyHotwords&#039;&#039;]]. Default ist &amp;lt;code&amp;gt;handleHotword=0&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== autoTraining ===&lt;br /&gt;
Da Änderungen auf der FHEM-Seite (z.B. bei Änderungen der rhasspyNames) auch Rhasspy bekannt gemacht werden müssen und anschließend ein Training erfolgen muss, damit Rhasspy diese Änderugnen ebenfalls berücksichtigt, übergibt RHASSPY derartige Änderungen nach Ablauf von einer Minute seit der letzten Änderung an Rhasspy und initiiert dann ein Training. Setzt man diesen Schlüssel auf &amp;quot;0&amp;quot;, wird diese Funktion deaktiviert, alle anderen numerischen Werte werden als Änderung dieses Timeouts (in Sekunden) interpretiert&lt;br /&gt;
Default ist &amp;lt;code&amp;gt;autoTraining=60&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|Nach dem Definieren eines RHASSPY-Modules sollte das IODev manuell gesetzt werden um ein automatische IO-Zuweisung zu verhindern. Z.B. &amp;lt;code&amp;gt;attr &amp;lt;deviceName&amp;gt; IODev &amp;lt;m2client&amp;gt;&amp;lt;/code&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
;Beispiele:&lt;br /&gt;
Läuft Rhasspy auf der selben Maschine wie FHEM, die Sprache ist im &#039;&#039;global&#039;&#039;-Device bereits richtig eingestellt und der Standardraum entspricht der siteId, die in Rhasspy vergeben wurde:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;define Rhasspy RHASSPY&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Läuft Rhasspy auf einem anderen System wie FHEM, der Standard-Raum enspricht nicht dem, was Rhasspy liefert, die Sprache soll auch anders sein und es sollen sowohl Geräte mit vorhandenem &#039;&#039;genericDeviceType&#039;&#039; Attribut, als auch die Geräte &#039;&#039;device_a1&#039;&#039; und &#039;&#039;device_xy&#039;&#039; gesteuert werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;define Rhasspy RHASSPY baseUrl=http://192.168.1.210:12101 defaultRoom=&amp;quot;Büro Lisa&amp;quot; language=de devspec=genericDeviceType=.+,device_a1,device_xy handleHotword=1&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Set-Befehle (SET) ==&lt;br /&gt;
&lt;br /&gt;
=== customSlot ===&lt;br /&gt;
Erstellt einen neuen - oder überschreibt einen alten - Slot in Rhasspy&lt;br /&gt;
* &amp;lt;code&amp;gt;slotname&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;slotdata&amp;lt;/code&amp;gt; sind verpflichtend&lt;br /&gt;
* &amp;lt;code&amp;gt;overwrite&amp;lt;/code&amp;gt; ist optional. Default ist &amp;lt;code&amp;gt;overwrite=true&amp;lt;/code&amp;gt;. Das Setzen eines anderes Wertes verhindert das Überschreiben einen bereits bestehenden Slot mit gleichem Namen.&lt;br /&gt;
* &amp;lt;code&amp;gt;training&amp;lt;/code&amp;gt; ist optional. Default ist &amp;lt;code&amp;gt;training=true&amp;lt;/code&amp;gt;. Das Setzen eines anderen Wertes verhindert ein Training von Rhasspy nach dem Speichern des Slots.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiele:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; customSlot mySlot a,b,c overwrite training&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; customSlot slotname=mySlot slotdata=a,b,c overwrite=false&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== fetchSiteIds ===&lt;br /&gt;
Liest alle in Rhasspy vorhandenen siteIDs aus und speichert sie im Reading &#039;&#039;siteIds&#039;&#039;. Wird z.B. verwendet, um festzustellen, auf welchem Satelliten der User über das Ende eines Timers benachrichtigt werden soll.&lt;br /&gt;
Muss immer ausgeführt werden, wenn eine neue siteId in Rhasspy hinzugefügt wird (neuer Satellit z.B.).&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; fetchSiteIds&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== play ===&lt;br /&gt;
Sendet eine WAV Datei an Rhasspy, &amp;lt;code&amp;gt;siteId&amp;lt;/code&amp;gt; und &amp;lt;path&amp;gt; sind verpflichtend!&lt;br /&gt;
&lt;br /&gt;
Optional kann die Anzahl der Wiederholungen (Default: 1) und die Dauer der Pause zwischen den jeweiligen Wiederholungen (Default: 15) angeben werden.&lt;br /&gt;
&#039;&#039;Beispiele:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; play siteId=&amp;quot;default&amp;quot; path=&amp;quot;/opt/fhem/test.wav&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; play siteId=&amp;quot;default&amp;quot; path=&amp;quot;./test.wav&amp;quot; repeats=3 wait=20&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== speak ===&lt;br /&gt;
Sendet einen Text an das TTS-Sytem, welches ihn dann als Sprache ausgibt.&lt;br /&gt;
&lt;br /&gt;
Beide Argumente &amp;lt;code&amp;gt;siteId&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;text&amp;lt;/code&amp;gt; sind verpflichtend!&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; speak siteId=&amp;quot;wohnzimmer&amp;quot; text=&amp;quot;This is a test&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== textCommand ===&lt;br /&gt;
Sendet ein Text-Kommando an Rhasspy.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; textCommand schalte das licht ein&amp;lt;/code&amp;gt;&lt;br /&gt;
Mangels siteId erfolgt hier keine Rückmeldung zum ausgeführten Kommando.&lt;br /&gt;
&lt;br /&gt;
=== trainRhasspy ===&lt;br /&gt;
Startet das Training von Rhasspy.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; trainRhasspy&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== update ===&lt;br /&gt;
&#039;&#039;update&#039;&#039; kennt diverse Abstufungen:&lt;br /&gt;
&lt;br /&gt;
==== update devicemap ====&lt;br /&gt;
Wenn an der Konfiguration von RHASSPY oder an den von ihm gesteuerten Geräten etwas geändert wurde, muss dieser Befehl ausgeführt werden, um die Datenstruktur von RHASSPY zu aktualisieren, Rhasspy von den Änderungen zu informieren (Slots z.B.) und ein Training zu starten. Wenn [[#autoTraining|autoTraining]] nicht deaktiviert wurde, erfolgt dies bei Änderungen an relevanten Attributen nach einiger Zeit zwar automatisch, über diesen Befehl kann aber sichergestellt werden, dass dies unmittelbar und ohne Vergleich mit Alt-Daten erfolgt.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update devicemap&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== update devicemap_only ====&lt;br /&gt;
Aktualisiert die Datenstruktur von RHASSPY. Es werden weder Slots in Rhasspy geändert, noch das Training gestartet.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update devicemap_only&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== update slots ====&lt;br /&gt;
Aktualisiert (bzw. erstellt) alle Slots in Rhasspy mit den aktuellen Geräten, Räumen, usw.&lt;br /&gt;
&lt;br /&gt;
Erstellte/Aktualisierte Slots sind z.B.:&lt;br /&gt;
* de.fhem.AllKeywords  (Hinweis: Die ersten beiden Teile &#039;&#039;de&#039;&#039; und &#039;&#039;fhem&#039;&#039; hängen von der DEF des RHASSPY-Devices ab)&lt;br /&gt;
* de.fhem.Device&lt;br /&gt;
* de.fhem.Device-&#039;&#039;genericDeviceType&#039;&#039;&lt;br /&gt;
* de.fhem.Device-&#039;&#039;Intent&#039;&#039;&lt;br /&gt;
* de.fhem.Group&lt;br /&gt;
* de.fhem.Room&lt;br /&gt;
* de.fhem.MediaChannels&lt;br /&gt;
* de.fhem.Color&lt;br /&gt;
* de.fhem.NumericType&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update slots&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== slots_no_training ====&lt;br /&gt;
Wie &amp;lt;code&amp;gt;slots&amp;lt;/code&amp;gt;, aber ohne Training nach dem Update.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update slots_no_training&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== update language ====&lt;br /&gt;
Liest das das Sprach-File (&#039;&#039;languageFile&#039;&#039;) neu ein.&lt;br /&gt;
&lt;br /&gt;
Muss immer ausgeführt werden, wenn in diesem File oder dem Attribut &#039;&#039;languageFile&#039;&#039; etwas geändert wurde!&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update language&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== update intent_filter ====&lt;br /&gt;
Setzt die Intent Filter, die vom Rhasspy Dialogue Manger verwendet werden zurück. Details dazu bei [[#intentFilter|intentFilter]] im &#039;&#039;rhasspyTweaks&#039;&#039;-Attribut.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update intent_filter&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== update all ====&lt;br /&gt;
Aktualisiert die Devicemap und das languageFile&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update all&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== volume ===&lt;br /&gt;
Stellt die Lautstärke der gewünschten siteId auf einen Wert zwischen 0 and 1 (float). Beide Argumente &amp;lt;code&amp;gt;siteId&amp;lt;/code&amp;gt; &amp;lt;code&amp;gt;volume&amp;lt;/code&amp;gt; sind verpflichtend.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; siteId=&amp;quot;default&amp;quot; volume=&amp;quot;0.5&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|Bitte nicht vergessen, dass nach jeder Änderung an RHASSPY oder an einem von RHASSPY gesteuerten Gerät ein &amp;lt;code&amp;gt;update devicemap&amp;lt;/code&amp;gt; ausgeführt werden sollte, v.a. wenn das [[#autoTraining|autoTraining]] in der DEF deaktiviert wurde!}}&lt;br /&gt;
&lt;br /&gt;
== Get-Befehle (GET) ==&lt;br /&gt;
=== export_mapping ===&lt;br /&gt;
Liefert für das angegebene Device ein &amp;quot;klassisches&amp;quot; &#039;&#039;rhasspyMapping&#039;&#039;, das dann als Basis für eigene Weiterentwicklungen genutzt werden kann. Funktioniert ggf. nicht in allen Fällen (z.B. bei &#039;&#039;SetScene&#039;&#039; und dem Szenen-Format für &#039;&#039;HUEBridge&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
=== test_file ===&lt;br /&gt;
Anzugeben ist der Dateiname (einschl. Pfad)&lt;br /&gt;
&lt;br /&gt;
Die Datei wird zeilenweise eingelesen und an die Rhasspy-Komponente für die Intent-Erkennung übergeben. Das Ergebnis der Analyse wird in eine File geschrieben, die auf &#039;_result.txt&#039; endet. &#039;&#039;stop&#039;&#039; als Dateiname unterbricht einen laufenden Test. Die ggf. abgeleiteten Kommandos werden nicht ausgeführt, FHEM wird während eines laufende Tests auch keine anderen Kommandos von der Rhasspy-Seite her annehmen.&lt;br /&gt;
Für diese Funktion ist es zwingend erforderlich, dass die &#039;&#039;siteId&#039;&#039; der RHASSPY-Instanz bei der Intent-Recognition-Komponente in Rhasspy als Satellit angegeben wurde.&lt;br /&gt;
&lt;br /&gt;
=== test_sentence ===&lt;br /&gt;
Es kann ein beliebiger einzelner Satz eingegeben werden, die Ausgabe erfolgt dann in einem eigenen Dialogfeld, ansonsten gilt sinngemäß dasselbe wie bei &#039;&#039;test_file&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==Attribute (ATTR)==&lt;br /&gt;
Um RHASSPY zum Laufen zu bringen, müssen unterschiedliche Attribute gesetzt werden. Dabei gibt es&lt;br /&gt;
*Attribute, die im RHASSPY-Device selbst gesetzt werden müssen und&lt;br /&gt;
*Attribute, die in den Devices gesetzt werden müssen, die von RHASSPY kontrolliert werden sollen.&lt;br /&gt;
&lt;br /&gt;
Letztere werden im Abschnitt [[#FHEM-Devices für die Verwendung mit Rhasspy konfigurieren|FHEM-Devices für die Verwendung mit Rhasspy konfigurieren]] behandelt.&lt;br /&gt;
&lt;br /&gt;
In diesem Abschnitt werden die Attribute behandelt, die auf das RHASSPY-Device selbst wirken.&lt;br /&gt;
&lt;br /&gt;
===IODev===&lt;br /&gt;
Das MQTT2_CLIENT Device, welches die MQTT-Nachrichten für RHASSPY liefert.&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;code&amp;gt;attr &amp;lt;rhasspyDevice&amp;gt; IODev rhasspyMQTT2&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===forceNEXT===&lt;br /&gt;
Wenn dieses Attribut auf 1 gesetzt ist, leitet RHASSPY eingehende MQTT-Nachrichten an andere MQTT2-IO-Client Module wie MQTT2_DEVICE weiter, auch wenn das Topic zu einem von RHASSPY abonnierten passt.&lt;br /&gt;
Standardmäßig werden diese Nachrichten nicht weitergeleitet um eine bessere Kompatibilität mit dem &#039;&#039;autocreate&#039;&#039;-Feature des MQTT2_DEVICE sicher zu stellen.&lt;br /&gt;
Siehe dazu das {{Link2CmdRef|Anker=MQTT2_CLIENT-attr-clientOrder|Lang=en|Label=clientOrder}}-Attribut in der CommandRef zum MQTT2_CLIENT Device.&lt;br /&gt;
Das Setzen dieses Attributs in einer RHASSPY-Instanz kann auch andere eventuell vorhandene RHASSPY-Instanzen beinflussen.&lt;br /&gt;
Default ist &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;code&amp;gt;attr &amp;lt;rhasspyDevice&amp;gt; forceNext 1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===languageFile===&lt;br /&gt;
{{Randnotiz|RNTyp=g|RNText=Bei Nutzung von configDB wird diese Datei aus der Datenbank gelesen.}}&lt;br /&gt;
Pfad zur Sprach-Datei&lt;br /&gt;
Ist dieses Argument nicht gesetzt, wird ein Standard-Set an englischen Sätzen für die Sprachantworten verwendet.&lt;br /&gt;
Die Datei selbst muss ein gültiges JSON-File sein, dass sich nach der Struktur aus den englischen Standardwerten richtet.&lt;br /&gt;
Eine deutsche Beispiel-Datei ist in [https://svn.fhem.de/trac/browser/trunk/fhem/contrib/RHASSPY/rhasspy-de.cfg SVN] und [https://github.com/fhem/fhem-rhasspy/blob/dev/FHEM/rhasspy-de.cfg GitHub] vorhanden. Man kann aber einfach ein Dump der englischen Struktur machen (replace RHASSPY by your device&#039;s name: &amp;lt;code&amp;gt;{toJSON($defs{RHASSPY}-&amp;gt;{helper}{lng})}&amp;lt;/code&amp;gt;, das Ergebnis dann bearbeiten und es als eigenes languageFile verwenden.&lt;br /&gt;
Im Standard-Set sind auch einige Variablen enthalten. Auch die können im eigenen File verwendet werden.&lt;br /&gt;
&#039;&#039;languageFile&#039;&#039; erlaubt auch eine Kombination aus vorhandenen und eigenen Sätzen. Dazu können die eigenen Sätzen einfach im Sub-Tree &#039;&#039;user&#039;&#039; abgelegt werden.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039; (vorausgesetzt, die Sprach-Datei ist im selben Verzeichnis wie fhem.pl):&lt;br /&gt;
&amp;lt;code&amp;gt;attr &amp;lt;rhasspyDevice&amp;gt; languageFile ./rhasspy-de.cfg&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====response====&lt;br /&gt;
{{Hinweis|Die Verwendung dieses Attributs ist nicht mehr empfohlen. Bessere Alternative ist die Sprach-Datei.}}&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Mit diesem Attribut können eigene Standardantworten definiert werden.&lt;br /&gt;
Mögliche Schlüsselwörter sind &amp;lt;code&amp;gt;DefaultError&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;NoActiveMediaDevice&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;DefaultConfirmation&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;DefaultError=&lt;br /&gt;
DefaultConfirmation=Klaro, mach ich&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===rhasspyHotwords===&lt;br /&gt;
Kann verwendet werden, um benutzerdefinierte Aktionen auszuführen, sobald ein bestimmtes Hotword erkannt wurde. Dazu sind keine speziellen Konfigurationsschritte in anderen FHEM Devices notwendig.&lt;br /&gt;
Wenn mittels Attribut oder DEF aktiviert, wird ein Reading &#039;&#039;hotword&#039;&#039; erstellt und mit dem erkannten Hotword und der siteId befüllt um ein Event-Handling zu ermöglichen.&lt;br /&gt;
{{Hinweis|Da bei den hotword messages für alle Teilnehmer dieselbe Topic-Structur verwendet wird, kann RHASSPY nicht unterscheiden, ob eine solche für diese Instanz relevant ist. Falls entsprechende Unterscheidungen gemacht werden sollen, muss dies vom User entsprechend konfiguriert werden, z.B. indem die subscriptions (am MQTT2_CLIENT) eingeschränkt werden oder indem nur jeweils andere hotword-Einträge für jede RHASSPY-Instanz genutzt werden.}}&lt;br /&gt;
Ein Hotword pro Zeile, Syntax entweder einfach oder erweitert&lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;&#039;Beispiele:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;bumblebee_linux = set amplifier2 mute on&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;porcupine_linux = livingroom=&amp;quot;set amplifier mute on&amp;quot; default={Log3($DEVICE,3,&amp;quot;device $DEVICE - room $ROOM - value $VALUE&amp;quot;)}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im ersten Beispiel wird der Befehl immer ausgeführt, wenn das Hotword &#039;&#039;bumblebee_linux&#039;&#039; erkannt wurde.&lt;br /&gt;
Im zweiten nur, wenn das Hotword &#039;&#039;porcupine_linux&#039;&#039; in der siteId &#039;&#039;livingroom&#039;&#039; erkannt wurde.&lt;br /&gt;
$DEVICE wird ausgewertet als der Name des RHASSPY Devices, $ROOM als siteId und $VALUE als das verwendete Hotword.&lt;br /&gt;
&lt;br /&gt;
===rhasspyIntents===&lt;br /&gt;
Definiert einen benutzerdefinierten Intent.&lt;br /&gt;
Ein Intent pro Zeile.&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;attr &amp;lt;rhasspyDevice&amp;gt; rhasspyIntents SetCustomIntentsTest=SetCustomIntentsTest(siteId,Type)&amp;lt;/code&amp;gt;&lt;br /&gt;
in Kombination mit folgendem myUtils-Code&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub SetCustomIntentsTest {&lt;br /&gt;
my $room = shift;&lt;br /&gt;
my $type = shift;&lt;br /&gt;
Log3(&#039;rhasspy&#039;,3 , &amp;quot;RHASSPY: Room $room, Type $type&amp;quot;);&lt;br /&gt;
return &amp;quot;RHASSPY: Room $room, Type $type&amp;quot;;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
schreibt einen Log-Eintrag nach jedem Aufruf dieses Intents.&lt;br /&gt;
&lt;br /&gt;
Die folgenden Argumente können dabei übergeben werden:&lt;br /&gt;
* NAME =&amp;gt; Name des RHASSPY-Devices&lt;br /&gt;
* DATA =&amp;gt; komplette JSON-$data (wie intern geparsed), in JSON kodiert&lt;br /&gt;
* siteId, Device etc. =&amp;gt; jedes Element, das in JSON-$data existiert&lt;br /&gt;
Wird von der Funktion ein einfacher Text zurück geliefert, wird dieser als &#039;&#039;response&#039;&#039; angesehen. Wenn der Rückgabewert nicht definiert ist, wird die Standard-&#039;&#039;response&#039;&#039; verwendet.&lt;br /&gt;
&lt;br /&gt;
Es kann aber auch ein &#039;&#039;&#039;HASH&#039;&#039;&#039; oder &#039;&#039;&#039;ARRAY&#039;&#039;&#039; übergeben werden.&lt;br /&gt;
* Im Falle eines &#039;&#039;&#039;ARRAY&#039;&#039;&#039;s wird das erste Element als &#039;&#039;response&#039;&#039; interpretiert und kann ein reiner Text sein, womit der Dialog beendet wird. &lt;br /&gt;
* Ist das erste Element ein &#039;&#039;&#039;HASH&#039;&#039;&#039; wird die Dialog-Session fortgesetzt. Eine offene Dialog-Session wird per Default nach 20 Sekunden beendet. Diese Zeitspanne kann aber auch geändert werden, in dem im ARRAY als zweiter Wert eine Zahl übergeben wird. Das zweite Element kann aber auch eine komma-getrennte Liste an Geräten sein, die geändert (geschalten) wurden. Das dient dazu, damit die Geräte auch Events liefern, was ansonsten nicht der Fall wäre. Siehe dazu den &amp;quot;d&amp;quot;-Parameter beim Attribut [[#rhasspyShortcuts|rhasspyShortcuts]].&lt;br /&gt;
Wird eine HASH-Datenstruktur (ggf. in $response innerhalb einer ARRAY-Struktur), um einen laufenden Dialog fortzusetzen, muss sichergestellt werden, dass alle erforderlichen Datenelemente enthalten sind, insbesondere &#039;&#039;intentFilter&#039;&#039;, falls die für den weiteren Dialog relevanten Intents eingeschränkt (oder erweitert) werden sollen. Dabei sollte möglichst der Intent &#039;&#039;CancelAction&#039;&#039; aktiv gehalten werden, damit der User die Option hat, den Dialog jederzeit aktiv zu beenden.&lt;br /&gt;
&lt;br /&gt;
Siehe dazu auch den Abschnitt [[#Eigene Intents erstellen|Eigene Intents erstellen]].&lt;br /&gt;
&lt;br /&gt;
===rhasspyShortcuts===&lt;br /&gt;
Hiermit können benutzerdefinierte Sätze erstellt werden ohne die sentences.ini in Rhasspy bearbeiten zu müssen.&lt;br /&gt;
Diese Shortcuts werden zu Rhasspy hochgeladen, sobald das &amp;lt;code&amp;gt;updateSlots&amp;lt;/code&amp;gt; [[#set-update|Set]]-Kommando ausgeführt wird.&lt;br /&gt;
Ein Shortcut pro Zeile, Syntax ist entweder einfach oder erweitert.&lt;br /&gt;
&#039;&#039;&#039;Beispiele:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;mute on=set amplifier2 mute on&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;lamp off={fhem(&amp;quot;set lampe1 off&amp;quot;)}&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;i=&amp;quot;du bist cool&amp;quot; f=&amp;quot;set $NAME speak siteId=&#039;livingroom&#039; text=&#039;danke dir! du bist noch viel cooler!&#039;&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;i=&amp;quot;schalte den ton aus&amp;quot; p={fhem (&amp;quot;set $NAME mute off&amp;quot;)} n=amplifier2 c=&amp;quot;soll ich den ton wirklich ausschalten?&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;i=&amp;quot;ich hab hunger&amp;quot; f=&amp;quot;set Herd on&amp;quot; d=&amp;quot;Herd&amp;quot; c=&amp;quot;möchtest du schweinsbraten?&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Erklärung zu den Abkürzungen:&lt;br /&gt;
* &amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt; =&amp;gt; intent&lt;br /&gt;
Zeilen, die mit &amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt; beginnen, werden als erweiterte Syntax interpretiert. Soll die erweiterte Syntax verwendet werden, ist das &amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt; also Pflicht!&lt;br /&gt;
* &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; =&amp;gt; FHEM Befehl&lt;br /&gt;
Syntax wie von der FHEM Kommandozeile gewohnt&lt;br /&gt;
* &amp;lt;code&amp;gt;p&amp;lt;/code&amp;gt; =&amp;gt; Perl Befehl&lt;br /&gt;
Syntax wie von der FHEM Kommandozeile gewohnt, eingerahmt in geschwungenen Klammern (&amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt;). &amp;lt;code&amp;gt;p&amp;lt;/code&amp;gt; hat Vorrang vor &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;d&amp;lt;/code&amp;gt; =&amp;gt; Device Name(en, Komma getrennt)&lt;br /&gt;
Device Name(n), die an fhem.pl als upgedated übergeben werden sollen. Das wird benötigt um weitere Aktionen in FHEM und das Longpolling zu triggern.&lt;br /&gt;
&lt;br /&gt;
Hinweis: Wenn Perl-Funktionen aufgerufen werden, wird der Rückgabewert dieser Funktion verwendet, sofern kein explizites Device angegeben ist.&lt;br /&gt;
* &amp;lt;code&amp;gt;r&amp;lt;/code&amp;gt; =&amp;gt; Response&lt;br /&gt;
Sprachanwort, die ausgegeben wird. Ist &amp;lt;code&amp;gt;r&amp;lt;/code&amp;gt; nicht gesetzt, wird der Rückgabewert der aufgerufenen Funktion verwendet.&lt;br /&gt;
In den Antwortsätze werden &#039;&#039;set magic&#039;&#039;-ähnliche Ersetzungen verarbeitet. Es ist also auch eine Zeile wie &amp;lt;code&amp;gt;i=&amp;quot;what&#039;s the time for sunrise&amp;quot; r=&amp;quot;at [Astro:SunRise] o&#039;clock&amp;quot;&amp;lt;/code&amp;gt; gültig.&lt;br /&gt;
&lt;br /&gt;
Mit den folgenden Abkürzungen kann auch nach einer Bestätigung für den Befehl gefragt werden:&lt;br /&gt;
* &amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt; =&amp;gt; Entweder Zahl oder Text. Wenn Zahl, wird sie als Timeout für den Abbruch des Dialogs behandelt. Wenn Text wird dieser als Sprachausgabe zur Bestätigung verwendet.&lt;br /&gt;
* &amp;lt;code&amp;gt;ct&amp;lt;/code&amp;gt; =&amp;gt; Numerischer Wert für das Timeout des Dialogs in Sekunden. Default ist &amp;lt;code&amp;gt;15&amp;lt;/code&amp;gt;.&lt;br /&gt;
Siehe [[#attr-rhasspytweaks-confirmintents|hier]] für weitere Informationen zu Bestätigungen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===rhasspyTweaks===&lt;br /&gt;
Mit diesen Einstellungen können benutzerdefinierte Optimierungen an RHASSPY vorgenommen werden.&lt;br /&gt;
&lt;br /&gt;
====timerLimits====&lt;br /&gt;
Wird verwendet um den Timer anzuweisen mit z.B. &amp;quot;gestellt auf 30 Minuten&amp;quot; oder &amp;quot;gestellt auf 10:30&amp;quot; zu antworten&lt;br /&gt;
:&amp;lt;code&amp;gt;timerLimits=90,300,3000,2*HOURSECONDS,50&amp;lt;/code&amp;gt;&lt;br /&gt;
Hierbei müssen fünf Werte gesetzt werden, die den Zeitgrenzen für Stufen in der Antwortstruktur &#039;&#039;timerSet&#039;&#039; entsprechen.&lt;br /&gt;
Obiges Beispiel also würde dazu führen, unter einer eingestellten Zeit von 90 Sekunden mit der Sekundenangabe geantwortet wird. In Minuten und Sekunden solange der Timer kürzer als 300 Sekunden ist. Usw. Der letzte Wert ist das Limit in Sekunden, wenn der Timer im &amp;quot;Uhrzeit&amp;quot;-Format gestellt ist.&lt;br /&gt;
&lt;br /&gt;
====timerSounds====&lt;br /&gt;
Standardmäßig antwortet der Timer mit einer Sprachnachricht, wenn er abgelaufen ist. Soll lieber eine WAV-Datei verwendet werden, kann das hier eingestellt werden.&lt;br /&gt;
:&amp;lt;code&amp;gt;timerSounds= default=./yourfile1.wav eier=3:20:./yourfile2.wav kartoffeln=5:./yourfile3.wav&amp;lt;/code&amp;gt;&lt;br /&gt;
Die Keys in dieser Code-Zeile sind Beispiele und deren Name - bis auf &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; frei wählbar. Der Name muss aber zu den &#039;&#039;Label&#039;&#039;-Tags für die Timer in den Rhasspy-Sentences passen.&lt;br /&gt;
&amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; ist optional. Wenn gesetzt, wird dieses WAV-File für alle benannten Timer verwendet, für die kein Keyword in der Konfiguration ist.&lt;br /&gt;
Die beiden Nummern sind optional. Die erste legt fest, wie oft die WAV-Datei wiederholt werden soll (Default: 5). Die zweite definiert die Pause in Sekunden zwischen den Wiederholungen (Default: 15). Ist nur eine Zahl gesetzt, wird diese als gewünschte Anzahl an Wiederholungen interpretiert.&lt;br /&gt;
&lt;br /&gt;
====updateSlots====&lt;br /&gt;
Ändert diverse Aspekte des Erstellens und Updatens von Slots&lt;br /&gt;
* &amp;lt;code&amp;gt;noEmptySlots=1&amp;lt;/code&amp;gt;&lt;br /&gt;
Per Default generiert RHASSPY einen zusätzlichen Slot für jeden &#039;&#039;genericDeviceType&#039;&#039;, der erkannt wird. Unabhängig davon, ob er bei einem Gerät gesetzt ist. Das kann zu leeren Slots führen.&lt;br /&gt;
Ist der Wert &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;, werden keine leeren Slots erstellt.&lt;br /&gt;
* &amp;lt;code&amp;gt;overwrite_all=false&amp;lt;/code&amp;gt;&lt;br /&gt;
RHASSPY überschreibt alle vorhandenen Slots wenn ein &amp;lt;code&amp;gt;updateSlots&amp;lt;/code&amp;gt; ausgeführt wird. Ist das nicht gewünscht, muss dieser Wert auf &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; gesetzt werden.&lt;br /&gt;
* &amp;lt;code&amp;gt;timeouts&amp;lt;/code&amp;gt;&lt;br /&gt;
Die Keywörter &amp;lt;code&amp;gt;confirm&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; können verwendet werden, um das Standard-Timeouts (15s/20s) für Dialoge zu ändern.&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;code&amp;gt;timeouts: confirm=25 default=30&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====confidenceMin====&lt;br /&gt;
Rhasspy ermittelt u.A. auch einen Indikator, anhand dem bestimmt werden kann, wie genau ein Satz erkannt wurde. Ist dieser &#039;&#039;confidence&#039;&#039;-Wert sehr bzw. zu niedrig, kann es erwünscht sein, die (falsch erkannte) Absicht des Sprechers nicht umzusetzen. RHASSPY nutzt daher standardmäßig einen Mindestwert von 0.66, bei allen darunter liegenden Werten wird das betreffende Kommando nicht ausgeführt. Dies kann über diesen Tweak global (key: default) oder feiner pro Intent festgelegt werden.&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;code&amp;gt;confidenceMin= default=0.6 SetMute=0.4 SetOnOffGroup=0.8 SetOnOff=0.8&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====confirmIntents====&lt;br /&gt;
Hiermit kann eingestellt werden, dass für bestimmte Intents immer ein Bestätigung erfragt wird. Unterstützt werden derzeit alle &amp;quot;set-&amp;quot;-Intents.&lt;br /&gt;
Dazu werden &amp;lt;code&amp;gt;Intent&amp;lt;/code&amp;gt;=&amp;lt;code&amp;gt;regex&amp;lt;/code&amp;gt;-Paare verwendet. &amp;lt;code&amp;gt;Intent&amp;lt;/code&amp;gt; ist der Name des gewünschten Intents, &amp;lt;code&amp;gt;regex&amp;lt;/code&amp;gt; ist eine Regex, die eine bestimmte Gruppe (für Gruppen-Intents) oder einen bestimmten Device-Namen beschreiben muss.&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;code&amp;gt;confirmIntents=SetOnOffGroup=light|blinds SetOnOff=blind.*&amp;lt;/code&amp;gt;&lt;br /&gt;
Befehle werden nur nach einer positiven Bestätigung ausgeführt. Das bedeutet, es wird eine Rückfrage ausgegeben, auf diese muss dann (innerhalb des gesetzten Timeouts) unbedingt ein &amp;lt;code&amp;gt;Mode:OK&amp;lt;/code&amp;gt;-Wert vom &#039;&#039;ConfirmAction&#039;&#039;-Intent gesendet werden. Jede andere Wert für &amp;lt;code&amp;gt;Mode&amp;lt;/code&amp;gt; wird als Abbruch gewertet. Es kann aber auch der eigene Intent &#039;&#039;CancelAction&#039;&#039; für den Abbruch verwendet werden.&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:ConfirmAction]&lt;br /&gt;
( yes, please do it | go on | that&#039;s ok | yes, please ){Mode:OK}&lt;br /&gt;
( don&#039;t do it after all ){Mode}&lt;br /&gt;
&lt;br /&gt;
[de.fhem:CancelAction]&lt;br /&gt;
( let it be | oh no | cancel | cancellation ){Mode:Cancel}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====confirmIntentResponses====&lt;br /&gt;
Üblicherweise ist die Bestätigungs-Frage ein &amp;quot;Echo&amp;quot; des ursprünglich gesprochenen Befehls. Dies kann für jeden Intent geändert werden,&lt;br /&gt;
Dies kann für jeden Intent individuell angepaßt werden, wobei die Variablen $target, ($rawInput) und $Value verwendet werden können.&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;code&amp;gt;confirmIntentResponses=SetOnOffGroup=&amp;quot;wirklich die Gruppe $target $Value schalten&amp;quot; SetOnOff=&amp;quot;bestätige dass $target $Value geschaltet werden soll&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;$Value&amp;lt;/code&amp;gt; wird dabei mit den defaults aus dem &#039;&#039;words&#039;&#039; key in der languageFile übersetz (falls vorhanden). Weitere Optionen für Ersetzungen von &amp;lt;code&amp;gt;$Value&amp;lt;/code&amp;gt; sind für einzelne Devices über den [[#attr-rhasspyspecials-confirmvaluemap|confirmValueMap]] key im Attribut &#039;&#039;rhasspySpecials&#039;&#039; verfügbar.&lt;br /&gt;
&lt;br /&gt;
====intentFilter====&lt;br /&gt;
Rhasspy aktiviert bei jedem Neustart alle ihm bekannten Intents. Da manche der von FHEM genutzten Intents nur in bestimmten Situationen (v.a. innerhalb offener Dialoge) benötigt werden, deaktiviert RHASSPY diese (derzeit: ConfirmAction, CancelAction, Choice, ChoiceRoom und ChoiceDevice beim Start, sowie jedes Mal, wenn erkannt wird, dass das Standardfiltering nicht wie erwartet funktioniert (was v.a. bei einem zwischenzeitlichen Rhasspy-Neustart der Fall sein kann). Über diesen Tweak können weitere Intents mit in diese automatisierte (De-) Aktivierung mit einbezogen werden. Entweder ist dabei einfach der Name (ohne die Zusätze aus &#039;&#039;language&#039;&#039; und &#039;&#039;fhemId&#039;&#039; anzugeben, oder eine explizite Anweisung zum ein- und Ausschalten (in der Form &amp;lt;code&amp;gt;intentname=true&amp;lt;/code&amp;gt;). Die 4 vorgenannten Standard-Intents können nicht über diesen Weg aktiviert werden. Details zur intern genutzten Rhasspy-Funktionalität sind in der [https://rhasspy.readthedocs.io/en/latest/reference/#dialogue-manager Rhasspy-Dokumentation] zu finden.&lt;br /&gt;
&lt;br /&gt;
====ignoreKeywords====&lt;br /&gt;
Da in manchen der von RHASSPY automatisch ausgewerteten Attribute häufig auch eher technisch motivierte Angaben zu finden sind, kann über diesen Schlüssel verhindert werden, dass derartige Angaben bei der slot-Erstellung übergangen werden. Dies betrifft z.B. häufig anzutreffende &#039;&#039;room&#039;&#039;-Werte wie &#039;&#039;MQTT&#039;&#039;, &#039;&#039;alexa&#039;&#039;, &#039;&#039;homebridge&#039;&#039; oder &#039;&#039;googleassistant&#039;&#039;. Die hier angegebenen key-value-Paare werden als Negativ-Filter für die angegebenen Werte verwendet (derzeit nur für &#039;&#039;rooms&#039;&#039; und &#039;&#039;group&#039;&#039;). &#039;&#039;value&#039;&#039; wird dabei als (case-insensitive) regex behandelt, verglichen wird auf exakten match (es müssen also ggf. vorne bzw. hinten &#039;&#039;.*&#039;&#039; angefügt werden).&lt;br /&gt;
Dieses &#039;&#039;&#039;Beispiel&#039;&#039;&#039; filtert daher die o.g. Räume aus und dazu noch die strukturierten Unterräume unterhalb &#039;&#039;Steuerung&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ignoreKeywords=rooms=mqtt.*|alexa|homebridge|googleassistant|steuerung-.&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====gdt2groups====&lt;br /&gt;
Dieser Eintrag ermöglicht es, alle Geräte eines generichDeviceType innerhalb der automatischen Erfassung automatisch einer oder mehreren Gruppen zuzuordnen. Die Vorgaben in diesem Eintrag werden nicht übernommen, wenn am jeweiligen Einzelgerät  das Attribut &#039;&#039;rhasspyGroup&#039;&#039; gesetzt ist.  Hier eine deutschsprachige Vorbelegung als &#039;&#039;&#039;Beispiel&#039;&#039;&#039;: &amp;lt;code&amp;gt;gdt2groups= blind=rollläden,rollladen thermostat=heizkörper light=lichter,leuchten&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====mappingOverwrite====&lt;br /&gt;
Wird diese Option aktiviert, wird bei gesetztem &#039;&#039;rhasspyMapping&#039;&#039;-Attribut an einem Device alles gelöscht, was die automatisierte mapping-Erkennung anhand des genericDeviceType erkannt hatte. Sonst ird jeweils nur überschrieben, was als Intent im &#039;&#039;rhasspyMapping&#039;&#039; dieses Geräts angegeben ist.&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
:mappingOverwrite=1&lt;br /&gt;
&lt;br /&gt;
====extrarooms====&lt;br /&gt;
Komma-separierte Liste von weiteren Räumen, die die aus der Generierung der Device-Map bekannten Räume erweitert. Dies kann z.B. für CustomIntents benötigt werden.&lt;br /&gt;
Diese werden in die Slots für &amp;lt;code&amp;gt;rooms&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;mainrooms&amp;lt;/code&amp;gt; integriert.&lt;br /&gt;
Beispiel:&lt;br /&gt;
:extrarooms= barn,music collection,cooking recipies&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Readings / Events==&lt;br /&gt;
;&amp;lt;code&amp;gt;IODev&amp;lt;/code&amp;gt;&lt;br /&gt;
:Das eingestellte IO-Device&lt;br /&gt;
;&amp;lt;code&amp;gt;intents&amp;lt;/code&amp;gt;&lt;br /&gt;
:Eine Liste der in Rhasspy vorhandenen Intents&lt;br /&gt;
;&amp;lt;code&amp;gt;lastIntentPayload&amp;lt;/code&amp;gt;&lt;br /&gt;
:Inhalt des letzten Intents der von FHEM empfangen wurde&lt;br /&gt;
;&amp;lt;code&amp;gt;lastIntentTopic&amp;lt;/code&amp;gt;&lt;br /&gt;
:Das MQTT-Topic des letzten Intents&lt;br /&gt;
;&amp;lt;code&amp;gt;listening_roomname&amp;lt;/code&amp;gt;&lt;br /&gt;
:Ein Reading für jeden Raum bzw. jede siteId&lt;br /&gt;
:Wechselt auf 1 sobald ein Hotword erkannt wurde und zurück auf 0, sobald die Dialog-Session beendet ist.&lt;br /&gt;
:Kann z.B. verwendet werden, um den Ton eines TVs auszuschalten, während Rhasspy auf ein Kommando hört.&lt;br /&gt;
;&amp;lt;code&amp;gt;mute_roomname&amp;lt;/code&amp;gt;&lt;br /&gt;
:Zeigt an, ob ein Raum / eine siteId vom Intent &#039;&#039;SetMute&#039;&#039; stumm geschalten wurde und somit keine Befehle ausführt.&lt;br /&gt;
:Jeweils ein Reading für jede siteId.&lt;br /&gt;
:Default ist 0.&lt;br /&gt;
;&amp;lt;code&amp;gt;responseType&amp;lt;/code&amp;gt;&lt;br /&gt;
:Der Typ der letzten Antwort (text/voice).&lt;br /&gt;
:voiceResponse and textResponse&lt;br /&gt;
:Antwort auf das letzte Sprach-/Text-Kommando.&lt;br /&gt;
;&amp;lt;code&amp;gt;siteIds&amp;lt;/code&amp;gt;&lt;br /&gt;
:Listet alle siteIds auf.&lt;br /&gt;
:Kann mit [[#set-fetchsiteids|fetchSiteIds]] aktualisiert werden.&lt;br /&gt;
;&amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;&lt;br /&gt;
:Zeigt an ob RHASSPY mit Rhasspy verbunden ist&lt;br /&gt;
;&amp;lt;code&amp;gt;training&amp;lt;/code&amp;gt;&lt;br /&gt;
:Letzte zurückgelieferte Antwort auf einen [[#set-trainrhasspy|trainRhasspy]]-Befehl.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
;&amp;lt;code&amp;gt;updateSentences&amp;lt;/code&amp;gt;&lt;br /&gt;
:Letzte zurückgelieferte Antwort nach einem [[#set-update-slots|updateSlots]]-Befehl.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
;&amp;lt;code&amp;gt;updateSlots&amp;lt;/code&amp;gt;&lt;br /&gt;
:Letzte zurückgelieferte Antwort nach einem [[#set-update-slots|updateSlots]]-Befehl.&lt;br /&gt;
;&amp;lt;code&amp;gt;hotword&amp;lt;/code&amp;gt;&lt;br /&gt;
:Wenn aktiviert, beinhaltet dieses Reading das letzte verwendete Hotword und von welcher siteId es aufgerufen wurde.&lt;br /&gt;
;&amp;lt;code&amp;gt;voiceResponse&amp;lt;/code&amp;gt;&lt;br /&gt;
:Letze Sprach-Antwort auf einen Sprach-Befehl&lt;br /&gt;
&lt;br /&gt;
=== Benutzerdefinierte Readings ===&lt;br /&gt;
Um das Verhalten von RHASSPY beeinflussen zu können, können neben den bei den Attributen verfügbaren &#039;&#039;Tweaks&#039;&#039; auch die folgenden Readings genutzt - und v.a. auch im laufenden Betrieb immer weider geändert - werden:&lt;br /&gt;
*&amp;lt;code&amp;gt;siteId2room_&amp;lt;/code&amp;gt; Falls keine explizite Raum-Information in den an RHASSPY weitergegebenen Daten enthalten ist, ermittelt das Modul den Raum in der Regel aus dem Namen der &#039;&#039;siteId&#039;&#039;. So werden z.B. alle raumlosen Anweisungen von einem Satelliten names &#039;&#039;schlafzimmer&#039;&#039;, im Raum &#039;&#039;schlafzimmer&#039;&#039; ausgeführt werden (wenn möglich). Die Gruppenfunktion von Rhasspy wird unterstützt, so wird z.B. &#039;&#039;wohnzimmer.vorne&#039;&#039; ebenfalls automatisch dem Raum &#039;&#039;wohnzimmer&#039;&#039; zugeordnet. Über passende Angaben in &#039;&#039;siteId2room-Readings&#039;&#039; kann dieses Verhalten modifiziert werden:  &amp;lt;code&amp;gt;setreading siteId2room_mobile_phone1 wohnzimmer&amp;lt;/code&amp;gt; wird RHASSPY veranlassen, den Satelliten  &#039;&#039;mobile_phone1&#039;&#039; dem Raum &#039;&#039;wohnzimmer&#039;&#039; zuzuweisen. Ein Beispiel, mit dem dies per Sprachkommando erfolgt, ist in &#039;&#039;contrib&#039;&#039; zu finden, mit der mobilen Satelliten per Funktionsaufruf in einem [[#rhasspyIntents|rhasspyIntent]] einem neuen Raum zugewiesen werden können.&lt;br /&gt;
*&amp;lt;code&amp;gt;siteId2doubleSpeak_&amp;lt;/code&amp;gt; RHASSPY antwortet immer über den Satelliten, von dem die jeweilige Sprachanweisung kam. Manchmal kann es erwünscht sein, zusätzliche Sprachrückmeldungen an einen weiteren Satelliten zu geben - z.B. weil der betreffende Lautsprecher (zeitweise) ausgeschaltet ist. Ist ein entsprechendes Reading gesetzt, erfolgen (zusätzliche!) Sprachausgaben an den dort als Readingwert angegebenen zweiten Satelliten; das Namensschema der Readings entspricht dem für site2room.&lt;br /&gt;
&lt;br /&gt;
== FHEM-Devices für die Verwendung mit Rhasspy konfigurieren ==&lt;br /&gt;
Um ein Gerät mit Rhasspy steuern zu können, muss Rhasspy einige Details über das Gerät kennen. Diese werden bekannt gemacht, in dem bei den Geräten Attribute gesetzt werden, die anschließend vom RHASSPY-Modul ausgewertet und an Rhasspy gesendet werden.&lt;br /&gt;
&lt;br /&gt;
Der einfachste - und empfohlene - Weg, dies zu erreichen, ist durch Setzen des Attributs &#039;&#039;&#039;&#039;&#039;genericDeviceType&#039;&#039;&#039;&#039;&#039;. Das Modul erkennt dann die möglichen Schalt - und Abfragemöglichkeiten des Gerätes automatisch.&lt;br /&gt;
&lt;br /&gt;
Sollte &#039;&#039;genericDeviceType&#039;&#039; (gDT) nicht ausreichen, gibt es noch weitere Attribute, die stattdessen oder ergänzend dazu verwendet werden können (z.b. rhasspyName, rhasspyRoom, ...). Die Namen dieser Attribute beginnen alle mit dem &#039;&#039;prefix&#039;&#039;, das in der DEF des RHASSPY-Moduls gesetzt wurde. Diese Dokumentation verwendet das Prefix &amp;lt;code&amp;gt;rhasspy&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Sind sowohl &#039;&#039;genericDeviceType&#039;&#039; als auch Spezial-Attribute vorhanden, werden die von gDT gesammelten Möglichkeiten durch die der Spezial-Attribute überschrieben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Wichtig:&#039;&#039;&#039;&lt;br /&gt;
*Nach JEDER Änderung (bzw. nach Abschluss aller Änderungen) an den folgenden Attributen muss ein &amp;lt;code&amp;gt;[[#update devicemap|update devicemap]]&amp;lt;/code&amp;gt; ausgeführt werden. In der Regel wird dies automatisch veranlasst, aber wenn dies deaktiviert sein sollte, würden sonst weder RHASSPY, noch Rhasspy von der Änderung erfahren.&lt;br /&gt;
*RHASSPY sammelt alle Informationen aus diesen Attributen in seinem eigenen Device-HASH. Dieser wird durch das &amp;lt;code&amp;gt;update devicemap&amp;lt;/code&amp;gt;-Kommando aktualisiert und kann mittels &amp;lt;code&amp;gt;[[List|list]]&amp;lt;/code&amp;gt;-Befehl angezeigt werden. Für diesen HASH werden alle Namen und sonstige &amp;quot;Labels&amp;quot; in Kleinbuchstaben umgewandelt. Falls man Slots händisch befüllt, muss also darauf geachtet werden, dass Rhasspy ebenfalls Werte in Kleinbuchstaben liefert.&lt;br /&gt;
*Die Mindestvoraussetzungen für ein FHEM Device um mit RHASSPY zusammenzuarbeiten sind:&lt;br /&gt;
**Das Device muss von der &#039;&#039;devspec&#039;&#039; im Define des RHASSPY-Devices abgedeckt werden&lt;br /&gt;
**Es muss mindestens eines der folgenden Attribute (im Normalfall &#039;&#039;genericDeviceType&#039;&#039;) im Device gesetzt sein.&lt;br /&gt;
*Die Mapping-Logik (für Namen, mögliche Schaltzustände, etc.) ist wie folgt:&lt;br /&gt;
**Sind RHASSPY-spezifische Attribute gesetzt, werden ausschließlich diese verwendet. Natürlich nur für den Zweck des gesetzten Attributs. Ein gesetzter &#039;&#039;rhasspyName&#039;&#039; z.B. wird also nicht verhindern, dass die durch &#039;&#039;genericDeviceType&#039;&#039; ermittelten möglichen Schaltzustände ebenfalls gespeichert werden.&lt;br /&gt;
**Je spezifischer ein Attribut ist, desto eher wird überschreiben, was weniger speziell ist. Ein gesetzter &#039;&#039;alias&#039;&#039; wird also verhindern, dass der (technische) Device-Name verwendet wird. Aber ein gesetztes Attribut &#039;&#039;alexaName&#039;&#039;, &#039;&#039;gassistantName&#039;&#039; oder &#039;&#039;siriName&#039;&#039; wird (auch) den &#039;&#039;alias&#039;&#039; überschreiben. Sind zwei &amp;quot;gleichwertige&amp;quot; Attribute vorhanden (z.B. &#039;&#039;siriName&#039;&#039; und &#039;&#039;alexaName&#039;&#039;), werden beide verwendet.&lt;br /&gt;
*Attribut-Werte werden typischerweise &amp;quot;Zeile für Zeile&amp;quot; gelesen. Wobei gilt, eine Zeile pro Wert/Befehl/Funktionalität. Zeilenumbrüche &#039;&#039;&#039;müssen&#039;&#039;&#039; also an den richtigen Stellen gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
=== genericDeviceType ===&lt;br /&gt;
Ist dieses Attribut gesetzt &#039;&#039;&#039;und&#039;&#039;&#039; entspricht der Devicename der devspec, wird RHASSPY das Mapping (und andere eventuell schon vorhandene Werte) automatisch ermitteln.&lt;br /&gt;
&lt;br /&gt;
Derzeit werden folgende Werte für das Attribut genericDeviceType unterstützt:&lt;br /&gt;
*switch&lt;br /&gt;
*light&lt;br /&gt;
*thermostat&lt;br /&gt;
*thermometer&lt;br /&gt;
*HumiditySensor&lt;br /&gt;
*blind/blinds/shutter&lt;br /&gt;
*media&lt;br /&gt;
*motion/contact/ContactSensor/lock/presence&lt;br /&gt;
&lt;br /&gt;
Wird &#039;&#039;genericDeviceType&#039;&#039; verwendet, werden unter anderem folgende Informationen gesammelt:&lt;br /&gt;
* der Name (&amp;lt;code&amp;gt;NAME&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;alias&amp;lt;/code&amp;gt;) des Devices&lt;br /&gt;
* der (FHEM-)Raum, in dem sich das Device befindet.&lt;br /&gt;
* die Gruppe, zu der das Device gehört (ggf. unter Beachtung des Schlüssels [[#gdt2groups|gdt2groups]] aus [[#rhasspyTweaks|rhasspyTweaks]])&lt;br /&gt;
* wie Informationen vom Gerät abgefragt werden können&lt;br /&gt;
* wie Werte/Status am Gerät gesetzt werden können&lt;br /&gt;
&lt;br /&gt;
Die Verwendung von &#039;&#039;genericDeviceType&#039;&#039; ist der einfachste Weg, wie man FHEM-Devices dazu bringen kann, mit RHASSPY zusammenzuarbeiten. Manchmal liefert genericDeviceType aber nicht ausreichende oder nicht passende Informationen. In so einem Fall können die folgenden Attribute (zusätzlich) verwendet werden.&lt;br /&gt;
&lt;br /&gt;
=== rhasspyName ===&lt;br /&gt;
Mit diesem Attribut kann der Name des Geräts eingestellt werden, mit dem es in einem Sprachbefehl angesprochen werden soll. Es können auch mehrere Namen - getrennt durch ein Komma - angegeben werden, der erste Wert in dieser Liste dient intern als Hauptname (&#039;&#039;alias&#039;&#039;), z.B. in Auswahldialogen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039; &amp;lt;code&amp;gt;attr &amp;lt;device&amp;gt; rhasspyName Lampe,Stehlampe,Wunderlicht&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es ist durchaus möglich, mehrere FHEM-Geräte mit dem selben Namen zu haben. Sie müssen dann nur in unterschiedlichen Räumen sein.&lt;br /&gt;
&lt;br /&gt;
=== rhasspyRoom ===&lt;br /&gt;
Dieses Attribut kann verwendet werden, um Rhasspy mitzuteilen, in welchem physischem (oder logischen) Raum sich das Gerät befindet.&lt;br /&gt;
&lt;br /&gt;
Ist es nicht vorhanden, wird &amp;lt;code&amp;gt;alexaRoom&amp;lt;/code&amp;gt; oder das FHEM-Attribut &amp;lt;room&amp;gt; verwendet. Sind auch diese nicht vergeben, gehört das Gerät zum &amp;quot;Standard-Raum&amp;quot;, der im Define des RHASSPY-Devices angegeben wurde.&lt;br /&gt;
&lt;br /&gt;
Das Attribut ist nützlich, wenn man Sprachbefehle ohne explizite Raumangabe verwenden will. Gibt es z.B. ein Gerät mit dem Namen &#039;&#039;Lampe&#039;&#039; und dessen rhasspyRoom-Attribut ist gleich, wie die &#039;&#039;siteId&#039;&#039; von der aus der Sprachbefehl abgesetzt wird, reicht es zu sagen &amp;quot;Lampe ein&amp;quot;. Der Raum muss also nicht extra dazu gesagt werden.&lt;br /&gt;
&lt;br /&gt;
Es ist auch möglich, mehrere Raum-Namen zu vergeben sofern diese durch ein Komma voneinander getrennt werden (der erste Wert ist wieder der &#039;&#039;Hauptraum&#039;&#039; für Auswahldialoge etc.).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039; &amp;lt;code&amp;gt;attr &amp;lt;device&amp;gt; rhasspyRoom livingroom&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hinweis: Wenn die &#039;&#039;siteId&#039;&#039; den Konventionen von Rhasspy zur Gruppierung von siteIds folgt (&#039;&#039;roomname.satellite&#039;&#039;), wird nur &amp;lt;code&amp;gt;roomname&amp;lt;/code&amp;gt; als Raum-Name angenommen. Beachte: Die automatisierte Zuweisung zu einem Raum kann durch &#039;&#039;siteId2room_.*&#039;&#039;-Readings modifiziert werden (s.o.). &lt;br /&gt;
&lt;br /&gt;
=== rhasspyGroup ===&lt;br /&gt;
Kommagetrennte Liste an Gruppen, zu denen das Gerät zugehörig ist&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039; &amp;lt;code&amp;gt;attr &amp;lt;device&amp;gt; rhasspyGroup Lampen,Beleuchtung Arbeitsfläche,Küchen Beleuchtung&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== rhasspyMapping ===&lt;br /&gt;
Wenn die automatische Erkennung des richtigen Intents für ein Gerät nicht funktioniert oder nicht das gewünschte Ergebnis liefert, kann mit diesem Attribut angegeben werden, mit welchem Intent das Gerät gesteuert werden kann.&lt;br /&gt;
&lt;br /&gt;
Es ist möglich, mehrere verschiedene Intents pro Gerät zu verwenden. Es muss nur einfach eine neue Zeile für ein weiteres Mapping verwendet werden.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr &amp;lt;device&amp;gt; rhasspyMapping SetOnOff:cmdOn=on,cmdOff=off,response=&amp;quot;Alles klar&amp;quot;&lt;br /&gt;
GetOnOff:currentVal=state,valueOff=off&lt;br /&gt;
GetNumeric:currentVal=pct,type=brightness&lt;br /&gt;
SetNumeric:currentVal=brightness,cmd=brightness,minVal=0,maxVal=255,map=percent,step=1,type=brightness&lt;br /&gt;
Status:response=Die Helligkeit in der Küche ist bei [&amp;lt;device&amp;gt;:pct]&lt;br /&gt;
MediaControls:cmdPlay=play,cmdPause=pause,cmdStop=stop,cmdBack=previous,cmdFwd=next&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Formatierung von Befehlen und Readings innerhalb eines rhasspyMappings ====&lt;br /&gt;
Manche Intents können FHEM-Kommandos oder -Readings verwenden, um Werte auszulesen oder zu setzen.&lt;br /&gt;
&lt;br /&gt;
Dabei gibt es drei Möglichkeiten, wie diese geschrieben werden können:&lt;br /&gt;
*Direktes Verwenden von SET-Kommando oder Reading des aktuellen Device:&lt;br /&gt;
:&amp;lt;code&amp;gt;cmd=on or currentReading=temperature&amp;lt;/code&amp;gt;&lt;br /&gt;
*Umleiten eines Kommando auf ein anderes Device oder Verwenden eines Readings aus einem anderen Gerät:&lt;br /&gt;
:&amp;lt;code&amp;gt;cmd=Otherdevice:on or currentReading=Otherdevice:temperature&amp;lt;/code&amp;gt;&lt;br /&gt;
*Perl-Code um einen Befehl auszuführen oder einen Wert zu setzen:&lt;br /&gt;
:Das ermöglicht sehr komplexe Anfragen.&lt;br /&gt;
:Der Code muss in geschwungenen Klammern sein.&lt;br /&gt;
:&amp;lt;code&amp;gt;{currentVal={ReadingsVal($DEVICE,&amp;quot;state&amp;quot;,0)}&amp;lt;/code&amp;gt;&lt;br /&gt;
:oder&lt;br /&gt;
:&amp;lt;code&amp;gt; cmd={fhem(&amp;quot;set $DEVICE dim $VALUE&amp;quot;)}&amp;lt;/code&amp;gt;&lt;br /&gt;
:$DEVICE ist das aktuelle FHEM-device. Der SetNumeric-Intent kann $VALUE für den Wert verwenden, der gesetzt werden soll.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== rhasspySpecials ===&lt;br /&gt;
Dieses Attribut wirkt ähnlich wie [[#rhasspyTweaks| rhasspyTweaks]], verändert allerdings nur jeweils das Verhalten des Geräts, bei dem es gesetzt ist. Auch dieses Attribut wird zeilenweise eingelesen, es können ein oder mehrere der folgenden Optionen gesetzt werden:&lt;br /&gt;
&lt;br /&gt;
==== group ====&lt;br /&gt;
::Wird dieser Schlüssel gesetzt, wird das Gerät bei Gruppenaktionen nicht direkt adressiert, sondern die hier angegebene Gruppe. Details hierzu sind in [[RHASSPY/Vertiefung#Timing-Aspekte| Vertiefung - Timing-Aspekte]] zu finden.&lt;br /&gt;
&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;attr lamp1 rhasspySpecials group:async_delay=100 prio=1 group=lights&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== numericValueMap ====&lt;br /&gt;
::Ermöglicht es, statt der allgemeinen Methode zum Umgang mit numerischen Werten einzelnen Werten spezielle Kommandos zuzuweisen. Dies kann z.B. hilfreich sein, um spezielle Positionen für Rollladengeräte anzusteuern.&lt;br /&gt;
::&#039;&#039;&#039;Beispiel&#039;&#039;&#039;:&lt;br /&gt;
::&amp;lt;code&amp;gt;attr blind1 rhasspySpecials numericValueMap:10=&#039;Event Slit&#039; 50=&#039;myPosition&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
::führt dazu, dass ein numerischer Wert von 10 (im {Value}-key) das Kommando &amp;lt;code&amp;gt;set blind1 Event Slit&amp;lt;/code&amp;gt; ausführt.&lt;br /&gt;
&lt;br /&gt;
==== venetianBlind ====&lt;br /&gt;
Siehe [[RHASSPY/Vertiefung#Jalousien|Vertiefung - Jalousien]]&lt;br /&gt;
&lt;br /&gt;
==== colorCommandMap ====&lt;br /&gt;
Sowie **colorTempMap** und **colorForceHue2rgb**&lt;br /&gt;
Siehe [[RHASSPY/Vertiefung#Farben|Vertiefung - Farben]]&lt;br /&gt;
&lt;br /&gt;
==== priority ====&lt;br /&gt;
Ermöglicht es, Rückfragen zu vermeiden, wenn mehrere Geräte für bestimmte Aktionen in Frage kommen. Siehe [[RHASSPY/Vertiefung#Einer_statt_alle|Einer statt alle]]&lt;br /&gt;
&lt;br /&gt;
==== confirm ====&lt;br /&gt;
Ist eine Möglichkeit, Geräte nur nach Rückfrage und Bestätigung zu schalten (ähnlich wie &#039;&#039;confirmIntents&#039;&#039; in &#039;&#039;rhasspyTweaks&#039;&#039;). Es können entweder einfach nur Intent-Namen angegeben werden, oder Paare von **Intent** und zugehöriger **response**:&lt;br /&gt;
 SetOnOff=&amp;quot;Soll $target wirklich $Value geschaltet werden&amp;quot; SetScene&lt;br /&gt;
&lt;br /&gt;
==== confirmValueMap ====&lt;br /&gt;
Kann spezielle Übersetzungen für $Value enthalten, z.B. für Rollladen-Geräte:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;confirm: SetOnOff=&amp;quot;wirklich $Value $target&amp;quot;&lt;br /&gt;
confirmValueMap: on=öffnen off=schließen&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== scenes ====&lt;br /&gt;
Wird bei der automatisierten Erfassung erkannt, dass ein Gerät das Setzen von Szenen unterstützt, werden die erkannten Szenen-Namen an Rhasspy übergeben. Da diese häufig technischer Natur sind, eignen sie sich nicht für eine Spracherkennung. Über diesen Schlüssel können daher sprechbare Namen für jede Szene vergeben werden, und/oder einzelne bzw. alle Szenen von der Erkennung ausgenommen werden. Der Kenner &#039;&#039;none&#039;&#039; löscht die Szene von der Liste der übermittelten Szenen, wird die Kombination &#039;&#039;all=none&#039;&#039; angegeben, wird dieses Gerät insgesamt von der Vorbereitung für den Intent &#039;&#039;SetScene&#039;&#039; ausgeschlossen.&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;attr lamp1 rhasspySpecials scenes:scene2=&amp;quot;Kino zu zweit&amp;quot; scene3=Musik scene1=none scene4=none&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Siehe auch [[RHASSPY/Vertiefung#echte_Szenen|Vertiefung - echte Szenen]]. &lt;br /&gt;
&lt;br /&gt;
=== Veraltete Attribute ===&lt;br /&gt;
In der Regel sollte es ausreichen, die zu steuernden Devices über die oben genannten Attribute zu konfigurieren. Es gibt jedoch noch zwei ältere Methoden. Um diese zu verwenden, muss zuerst jeweils ein entsprechendes User-Attribut im FHEM-Device, das damit gesteuert werden soll, angelegt werden.&lt;br /&gt;
&lt;br /&gt;
==== rhasspyChannels ====&lt;br /&gt;
Das Attribut wird vom Intent &#039;&#039;MediaControls&#039;&#039; verwendet. Es informiert den Intent darüber, welche (Medien-)Kanäle vorhanden sind und welcher FHEM-Befehl oder Perl-Code auszuführen ist, wenn auf diesen Kanal geschaltet werden soll.&lt;br /&gt;
&lt;br /&gt;
In diesem Attribut muss eine Zeile pro (Medien-)Kanal verwendet werden.&lt;br /&gt;
&lt;br /&gt;
Um rhasspyChannels zu verwenden, muss zuerst ein neues User-Attribut im FHEM-Device, das damit gesteuert werden soll, angelegt werden. Dafür kann z.B. dieses Beispiel verwendet werden: &amp;lt;code&amp;gt;attr &amp;lt;deviceName&amp;gt; userattr rhasspyChannels:textField-long&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr &amp;lt;device&amp;gt; rhasspyChannels orf eins=channel 201&lt;br /&gt;
orf zwei=channel 202&lt;br /&gt;
orf drei=channel 203&lt;br /&gt;
netflix=launchApp Netflix&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== rhasspyColors ====&lt;br /&gt;
Ältere Methode, die verwendet werden kann, um Lichtfarben zu wechseln. Es wird nachdrücklich empfohlen, die neueren Methoden über die (nummerisch zu übergebenden) allgemeinen Farbwerte und/oder ein &#039;&#039;colorCommandMap&#039;&#039; oder &#039;&#039;colorTempMap&#039;&#039; (siehe &#039;&#039;rhasspySpecials&#039;&#039;) zu konfigurieren!&lt;br /&gt;
&lt;br /&gt;
Um das Mapping zu verwenden, muss zuerst ein User-Attribut am zu steuernden Gerät angelegt werden. Z.B. &amp;lt;code&amp;gt;attr &amp;lt;deviceName&amp;gt; userattr rhasspyChannels:textField-long&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Eine Zeile pro Farbe&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr lamp1 rhasspyColors rot=rgb FF0000&lt;br /&gt;
grün=rgb 008000&lt;br /&gt;
blau=rgb 0000FF&lt;br /&gt;
gelb=rgb FFFF00&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Intents ==&lt;br /&gt;
Intents werden verwendet um FHEM zu sagen, was es nach einem erhaltenen Sprach-/Textkommand unternehmen soll. Dieses Modul stellt einige Intents bereit.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Wichtig&lt;br /&gt;
:*Bei Tags (&amp;lt;code&amp;gt;Value&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;, etc.) ist die Schreibweise sehr wichtig! Die sind case-sensitive. Bitte daher genau so schreiben, wie sie in dieser Dokumentation vorkommen.&lt;br /&gt;
:*RHASSPY erstellt bei einem &amp;lt;code&amp;gt;update slots&amp;lt;/code&amp;gt; auch Slots je nach Möglichkeiten der Geräte oder Gruppen. Unterstützt ein Gerät zum Beispiel den Intent &#039;&#039;GetNumeric&#039;&#039;, wird auch ein Slot &amp;lt;code&amp;gt;de.fhem.Device-GetNumeric&amp;lt;/code&amp;gt; erstellt. Ein Gerät, dass ein- und ausgeschalten werden kann, wird im Slot &amp;lt;code&amp;gt;de.fhem.Device-SetOnOff&amp;lt;/code&amp;gt; untergebracht. Ein einzelnes Gerät kann sich auch in mehreren Slots befinden. Um eine möglichst genaue Spracherkennung zu gewährleisten, ist &#039;&#039;&#039;empfohlen&#039;&#039;&#039;, diese &#039;&#039;&#039;spezifischen Slots&#039;&#039;&#039; - statt einfach nur &amp;lt;code&amp;gt;de.fhem.Device&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;de.fhem.Group&amp;lt;/code&amp;gt; - &#039;&#039;&#039;zu verwenden&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetOnOff ===&lt;br /&gt;
Intent um Geräte zwischen zwei Zuständen (ein/aus, auf/zu, start/stop) zu schalten.&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
SetOnOff:cmdOn=on,cmdOff=off&lt;br /&gt;
SetOnOff:cmdOn=on,cmdOff=off,response=&amp;quot;Sir yes Sir&amp;quot;&lt;br /&gt;
SetOnOff:cmdOn=on,cmdOff=off,response=&amp;quot;$DEVICE now [$DEVICE:state]&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Argumente:&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdOn&amp;lt;/code&amp;gt; Befehl um das Gerät einzuschalten. Siehe [[#Formatierung von Befehlen und Readings innerhalb eines rhasspyMappings|Formatierung von Befehlen und Readings innerhalb eines rhasspyMappings]].&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdOff&amp;lt;/code&amp;gt; Befehl um das Gerät auszuschalten. Siehe [[#Formatierung von Befehlen und Readings innerhalb eines rhasspyMappings|Formatierung von Befehlen und Readings innerhalb eines rhasspyMappings]].&lt;br /&gt;
&lt;br /&gt;
Optionale Argumente:&lt;br /&gt;
*&amp;lt;code&amp;gt;response&amp;lt;/code&amp;gt; Eine benutzerdefinierte Antwort auf den Befehl&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
schalten das licht ein&lt;br /&gt;
schließe den rollladen im schlafzimmer&lt;br /&gt;
starte die kaffeemaschine&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetOnOff]&lt;br /&gt;
(schalte|schalt|mache|mach|stelle|stell|starte) [den|die|das] $de.fhem.Device-SetOnOff{Device} [[(im|in dem|auf dem|in der|auf der)] $de.fhem.Room{Room}] (an|ein){Value:on}&lt;br /&gt;
(schalte|schalt|mache|mach|stelle|stell) [den|die|das] $de.fhem.Device-SetOnOff{Device} [[(im|in dem|auf dem|in der|auf der)] $de.fhem.Room{Room}] aus{Value:off}&lt;br /&gt;
(fahre|fahr) [den|die|das] $de.fhem.Device-blind{Device} [[(im|in dem|auf dem|in der|auf der)] $de.fhem.Room{Room}] ((hoch|auf){Value:on}|(zu|runter){Value:off})&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verpflichtende Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Value:on&amp;lt;/code&amp;gt; und/oder &amp;lt;code&amp;gt;Value:off&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetOnOffGroup ===&lt;br /&gt;
Intent um Gruppen von Geräte zwischen zwei Zuständen zu schalten.&lt;br /&gt;
&lt;br /&gt;
Dafür ist ein SetOnOff-Mapping benötigt und alle gewünschten Geräte müssen (ggf. u.A. auch) der gewählten Gruppe angehören (einzustellen über das Attribut &amp;lt;code&amp;gt;group&amp;lt;/code&amp;gt; bzw. &amp;lt;code&amp;gt;rhasspyGroup&amp;lt;/code&amp;gt;, oder allgemein kommend aus rhasspyTweaks - gdt2groups).&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
schalte die lampen in der küche aus&lt;br /&gt;
schließe alle rollläden im schlafzimmer&lt;br /&gt;
schalte sämtliche lampen aus&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetOnOffGroup]&lt;br /&gt;
\[(schalt|mach)] (die | alle | sämtliche ) $de.fhem.Group-SetOnOff{Group} [[in|im|in der|auf der] [( überall:global | $de.fhem.Room ){Room}] ein{Value:on}&lt;br /&gt;
\[(schalt|mach)] (die | alle | sämtliche ) $de.fhem.Group-SetOnOff{Group} [[in|im|in der|auf der] [( überall:global | $de.fhem.Room ){Room}] aus{Value:off}&lt;br /&gt;
(öffne{Value:on}|schließe{Value:off}) (alle | sämtliche ) $de.fhem.Group-blind{Group} [[in|im|in der|auf der] [( überall:global{Room:global} | $de.fhem.Room{Room} )] &lt;br /&gt;
(fahr|fahre|mach|mache) [den|die|das] $de.fhem.Group-blind{Group} [[(im|in dem|in der)] ( überall:global{Room:global} | $de.fhem.Room{Room} )] ( auf{Value:on} | hoch{Value:on} | zu{Value:off} | runter{Value:off} )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verpflichtende Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Value:on&amp;lt;/code&amp;gt; und/oder &amp;lt;code&amp;gt;Value:off&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Group&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== SetTimedOnOff ===&lt;br /&gt;
Intent um Geräte für eine bestimmte Zeitspanne in einen bestimmten Zustand zu versetzten.&lt;br /&gt;
&lt;br /&gt;
Device muss ein SetOnOff-Mapping haben und die {{Link2CmdRef|Anker=setExtensions|Lang=de|Label=SetExtentions}} unterstützen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
schalte das licht für eine minute und dreißig sekunden aus&lt;br /&gt;
schalte die musik im bad bis zwei uhr ein&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetTimedOnOff]&lt;br /&gt;
schalte $de.fhem.Device-SetOnOff{Device} [$de.fhem.Room{Room}] für ([(1..60){Hour!int} (stunde|stunden)] [und] [(1..60){Min!int} (minute|minuten)] [und] [(1..60){Sec!int} (sekunde|sekunden)]) (ein{Value:on}|aus{Value:off})&lt;br /&gt;
schalte $de.fhem.Device-SetOnOff{Device} [$de.fhem.Room{Room}] bis (0..24){Hourabs!int} [(1..60){Min!int}] (ein{Value:on}|aus{Value:off})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verpflichtende Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Value&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Hour&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Min&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Sec&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Hourabs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetTimedOnOffGroup ===&lt;br /&gt;
Intent um eine Gruppe von Geräten für eine bestimmte Zeit zu schalten.&lt;br /&gt;
&lt;br /&gt;
Devices müssen ein SetOnOff-Mapping haben, in einer Gruppe sein und die {{Link2CmdRef|Anker=setExtensions|Lang=de|Label=SetExtentions}} unterstützen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
schalte alle lichter in der küche für fünfzig sekunden ein&lt;br /&gt;
schalte alle licher bis zwei uhr ein&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetTimedOnOffGroup]&lt;br /&gt;
schalte $de.fhem.Group-SetOnOff{Group} [$de.fhem.Room{Room}] für ([(1..60){Hour!int} (stunde|stunden)] [und] [(1..60){Min!int} (minute|minuten)] [und] [(1..60){Sec!int} (sekunde|sekunden)]) (ein{Value:on}|aus{Value:off})&lt;br /&gt;
schalte $de.fhem.Group-SetOnOff{Group} [$de.fhem.Room{Room}] bis (0..24){Hourabs!int} [(1..60){Min!int}] (ein{Value:on}|aus{Value:off})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verpflichtende Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Value&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Group&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Hour&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Min&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Sec&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Hourabs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GetOnOff ===&lt;br /&gt;
Intent um den aktuellen Zustand eines Gerätes zu erfragen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
GetOnOff:currentVal=state,valueOff=closed&lt;br /&gt;
GetOnOff:currentVal=state,valueOn=on&lt;br /&gt;
GetOnOff:currentVal=pct,valueOff=0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Argumente:&lt;br /&gt;
Hinweis: nur &amp;lt;code&amp;gt;valueOn&amp;lt;/code&amp;gt; ODER &amp;lt;code&amp;gt;valueOff&amp;lt;/code&amp;gt; müssen gesetzt werden. Der jeweils andere Wert bekommt den anderen Status.&lt;br /&gt;
*&amp;lt;code&amp;gt;currentVal&amp;lt;/code&amp;gt; Reading aus dem der aktuelle Status hervorgeht&lt;br /&gt;
*&amp;lt;code&amp;gt;valueOff&amp;lt;/code&amp;gt; Wert, der den Zustand &#039;&#039;aus&#039;&#039; beschreibt&lt;br /&gt;
*&amp;lt;code&amp;gt;valueOn&amp;lt;/code&amp;gt; Wert, der den Zustand &#039;&#039;an&#039;&#039; beschreibt&lt;br /&gt;
&lt;br /&gt;
Optionale Argumente:&lt;br /&gt;
*&amp;lt;code&amp;gt;response&amp;lt;/code&amp;gt; Eine benutzerdefinierte Antwort auf den Befehl&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
ist das licht im bad ein&lt;br /&gt;
ist das fenster im wohnzimmer geöffnet&lt;br /&gt;
läuft die waschmaschine&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[en.fhem:GetOnOff]&lt;br /&gt;
ist $de.fhem.Device-GetOnOff{Device} [$de.fhem.Room{Room}] (ein|geöffnet){State:on}&lt;br /&gt;
ist $de.fhem.Device-GetOnOff{Device} [$de.fhem.Room{Room}] (aus|geschlossen){State:off}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zustände &#039;&#039;ein&#039;&#039; und &#039;&#039;aus&#039;&#039; sollten in unterschiedlichen Sentences sein und müssen &amp;lt;code&amp;gt;{State:on}&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;{State:off}&amp;lt;/code&amp;gt; beinhalten.&lt;br /&gt;
&lt;br /&gt;
Verpflichtende Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;State:on&amp;lt;/code&amp;gt; und/oder &amp;lt;code&amp;gt;State:off&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetNumeric ===&lt;br /&gt;
Intent, um Lampen zu dimmen, Rollladengeräte zu positionieren, Lautstärken oder Solltemperaturen zu ändern, usw.. &lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
SetNumeric:currentVal=pct,cmd=dim,minVal=0,maxVal=99,step=25,type=brightness&lt;br /&gt;
SetNumeric:currentVal=volume,cmd=volume,minVal=0,maxVal=99,step=10,type=volume&lt;br /&gt;
SetNumeric:currentVal=brightness,cmd=brightness,minVal=0,maxVal=255,map=percent,step=1,type=brightness&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Argumente:&lt;br /&gt;
*&amp;lt;code&amp;gt;currentVal&amp;lt;/code&amp;gt; Reading, in dem der aktuelle Wert zu finden ist (wird zwingend benötigt).&lt;br /&gt;
*&amp;lt;code&amp;gt;part&amp;lt;/code&amp;gt; Kann genutzt werden, um den Wert aus **currentVal** in mehrere Teile zu zerlegen (getrennt wird am Leerzeichen). Z.B. wenn currentVal 23 C ist, wird **part=0** **23** ergeben. Optionaler Parameter.&lt;br /&gt;
*&amp;lt;code&amp;gt;cmd&amp;lt;/code&amp;gt; Das **Set**-Kommando des Geräts, das in Folge des Sprachkommandos ausgeführt werden soll. (Notwendiger Parameter).&lt;br /&gt;
*&amp;lt;code&amp;gt;minVal&amp;lt;/code&amp;gt; Niedrigster zugelassener Wert, optional.&lt;br /&gt;
*&amp;lt;code&amp;gt;maxVal&amp;lt;/code&amp;gt; Höchster zugelassener Wert, optional.&lt;br /&gt;
*&amp;lt;code&amp;gt;step&amp;lt;/code&amp;gt; Schrittweite für relative Änderungen wie &amp;lt;code&amp;gt;mach lauter&amp;lt;/code&amp;gt;. Optional. Default: 10.&lt;br /&gt;
*&amp;lt;code&amp;gt;map&amp;lt;/code&amp;gt; Derzeit wird ausschließlich die Angabe **percent** ausgewertet. Optionaler Parameter, der bewirkt, dass alle Angaben als Prozentwert (zwischen minVal und maxVal) interpretiert werden und entsprechend gerechnet wird. So wird z.B. eine Leuchte mit **minVal=0** und **maxVal=255** beim Befehl &amp;quot;stelle das Licht auf 50&amp;quot; dies so verstehen, als wäre die Anweisung &amp;quot;stelle das Licht auf 50 Prozent&amp;quot; gewesen. Das Licht wird daher auf 127 gestellt, und nicht auf (absolut) 50.&lt;br /&gt;
*&amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; Zur Unterscheidung, falls mehrere SetNumeric-Intents für das Gerät möglich sind. Empfohlener Parameter.&lt;br /&gt;
&lt;br /&gt;
Gut zu wissen:&lt;br /&gt;
Um Kommandos wie **lauter** oder **leiser** ohne Angabe eines Gerätes ausführen zu können, muss RHASSPY zunächst ermitteln, welches Gerät gerade überhaupt etwas wiedergibt ist. Daher nutzt es die GetOnOff-Mappings, um festzustellen, welches Gerät vom **type=volume** überhaupt angeschaltet ist. Dabei wird wie üblich zunächst im aktuellen rhasspyRoom gesucht, bevor die Suche außerhalb fortgesetzt wird.&lt;br /&gt;
Setzt man also Mappings manuell, ist es ratsam, auch ein **GetOnOff**-Mapping zu setzen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zulässige Typen sind:&lt;br /&gt;
*&amp;lt;code&amp;gt;brightness&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;setTarget&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;temperature&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;volume&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
Stelle das Licht auf 30 Prozent&lt;br /&gt;
Mach das Radio leiser&lt;br /&gt;
Stell die Temperatur im Wohnzimmer 2 Grad wärmer&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
(Beachte: Wenn wie hier im Beispiel reele Zahlen (mit Komma) ermöglicht werden sollen (&amp;quot;acht Komma fünf&amp;quot;), wird ein [[#Custom Converter für reelle Zahlen| Custom Converter für reelle Zahlen]] benötigt)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetNumeric]&lt;br /&gt;
den=(den|die|das)&lt;br /&gt;
cmdmulti=(schalte|schalt|mache|mach|stelle|stell)&lt;br /&gt;
rooms=([(im|in dem|auf dem|in der|auf der)] $de.fhem.Room{Room})&lt;br /&gt;
&amp;lt;cmdmulti&amp;gt; [&amp;lt;den&amp;gt;] $de.fhem.Device-SetNumeric{Device} auf (0..100){Value!int} [Prozent{Unit:percent}]&lt;br /&gt;
\[&amp;lt;cmdmulti&amp;gt;] [die Lautstärke [an|am]] [dem|&amp;lt;den&amp;gt;] $de.fhem.Device-media{Device} [&amp;lt;rooms&amp;gt;] [um] [(0..10){Value!float}] [dezibel{Unit:decibel}|Prozent{Unit:percent}] ( lauter:volUp | leiser:volDown ){Change}&lt;br /&gt;
&amp;lt;cmdmulti&amp;gt; [die Lautstärke [an|am]] [dem|&amp;lt;den&amp;gt;] [$de.fhem.Device-media{Device}] [&amp;lt;rooms&amp;gt;] [um] [(0..10){Value!float}] [dezibel{Unit:decibel}|Prozent{Unit:percent}] ( lauter:volUp | leiser:volDown ){Change}&lt;br /&gt;
&amp;lt;cmdmulti&amp;gt; [&amp;lt;den&amp;gt;] $de.fhem.Device-thermostat{Device} [&amp;lt;rooms&amp;gt;] [um] [(0..10){Value!int}] [Grad{Unit.degree}] ( wärmer:tempUp | kälter:tempDown ){Change}&lt;br /&gt;
&amp;lt;cmdmulti&amp;gt; [&amp;lt;den&amp;gt;] $de.fhem.Device-light{Device} [&amp;lt;rooms&amp;gt;] [um] [(0..30 [Komma:. 1..9]){Value!customFloat}] [Prozent{Unit:percent}] ( heller:lightUp | dunkler:lightDown){Change}&lt;br /&gt;
&amp;lt;cmdmulti&amp;gt; [&amp;lt;den&amp;gt;] ( $de.fhem.Device-light | $de.fhem.Device-media |$de.fhem.Device-blind){Device}  [&amp;lt;rooms&amp;gt;] auf [(0..30 [Komma:. 1..9]){Value!customFloat}]&lt;br /&gt;
\[deutlich{Factor:2}] ( mehr{Change:lightUp} | weniger{Change:lightDown} ) $de.fhem.Device-light{Device} [&amp;lt;de.fhem:SetOnOff.rooms&amp;gt;]&lt;br /&gt;
( halte | stoppe | stop ) [&amp;lt;den&amp;gt;] $de.fhem.Device-blind{Device} [&amp;lt;de.fhem:SetOnOff.rooms&amp;gt;] [an] {Change:cmdStop}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Derzeit werden folgende Typen für das Feld &amp;lt;code&amp;gt;{Change}&amp;lt;/code&amp;gt; ausgewertet:&lt;br /&gt;
*&amp;lt;code&amp;gt;tempUp&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;tempDown&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;volUp&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;volDown&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;lightUp&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;lightDown&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;setUp&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;setDown&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notwendig sind:&lt;br /&gt;
*&amp;lt;code&amp;gt;Change&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Type&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Value&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Change&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Unit&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Factor&amp;lt;/code&amp;gt; Dieser Wert wird mit der Standard-Schrittweite (&amp;lt;code&amp;gt;step&amp;lt;/code&amp;gt; im Mapping) multipliziert&lt;br /&gt;
&lt;br /&gt;
=== SetNumericGroup ===&lt;br /&gt;
Intent, um Lampen zu dimmen, Rollladengeräte zu positionieren, Lautstärken oder Solltemperaturen zu ändern, usw.. Die Funktionsweise entspricht dabei dem des Intents &#039;&#039;SetNumeric&#039;&#039;, wobei eben statt eines einzelnen Devices eben ein oder mehrere Geräte über ihren Gruppennamen angesprochen werden. Statt des optionalen Tags &amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt; ist daher der Tag &amp;lt;code&amp;gt;Group&amp;lt;/code&amp;gt; zu übergeben.&lt;br /&gt;
Aus der Adressierung mehrerer Geräte ergeben sich einige Besonderheiten, die in der [[RHASSPY/Vertiefung]], dort speziell auch im Punkt [[RHASSPY/Vertiefung#Beispiel_SetOnOffGroup|Beispiel SetOnOffGroup]] näher erläutert sind. Wesentliche zu beachtende Aspekte sind:&lt;br /&gt;
* Vermeidung von Funk-Überschneidungen (&#039;&#039;Specials&#039;&#039; &#039;&#039;partOf&#039;&#039; und &#039;&#039;async_delay&#039;&#039;)&lt;br /&gt;
* Begrenzung der Gruppenzugehörigkeit durch die Raumzugehörigkeit (und die Aufhebung dieser Beschränkung durch die Übergabe des speziellen Raums &#039;&#039;global&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
=== GetNumeric ===&lt;br /&gt;
Intent, mit dem man Werte erfragen kann, wie z.B. die aktuelle Temperatur, Helligkeit, Lautstärke, ...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
GetNumeric:currentVal=temperature,part=1,type=temperature&lt;br /&gt;
GetNumeric:currentVal=pct,map=percent,minVal=0,maxVal=100,type=brightness&lt;br /&gt;
GetNumeric:currentVal=volume,type=volume&lt;br /&gt;
GetNumeric:currentVal=humidity,part=0,type=humidity&lt;br /&gt;
GetNumeric:currentVal=batteryPercent,type=battery&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Argumente:&lt;br /&gt;
*&amp;lt;code&amp;gt;currentVal&amp;lt;/code&amp;gt; Das Reading, das den abzufragenden Wert enthält&lt;br /&gt;
*&amp;lt;code&amp;gt;part&amp;lt;/code&amp;gt; Teile aus currentVal ableiten, indem am Leerzeichen getrennt wird. Ist &#039;&#039;currentVal&#039;&#039; beispielsweise &#039;&#039;23 C&#039;&#039;, entspricht &#039;&#039;part=1&#039;&#039; dem Wert &#039;&#039;23&#039;&#039;&lt;br /&gt;
*&amp;lt;code&amp;gt;map&amp;lt;/code&amp;gt; Die Funktionswiese entspricht dem &#039;&#039;SetNumeric&#039;&#039; Intent. Wandelt den vorhandenen Wert in eine Prozent-Angabe um.&lt;br /&gt;
*&amp;lt;code&amp;gt;minVal&amp;lt;/code&amp;gt; Niedrigster zulässiger Wert (nur benötigt, wenn &#039;&#039;map&#039;&#039; angegeben ist).&lt;br /&gt;
*&amp;lt;code&amp;gt;maxVal&amp;lt;/code&amp;gt; Höchster zulässiger Wert  (nur benötigt, wenn &#039;&#039;map&#039;&#039; angegeben ist).&lt;br /&gt;
*&amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; Dient der Unterscheidung zwischen mehreren GetNumeric-Anfragemöglichkeiten für dasselbe Gerät (auch relevant für SetNumeric-Anweisungen).&lt;br /&gt;
&lt;br /&gt;
Mögliche Abfragetypen:&lt;br /&gt;
*&amp;lt;code&amp;gt;humidity&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;battery&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;brightness&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;desired-temp&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;setTarget&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;soilMoisture&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;temperature&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;volume&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;waterLevel&amp;lt;/code&amp;gt;&lt;br /&gt;
Aus dem Abfragetypen ergibt sich die von RHASSPY ausgewählte Antwort.&lt;br /&gt;
&lt;br /&gt;
Beispiel Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
what is the temperature in the living room&lt;br /&gt;
how bright is the floor lamp&lt;br /&gt;
what is the volume of the tv&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
[en.fhem:GetNumeric]&lt;br /&gt;
#actual temperature&lt;br /&gt;
(what is|how high is) the temperature{Type:temperature} [$de.fhem.Device-GetNumeric{Device}] [$de.fhem.Room{Room}]&lt;br /&gt;
&lt;br /&gt;
#desired-temperature&lt;br /&gt;
\[what is the|how high is the] (desired temperature){Type:desired-temp} [$de.fhem.Device-GetNumeric{Device}] [$de.fhem.Room{Room}]&lt;br /&gt;
&lt;br /&gt;
#volume&lt;br /&gt;
(what is the|how high is the) volume{Type:volume} $de.fhem.Device-GetNumeric{Device} [$de.fhem.Room{Room}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Type&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional tags&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== GetState ===&lt;br /&gt;
Intent to get specific information of a device. The respone can be defined.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
GetState:response=&amp;quot;Temperature is [$DEVICE:temp] degree at [Thermo:hum] percent humidity&amp;quot;&lt;br /&gt;
GetState:response={my $value=ReadingsVal(&amp;quot;$DEVICE&amp;quot;,&amp;quot;brightness&amp;quot;,&amp;quot;&amp;quot;); return &amp;quot;Brightness is $value&amp;quot;;}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Options:&lt;br /&gt;
*&amp;lt;code&amp;gt;response&amp;lt;/code&amp;gt; Text for the response Rhassyp will give.&lt;br /&gt;
:To use values from FHEM use format [Device:Reading].&lt;br /&gt;
:A comma within the response has to be escaped (\, instead of ,).&lt;br /&gt;
:Or you can use Perl-code enclosed in curley brackets to define the response.&lt;br /&gt;
:Mixing text and Perl-code is not supported.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
How is the state of the thermostat in the kitchen&lt;br /&gt;
state light in livingroom&lt;br /&gt;
state washer&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:GetState]&lt;br /&gt;
\[how is the] (state) $de.fhem.Device{Device} [$de.fhem.Room{Room}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== MediaControls ===&lt;br /&gt;
Intent to control media devices&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mapping:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
MediaControls:cmdPlay=play,cmdPause=pause,cmdStop=stop,cmdBack=previous,cmdFwd=next&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Options:&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdPlay&amp;lt;/code&amp;gt; Play command of the device. See chapter Formatting Commands and Readings inside a rhasspyMapping.&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdPause&amp;lt;/code&amp;gt; Command to pause the device.&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdStop&amp;lt;/code&amp;gt; Command to stop the device.&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdFwd&amp;lt;/code&amp;gt; Command to skip to the next track/channel/etc.&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdBack&amp;lt;/code&amp;gt; Command to skip to the previous track/channel/etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note on issuing a voice-command without a room-name:&lt;br /&gt;
As described in the SetNumeric-Intent, it is recommended to define a GetOnOff-Mapping to use the MediaControls-Intent without a room name.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
skip to next track on the radio&lt;br /&gt;
pause&lt;br /&gt;
skip video on the dvd player&lt;br /&gt;
stop playback&lt;br /&gt;
next&lt;br /&gt;
previous&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:MediaControls]&lt;br /&gt;
(start){Command:cmdPlay} the playback [$de.fhem.Device-MediaControls{Device}]&lt;br /&gt;
(stop){Command:cmdStop} the playback [$de.fhem.Device-MediaControls{Device}]&lt;br /&gt;
(pause){Command:cmdPause} the playback [$de.fhem.Device-MediaControls{Device}]&lt;br /&gt;
(next){Command:Fwd} (song|title) [$de.fhem.Device-MediaControls{Device}]&lt;br /&gt;
(previous){Command:Back} (song|title) [$de.fhem.Device-MediaControls{Device}] [$de.fhem.Room{Room}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Command&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== MediaChannels ===&lt;br /&gt;
Intent to change radio-/tv channels, favorites, playlists, lightscenes, ...&lt;br /&gt;
&lt;br /&gt;
Instead of using the attribute rhasspyMapping, this intent is configured with an own attribute [[#rhasspyChannels]] in the respective device. Reason is the multiple-line-configuration.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
SWR3=favorite s_w_r_3&lt;br /&gt;
SWR1=favorite s_w_r_1&lt;br /&gt;
ARD=channel 204&lt;br /&gt;
Netflix=launchApp Netflix&lt;br /&gt;
Leselicht=set lightSceneWz scene Leselicht&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Notice on using the commands without a device name:&lt;br /&gt;
To start playback on a device without specifying the device name in the voice command, the module needs to know, which device should be used. Therefor it searches the attribute rhasspyChannels for suitable one. Devices in the actual or spoken room are preferred.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
play CNN on the radio in my office&lt;br /&gt;
switch to HBO&lt;br /&gt;
change channel on radio to BBC news&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[en.fhem:MediaChannels]&lt;br /&gt;
\[(play|switch to|change to)] ($de.fhem.MediaChannels){Channel} [($de.fhem.Device){Device}] [($de.fhem.Room){Room}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Channel&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetColor ===&lt;br /&gt;
Intent to change light colors&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Because of the multi-line settings, instead of configuring this intent with the attribute rhasspyMapping, a separate user-attribute [[#rhasspyColors]] is used.&lt;br /&gt;
&lt;br /&gt;
The content of the rhasspyColors uses the following format:&lt;br /&gt;
&amp;lt;code&amp;gt;Colorname=cmd&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Settings:&lt;br /&gt;
*&amp;lt;code&amp;gt;Colorname&amp;lt;/code&amp;gt; The name of the color you want to use in a voice-command&lt;br /&gt;
*&amp;lt;code&amp;gt;cmd&amp;lt;/code&amp;gt; The FHEM-command&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
red=rgb FF0000&lt;br /&gt;
green=rgb 00FF00&lt;br /&gt;
blue=rgb 0000FF&lt;br /&gt;
white=ct 3000&lt;br /&gt;
warm white=ct 2700&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
change light to green&lt;br /&gt;
lightstrip blue&lt;br /&gt;
color the light in the sleeping room white&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[en.fhem:SetColor]&lt;br /&gt;
\[change|color] $de.fhem.Device{Device} [$de.fhem.Room{Room}] $de.fhem.Color{Color}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Color&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional tags&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetColorGroup ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetScene ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GetTime ===&lt;br /&gt;
Intent um die Uhrzeit zu erfragen.&lt;br /&gt;
&lt;br /&gt;
Es werden keine Konfigurationen in FHEM benötigt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
wie spät ist es?&lt;br /&gt;
sag mir die uhrzeit&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:GetTime]&lt;br /&gt;
wie spät [ist es]&lt;br /&gt;
sag mir die uhrzeit&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GetDate ===&lt;br /&gt;
Intent um das aktuelle Datum zu erfragen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Keine FHEM Einstellungen nötig.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Satz:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
welcher tag ist heute&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:GetDate]&lt;br /&gt;
welcher tag ist heute&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetTimer ===&lt;br /&gt;
Intent to create a timer/countdown/alarm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This intent creates an AT-command in FHEM with the given time and - currently - speaks the sentences &amp;quot;timer expired&amp;quot; when it has expired.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
No FHEM-settings needed&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
Set timer in bedroom to five minutes&lt;br /&gt;
Set countdown in the kitchen to two hours&lt;br /&gt;
set timer to five and a half hours&lt;br /&gt;
set alarm to 5 o&#039; clock&lt;br /&gt;
set timer to 3 hours and 20 minutes&lt;br /&gt;
set timer to 1 hour, 30 minutes and 15 seconds&lt;br /&gt;
stop the timer in bedroom&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentence:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetTimer]&lt;br /&gt;
labels=(alarm|teetimer|countdown|timer)&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in) [((1..60){Hour!int} (hour|hours))] [and] [((1..60){Min!int} (minute|minutes))] [and] [((1..60){Sec!int} (second|seconds))]&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in) (1..60){Hour!int} and (a quarter{Min:15}|a half{Min:30}|three quarters{Min:45}) (hour|hours)&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in) (1..60){Min!int} and (a quarter{Sec:15}|a half{Sec:30}|three quarters{Sec:45}) (minute|minutes)&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in) ((the fourth){Min:15}|(half a){Min:30}|(three fourth){Min:45}) (hour)&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in) ((the fourth){Min:15}|(half a){Min:30}|(three fourth){Min:45}) (minute)&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in|at) (1..24){Hourabs!int} [(1..60){Min!int}] o clock&lt;br /&gt;
&lt;br /&gt;
(cancel|remove|stop|delete){CancelTimer} [&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags to set a timer:&lt;br /&gt;
*&amp;lt;code&amp;gt;Label&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Hour&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Hourabs&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Min&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Sec&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags to cancel a timer:&lt;br /&gt;
*&amp;lt;code&amp;gt;Label&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
rhasspyTweaks for Timer:&lt;br /&gt;
*&amp;lt;code&amp;gt;[[#attr-rhasspytweaks-timerlimits|timerLimits]]&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;[[#attr-rhasspytweaks-timersounds|timerSounds]]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetMute ===&lt;br /&gt;
Intent to disable/enable the processing of intents on a specific siteId. Rhasspy will still listen to the wakeword but will not process any intents.&lt;br /&gt;
&lt;br /&gt;
This intents creates a Reading &amp;lt;code&amp;gt;mute_siteId&amp;lt;/code&amp;gt; for every siteId it get&#039;s a voice-command from.&lt;br /&gt;
&lt;br /&gt;
No FHEM-settings needed&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
good night&lt;br /&gt;
be quiet&lt;br /&gt;
good morning&lt;br /&gt;
make noise&lt;br /&gt;
start listening&lt;br /&gt;
stop listening&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel für Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetMute]&lt;br /&gt;
(good night|be quiet){Value:on}&lt;br /&gt;
(good morning|make noise){Value:off}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hinweis: Die Felder &amp;lt;code&amp;gt;{Value:on}&amp;lt;/code&amp;gt; bzw. &amp;lt;code&amp;gt;{Value:off}&amp;lt;/code&amp;gt; sind verpflichtend und &#039;&#039;case sensitive&#039;&#039;, der Wert &#039;&#039;on&#039;&#039; bzw. &#039;&#039;off&#039;&#039; ist in Englisch anzugeben!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ConfirmAction ===&lt;br /&gt;
Dies ist - wie die folgenden Intents &#039;&#039;CancelAction&#039;&#039; und &#039;&#039;Choice&#039;&#039; (bzw. die überholten Varianten &#039;&#039;ChoiceRoom&#039;&#039; und &#039;&#039;ChoiceDevice&#039;&#039;) auch - ein Intent, der im Rahmen von Dialogen benötigt wird. Siehe dazu auch [[RHASSPY/Vertiefung#Dialoge|Vertiefung - Dialoge]].&lt;br /&gt;
Um eine Aktion tatsächlich auszuführen, ist als Rückgabe zwingend &amp;lt;code&amp;gt;{Mode}&amp;lt;/code&amp;gt; mit dem Wert &#039;&#039;OK&#039;&#039; erforderlich, alles andere wird so behandelt, als wäre der Intent &#039;&#039;CancelAction&#039;&#039; ausgewählt worden, was zur Beendigung des Dialogs ohne Aktion führt.&lt;br /&gt;
&lt;br /&gt;
=== CancelAction ===&lt;br /&gt;
Siehe &#039;&#039;ConfirmAction&#039;&#039;. Dieser Intent muss nicht zwingend existieren, es kann auch ein unpassender Rückgabewert in &#039;&#039;ConfirmAction&#039;&#039; angegeben werden, um die Abbruch-Routinen für Dialoge zu starten.&lt;br /&gt;
&lt;br /&gt;
=== Choice ===&lt;br /&gt;
Siehe &#039;&#039;ConfirmAction&#039;&#039;. Dient im Rahmen von Dialogen der Auswahl von einem oder mehreren der folgenden Elemente:&lt;br /&gt;
&amp;lt;code&amp;gt;{Device}&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;{Room}&amp;lt;/code&amp;gt; und/oder &amp;lt;code&amp;gt;{Scene}&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Beispiel für Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:Choice]&lt;br /&gt;
den=(den|die|das)&lt;br /&gt;
choose= ( nimm [bitte] | [bitte] nimm | ich hätte gerne | [ich] (wähle|nehme) )&lt;br /&gt;
&lt;br /&gt;
&amp;lt;choose&amp;gt; [ &amp;lt;den&amp;gt; [( Gerät | $de.fhem.Aliases{Device} )] ] ( aus ( dem | der ) | im | den | die ) $de.fhem.MainRooms{Room}&lt;br /&gt;
&amp;lt;choose&amp;gt; [ &amp;lt;den&amp;gt; ] $de.fhem.Aliases{Device} [ ( aus ( dem | der ) | im | den | die ) $de.fhem.MainRooms{Room} ]&lt;br /&gt;
&amp;lt;choose&amp;gt; [ ( die Szene | den Modus ) ] $de.fhem.Scenes [Modus] [ [( am | vom )] $de.fhem.Aliases{Device} ] [( aus ( dem | der ) | im | den | die ) $de.fhem.MainRooms{Room} ] [bitte]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== ChoiceRoom ====&lt;br /&gt;
Veralteter Intent. Diente im Rahmen von Dialogen der Auswahl eines Raums, wird heute pauschal nach &#039;&#039;Choice&#039;&#039; umgeleitet und sollte nicht mehr verwendet werden!&lt;br /&gt;
&lt;br /&gt;
==== ChoiceDevice ====&lt;br /&gt;
Veralteter Intent. Diente im Rahmen von Dialogen der Auswahl eines Gerätes, wird heute pauschal nach &#039;&#039;Choice&#039;&#039; umgeleitet und sollte nicht mehr verwendet werden!&lt;br /&gt;
&lt;br /&gt;
=== ReSpeak ===&lt;br /&gt;
Wiederholt den letzten Satz, den Rhasspy gesprochen hat. Um genauer zu sein: Spricht den Inhalt des FHEM Readings &amp;lt;code&amp;gt;voiceResponse&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Keine Einstellungen in FHEM benötigt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
was hast du gesagt&lt;br /&gt;
kannst du das wiederholen&lt;br /&gt;
ich habe dich nicht verstanden&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:ReSpeak]&lt;br /&gt;
was hast du gesagt&lt;br /&gt;
kannst du das [bitte] wiederholen&lt;br /&gt;
ich habe dich nicht verstanden&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Eigene Intents erstellen ==&lt;br /&gt;
Es ist auch möglich, eigene Intents zu erstellen, sollten die hier vorgestellten nicht reichen. Dafür gibt es zwei Wege: Für kleinere Intents können die Möglichkeiten von FHEMs [[99_myUtils_anlegen|99_myUtils.pm]] genutzt werden. Aufwendigere Intents können in jeweils eigenen Dateien abgelegt werden, die dann von RHASSPY ausgelesen werden.&lt;br /&gt;
=== Intents in 99_myUtils.pm ===&lt;br /&gt;
&lt;br /&gt;
Hier ein (veraltetes, siehe oben) Beispiel, mit dem die letzte &#039;&#039;voice response&#039;&#039; wiederholt werden kann.&lt;br /&gt;
&lt;br /&gt;
Ergänze deine 99_myUtils.pm mit folgender Funktion:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub Respeak(){&lt;br /&gt;
  #Credits to JensS&lt;br /&gt;
  my $name = &amp;quot;Rhasspy&amp;quot;; #Replace &amp;quot;Rhasspy&amp;quot; with the name of your RHASSPY-Device&lt;br /&gt;
  my $response = ReadingsVal($name,&amp;quot;voiceResponse&amp;quot;,&amp;quot;Ich kann mich leider nicht erinnern&amp;quot;);&lt;br /&gt;
  return $response;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ergänze im Attribut &#039;&#039;rhasspyIntents&#039;&#039; folgende Zeile (je Intent muss eine eigene Zeile verwendet werden):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
Respeak=Respeak()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ergänze einen neuen Intent in deinen &#039;&#039;sentence.ini&#039;&#039; an der Rhasspy base:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:Respeak]&lt;br /&gt;
was hast du gesagt&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Intents in eigenen Dateien ===&lt;br /&gt;
Beispiele: https://github.com/fhem/fhem-rhasspy/blob/main/FHEM/99_RHASSPY_Utils_Demo.pm&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: Raumwechsel ====&lt;br /&gt;
Erforderlichen Code in das Modulverzeichnis holen und laden: &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;{ Svn_GetFile(&#039;contrib/RHASSPY/99_RHASSPY_Utils_siteId2room.pm&#039;, &#039;FHEM/99_RHASSPY_Utils_siteId2room.pm&#039;,sub(){ RHASSPY_Utils_siteId2room_Initialize() }) }&amp;lt;/syntaxhighlight&amp;gt;Ergänze im Attribut &#039;&#039;rhasspyIntents&#039;&#039; folgende Zeile (je Intent muss eine eigene Zeile verwendet werden):&lt;br /&gt;
&amp;lt;syntaxhighlight  lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
siteId2room=RHASSPY::siteId2room::siteId2room(NAME,DATA)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Ergänze einen neuen Intent in deinen &#039;&#039;sentence.ini&#039;&#039; an der Rhasspy base:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:siteId2room]&lt;br /&gt;
( Ortswechsel  | begib dich ) ( ins | in den ) $de.fhem.Room{Room}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tipps &amp;amp; Tricks ==&lt;br /&gt;
===Custom Converter für reelle Zahlen===&lt;br /&gt;
{{Randnotiz|RNTyp=g|RNText=RHASSPY enthält für &amp;lt;code&amp;gt;{Value}&amp;lt;/code&amp;gt; nunmehr auch einen Konverter, der Leerzeichen aus Zahlenwerten entfernt. Enthält dieses Datenfeld bei der Übergabe aus Rhasspy z.B. &amp;lt;code&amp;gt;- 10 .5&amp;lt;/code&amp;gt;, wird dies automatisch in &amp;lt;code&amp;gt;-10.5&amp;lt;/code&amp;gt; umgewandelt.}}&lt;br /&gt;
Rhasspy kann (derzeit) keine gesprochenen reellen Nummern (z.B. 22,5) als Nummer erkennen. Stattdessen interpretiert es die Zahl als zwei Nummern und einen Punkt.&lt;br /&gt;
&lt;br /&gt;
Um reelle Nummern richtig zu verwenden, muss ein [https://rhasspy.readthedocs.io/en/latest/training/#converters Custom Converter] erstellt und in der sentences.ini verwendet werden.&lt;br /&gt;
&lt;br /&gt;
So ein Konverter kann erstellt werden, in dem unter &amp;lt;code&amp;gt;&amp;lt;profile&amp;gt;/converters&amp;lt;/code&amp;gt; ein neues File mit beliebigem Namen angelegt wird. Der Name muss aber dann auch genau so als Converter in der sentences.ini verwendet werden. Anschließend muss die Datei noch ausführbar gemacht werden.&lt;br /&gt;
&lt;br /&gt;
Z.B.:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
touch .config/rhasspy/profile/en/converters/customFloat&lt;br /&gt;
chmod +x .config/rhasspy/profile/en/converters/customFloat&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Folgender Beispiel-Code kann danach in die Datei geschrieben werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python3&lt;br /&gt;
import sys&lt;br /&gt;
import json&lt;br /&gt;
&lt;br /&gt;
# von Rhasspy als JSON übergebene/n Wert/e einlesen&lt;br /&gt;
args = json.load(sys.stdin)&lt;br /&gt;
&lt;br /&gt;
# wenn im deserialisierten JSON nur ein Wert ist, wird der als Ergebnis genommen&lt;br /&gt;
# sind mehrere Werte vorhanden (z.B. 22,.,5), werden die zu einem einzelnen String zusammen gesetzt&lt;br /&gt;
if type(args) == int:&lt;br /&gt;
    num = args&lt;br /&gt;
else:&lt;br /&gt;
    num = &amp;quot;&amp;quot;.join(str(s).strip() for s in args)&lt;br /&gt;
&lt;br /&gt;
# Ergebnis wird an Rhasspy übergeben&lt;br /&gt;
print(num)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nach einem Neustart von Rhasspy kann dieser Converter dann verwendet werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem.SetNumeric]&lt;br /&gt;
stelle die heizung auf (0..30 [komma:. 0..99]){Value!customFloat}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Rhasspy speaks actual state of device after switching it===&lt;br /&gt;
JensS wrote a short script to let Rhasspy speak the actual state of a FHEM-device after switching it with a voice-command.&lt;br /&gt;
Add the following to your 99_myUtils.pm&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub ResponseOnOff($){&lt;br /&gt;
  my ($dev) = @_;&lt;br /&gt;
  my $room;&lt;br /&gt;
  my $state = lc(ReadingsVal($dev,&amp;quot;state&amp;quot;,&amp;quot;in unknown state&amp;quot;));&lt;br /&gt;
  my $name = (split(/,/,AttrVal($dev,&amp;quot;rhasspyName&amp;quot;,&amp;quot;error&amp;quot;)))[0];&lt;br /&gt;
  if (AttrVal($dev,&amp;quot;rhasspyRoom&amp;quot;,&amp;quot;&amp;quot;)){$room = &amp;quot; in &amp;quot;.(split(/,/,AttrVal($dev,&amp;quot;rhasspyRoom&amp;quot;,&amp;quot;&amp;quot;)))[0]};&lt;br /&gt;
  $state=~s/.*on/turned on/;&lt;br /&gt;
  $state=~s/.*off/turned off/;&lt;br /&gt;
  return &amp;quot;Ok - &amp;quot;.$name.$room.&amp;quot; is now &amp;quot;.$state&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
and add a response to the SetOnOff-Mapping of a device&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
SetOnOff:cmdOn=on,cmdOff=off,response={ResponseOnOff($DEVICE)}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [https://github.com/rhasspy/rhasspy Rhasspy auf Github]&lt;br /&gt;
* [https://rhasspy.readthedocs.io/en/latest/ offizielle Rhasspy Doku-Seite]&lt;br /&gt;
* [https://community.rhasspy.org/ Offizielles Rhasspy Forum]&lt;br /&gt;
* [https://github.com/fhem/fhem-rhasspy fhem-rhasspy Modul auf GitHub]&lt;br /&gt;
* [https://github.com/Romkabouter/ESP32-Rhasspy-Satellite ESP32-basierte Hardware als Satelliten]&lt;br /&gt;
* [https://github.com/razzo04/rhasspy-mobile-app App für Android-Satelliten]&lt;br /&gt;
* [https://www.youtube.com/watch?v=sWVl0ZoXZEo Video zu sentences.ini]&lt;br /&gt;
[[Kategorie:Sprachsteuerung]]&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=RHASSPY&amp;diff=37424</id>
		<title>RHASSPY</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=RHASSPY&amp;diff=37424"/>
		<updated>2022-05-17T15:47:27Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: /* Custom Converter für reelle Zahlen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
Diese Seite beschreibt die Konfiguration und Verwendung des Moduls 10_RHASSPY.pm. &lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=Anbindung von FHEM an den Rhasspy Sprachassistenten&lt;br /&gt;
|ModType=contrib&lt;br /&gt;
|ModCmdRef=RHASSPY&lt;br /&gt;
|ModForumArea=Frontends/Sprachsteuerung&lt;br /&gt;
|ModFTopic=119447&lt;br /&gt;
|ModTechName=10_RHASSPY.pm&lt;br /&gt;
|ModOwner=Beta-User ({{Link2FU|9229|Forum}}/[[Benutzer Diskussion:Beta-User|Wiki]]), drhirn ({{Link2FU|15727|Forum}}/[[Benutzer Diskussion:Drhirn|Wiki]])&lt;br /&gt;
}}&lt;br /&gt;
[[File:Rhasspy_fhem.png|thumb|right|Schematische Darstellung von Rhasspy und FHEM/RHASSPY]]&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
[https://github.com/rhasspy/rhasspy Rhasspy] ist eine Open Source Server-Lösung für Spracherkennung und Sprachsteuerung, welche auf einem RaspBerry Pi oder einem anderen Debian-basierten Serversystem lauffähig ist. Es handelt sich dabei um eine Sammlung von Programmen (=Skripten in der Python-Sprechweise), die unter einer einheitlichen und sehr  flexiblen Benutzungsoberfläche zusammengefasst sind. Die Besonderheit an Rhasspy ist, dass es nach der Installation komplett offline betrieben werden kann. Es werden also keine Daten an einen Server im Internet geschickt, und für den Betrieb nur für FHEM werden nur moderate Hardwareanforderungen gestellt - ein aktueller Raspberry Pi ab Modell 3B+ sollte in der Regel genügen.&lt;br /&gt;
&lt;br /&gt;
Die Anbindung weiterer Räume ist über sogenannte &amp;quot;Satelliten&amp;quot; möglich. Dies kann z.B. ein Pi Zero mit Mikro und Lautsprecher sein, ein ESP32 mit entsprechender Hardware oder ein Mobiltelefon mit Android und der entsprechenden App.&lt;br /&gt;
&lt;br /&gt;
Rhasspy besteht aus vielen unterschiedlichen Modulen (Hot-Word Erkennung, Text-to-Speech, Speech-to-Text, Intent Erkennung, etc.). Alle diese Module kommunizieren miteinander über das [[MQTT|MQTT]]-Protokoll.&lt;br /&gt;
&lt;br /&gt;
Das Modul [[RHASSPY]] prüft Teile des MQTT-Traffics, konvertiert diese JSON-Nachrichten in FHEM-Befehle und sendet Nachrichten zurück an Rhasspy um z.B. Antworten über Text-to-Speech auszugeben.&lt;br /&gt;
&lt;br /&gt;
RHASSPY verwendet das Modul 00_MQTT2_CLIENT.pm um Nachrichten zu empfangen und zu senden. Daher ist es notwendig, eine Instanz dieses Moduls als FHEM-Device zu erstellen, bevor RHASSPY verwendet werden kann.&lt;br /&gt;
&lt;br /&gt;
Hervorgegangen ist RHASSPY aus dem Snips-Modul, nachdem Snips an Sonos verkauft und anschließend eingestellt wurde. Danke also an Thyraz, der die grundlegenden Arbeiten erledigt hat!&lt;br /&gt;
&lt;br /&gt;
=== Konventionen ===&lt;br /&gt;
{{Hinweis| In diesem Artikel und der CommandRef werden folgende Schreibweisen verwendet:&lt;br /&gt;
* &#039;&#039;&#039;[[RHASSPY]]&#039;&#039;&#039; bezieht sich auf das FHEM-Modul&lt;br /&gt;
* &#039;&#039;&#039;rhasspy&#039;&#039;&#039; bezieht sich auf das das FHEM-Device&lt;br /&gt;
* &#039;&#039;&#039;Rhasspy&#039;&#039;&#039; bezeichnet die (zentrale) Serverinstallation}}&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|Dialoge werden in RHASSPY verwaltet wie [https://rhasspy.readthedocs.io/en/latest/reference/#dialogue-manager hier] beschrieben. Dialoge werden also nicht funktionieren, sobald für das Dialogue-Management etwas anderes als &#039;&#039;RHASSPY&#039;&#039; eingestellt ist}}&lt;br /&gt;
&lt;br /&gt;
=== Erste Schritte ===&lt;br /&gt;
Die Installation und Erstinbetriebnahme von Rhasspy wird in einer Schnellstart-Anleitung erklärt: [[RHASSPY/Schnellstart]] Diese Anleitung sollte auch befolgt werden, wenn man sich sehr gut mit FHEM auskennt. Wer dies erfolgreich absolviert hat, kann gleich zu Abschnitt [[#Set-Befehle_.28SET.29|Set-Befehle (SET)]] weiterspringen, und/oder die [[RHASSPY/Vertiefung|Vertiefung]] durcharbeiten.&lt;br /&gt;
&lt;br /&gt;
=== Details zur Verwaltung des RHASSPY Moduls ===&lt;br /&gt;
Das Modul ist derzeit nicht in der &amp;quot;offiziellen&amp;quot; FHEM Distribution enthalten und muss daher manuell installiert werden. Dafür gibt es zwei Möglichkeiten.&lt;br /&gt;
&lt;br /&gt;
*Im Subversion Repository, kurz SVN von FHEM ist die jeweils aktuelle &amp;quot;stable&amp;quot; Version des Moduls im &#039;&#039;contrib&#039;&#039;-Zweig zu finden. Diese kann mit folgendem Befehl, der im FHEM Befehls-Eingabefeld einzugeben ist, heruntergeladen werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;{ Svn_GetFile(&#039;contrib/RHASSPY/10_RHASSPY.pm&#039;, &#039;FHEM/10_RHASSPY.pm&#039;) }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Genauere Informationen zu dieser Vorgangsweise finden sich unter [[Update#Einzelne_Dateien_aus_dem_SVN_holen]]. Nach Installation des Moduls muss FHEM neu gestartet werden.&lt;br /&gt;
*FHEM Update und GitHub&lt;br /&gt;
Im GitHub-Repository des Moduls gibt es zwei Branches &#039;&#039;main&#039;&#039; und &#039;&#039;dev&#039;&#039;. In &#039;&#039;main&#039;&#039; ist die stabile Version des Moduls, in &#039;&#039;dev&#039;&#039; die jeweils aktuelle Entwicklungsversion. Aus Gründen der Stabilität ist natürlich die aus &#039;&#039;main&#039;&#039; zu bevorzugen.&lt;br /&gt;
&lt;br /&gt;
Um das Modul zu installieren bzw. zu aktualisieren, kann der &#039;&#039;update&#039;&#039;-Mechanismus von FHEM genutzt werden. Dazu muss das Repository in der Liste der vom update-Befehl verarbeiteten Repositorien aufgenommen werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;update add https://raw.githubusercontent.com/fhem/fhem-rhasspy/main/controls_fhem-rhasspy.txt&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Anschließend kann mit folgendem Befehl das Modul installiert oder aktualisiert werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;update all https://raw.githubusercontent.com/fhem/fhem-rhasspy/main/controls_fhem-rhasspy.txt&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wählt man diesen Weg, wird das Modul auch automatisch aktualisiert, wenn ein Update von FHEM durchgeführt wird. Möchte man die Entwicklungsversion verwenden, muss in den beiden Befehlen &#039;&#039;main&#039;&#039; durch &#039;&#039;dev&#039;&#039; ersetzt werden.&lt;br /&gt;
&lt;br /&gt;
Weitere Informationen zu dieser Vorgangsweise in der stehen in der [https://fhem.de/commandref.html#update CommandRef] oder im [[Update|FHEM-Wiki]].&lt;br /&gt;
&lt;br /&gt;
Nach Installation des Moduls muss FHEM neu gestartet werden.&lt;br /&gt;
&lt;br /&gt;
== Einrichtung MQTT2_CLIENT ==&lt;br /&gt;
Rhasspy kommuniziert hauptsächlich über das [[MQTT]]-Protokoll. Und zwar sowohl Rhasspy-intern, wie auch mit FHEM. Da dies auch für die übertragene Sprache und Audio-Dateien gilt und es daher zu sehr viel MQTT-Verkehr kommt, sollte der Rhasspy-interne MQTT-Server verwendet werden. Daher ist die Einrichtung eines [[MQTT2_CLIENT]]-Devices notwendig, um die für FHEM relevanten Daten zu beziehen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zuerst muss ein MQTT2_CLIENT Device erstellt werden, welches sich mit dem MQTT-Server (Mosquitto) von Rhasspy verbindet:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;define &amp;lt;deviceName&amp;gt; MQTT2_CLIENT &amp;lt;ip-oder-hostname-des-mqtt-servers&amp;gt;:&amp;lt;port&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anschließend wird die &#039;&#039;clientOrder&#039;&#039; gesetzt, um die richtige Benachrichtigungsreihenfolge einzustellen. Wird das MQTT2_CLIENT Device nur für RHASSPY verwendet, reicht hier die Angabe &amp;lt;code&amp;gt;RHASSPY&amp;lt;/code&amp;gt;. Ansonsten müssen noch alle anderen Devices (z.B. &amp;lt;code&amp;gt;MQTT_GENERIC_BRIDGE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;MQTT2_DEVICE&amp;lt;/code&amp;gt;) angegeben werden.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;attr &amp;lt;deviceName&amp;gt; clientOrder RHASSPY [device2] [device3]&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Um die Topics einzuschränken, die das Device abonniert, müssen diese angegeben werden. Wird der MQTT-Server nur für RHASSPY verwendet, reicht die Angabe &amp;lt;code&amp;gt;setByTheProgram&amp;lt;/code&amp;gt;. Ansonsten müssen alle für RHASSPY notwendigen Topics eingefügt werden.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;attr &amp;lt;deviceName&amp;gt; subscriptions setByTheProgram&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
bzw.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;attr &amp;lt;deviceName&amp;gt; subscriptions hermes/intent/+ hermes/dialogueManager/sessionStarted hermes/dialogueManager/sessionEnded hermes/nlu/intentNotRecognized hermes/hotword/+/detected&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Beispiele&lt;br /&gt;
* Rhasspy-interner MQTT-Server wird mit seinem Standard-Port verwendet. Rhasspy läuft auf der selben Maschine wie FHEM. MQTT2_CLIENT wird nur für RHASSPY verwendet.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod rhasspyMQTT2 MQTT2_CLIENT localhost:12183&lt;br /&gt;
attr rhasspyMQTT2 clientOrder RHASSPY&lt;br /&gt;
attr rhasspyMQTT2 subscriptions setByTheProgram&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*Rhasspy läuft auf einem eigenen Server und verwendet einen externen MQTT Server mit eigener Port-Einstellung. MQTT2_CLIENT wird für RHASSPY, aber auch MQTT_GENERIC_BRIDGE und MQTT2_DEVICE verwendet.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod rhasspyMQTT2 MQTT2_CLIENT 192.168.1.122:1884&lt;br /&gt;
attr rhasspyMQTT2 clientOrder RHASSPY MQTT_GENERIC_BRIDGE MQTT2_DEVICE&lt;br /&gt;
attr rhasspyMQTT2 subscriptions hermes/intent/+ hermes/dialogueManager/sessionStarted hermes/dialogueManager/sessionEnded hermes/nlu/intentNotRecognized hermes/hotword/+/detected [zusätzliche Subscriptions für andere MQTT-Module]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Definition von RHASSPY (DEF)==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;define &amp;lt;name&amp;gt; RHASSPY &amp;lt;baseUrl&amp;gt; &amp;lt;devspec&amp;gt; &amp;lt;defaultRoom&amp;gt; &amp;lt;language&amp;gt; &amp;lt;fhemId&amp;gt; &amp;lt;prefix&amp;gt; &amp;lt;useGenericAttrs&amp;gt; &amp;lt;handleHotword&amp;gt; &amp;lt;encoding&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
{{Randnotiz|RNTyp=Info|RNText=RHASSPY verwendet sehr oft &amp;lt;parseParams&amp;gt;. Nicht nur im Define, sondern z.B. auch, um Attribut-Werte auszuwerten. Es sollten also alle Parameter im Define in der Form key=value angegeben werden.).}}{{Randnotiz|RNTyp=Info|RNText=RHASSPY führt jede Menge Daten aus unterschiedlichen Quellen zusammen um seine Funktion erfüllen zu können. Die endgültige Daten-Struktur, die RHASSPY verwendet, kann mittels des [[List|list]]-Kommandos angezeigt werden. Es wird empfohlen, sich diese Daten-Struktur auf jeden Fall anzusehen. Vor allem dann, wenn etwas nicht wie gewünscht funktioniert.}}&lt;br /&gt;
Alle Parameter sind &#039;&#039;&#039;optional&#039;&#039;&#039;. Die meisten werden im Normalfall gar nicht benötigt (z.B. &amp;lt;code&amp;gt;fhemId&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;prefix&amp;lt;/code&amp;gt;). Sollten sie aber verwendet und später geändert werden, kann es zu unvorhergesehenem Verhalten kommen. Speziell beim Einstieg in das Thema RHASSPY sollten nicht mehr, als die ersten drei verwendet werden. Ausgenommen eventuell noch &amp;lt;code&amp;gt;language&amp;lt;/code&amp;gt;, möchte man eine andere Sprache als Englisch oder Deutsch verwenden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;def-baseurl&amp;quot;&amp;gt;baseUrl&amp;lt;/code&amp;gt;&lt;br /&gt;
:Die URL zum Rhasspy-Webservice. Sollten eine Base und mehrere Satelliten verwendet werden, die URL zur Base. Bitte sicherstellen, dass die Adresse richtig ist (IP und Port)! Default ist &amp;lt;code&amp;gt;baseUrl=http://127.0.0.1:12101&amp;lt;/code&amp;gt;.&lt;br /&gt;
;&amp;lt;code id=&amp;quot;def-devspec&amp;quot;&amp;gt;devspec&amp;lt;/code&amp;gt;&lt;br /&gt;
:devspec der Geräte, die mit Rhasspy gesteuert werden sollen. Wenn der &#039;&#039;genericDeviceType&#039;&#039;-Support aktiviert ist, ist der Default &amp;lt;code&amp;gt;devspec=genericDeviceType=.+&amp;lt;/code&amp;gt;, sonst wird &amp;lt;code&amp;gt;devspec=room=Rhasspy&amp;lt;/code&amp;gt; verwendet. Ohne ein passendes Match in der devspec wird kein Gerät mit dem Modul interagieren, egal, ob sonst irgendwelche RHASSPY-spezifischen Attribute beim Gerät gesetzt sind. Genauere Informationen, wie z.B. eine Liste von Geräten oder Kombinationen aus Geräten und Räumen (z.B. &amp;lt;code&amp;gt;devspec=room=livingroom,room=bathroom,bedroomlamp&amp;lt;/code&amp;gt;) verwendet werden können, finden sich in der [https://commandref.fhem.de/commandref.html#devspec CommandRef].&lt;br /&gt;
;&amp;lt;code id=&amp;quot;def-defaultroom&amp;quot;&amp;gt;defaultRoom&amp;lt;/code&amp;gt;&lt;br /&gt;
:Der Name des Standard-Raumes, der verwendet wird, wenn im Sprachkommando kein Raum enthalten ist und auch kein passender für das Device gefunden werden kann. Default ist &amp;lt;code&amp;gt;defaultRoom=default&amp;lt;/code&amp;gt;.&lt;br /&gt;
;&amp;lt;code id=&amp;quot;def-language&amp;quot;&amp;gt;language&amp;lt;/code&amp;gt;&lt;br /&gt;
:Sprache, in der mit Rhasspy gesprochen wird. Der Standard-Wert hängt vom &#039;&#039;global&#039;&#039;-Device ab. Dieser ist standardmäßig &amp;lt;code&amp;gt;language=en&amp;lt;/code&amp;gt;.&lt;br /&gt;
;&amp;lt;code id=&amp;quot;def-fhemid&amp;quot;&amp;gt;fhemId&amp;lt;/code&amp;gt;&lt;br /&gt;
:Wird verwendet um auf MQTT-Seite zwischen mehreren Installationen des RHASSPY-Moduls zu unterscheiden. Ist auch ein Teil des Topic-Trees, auf den die jeweilige RHASSPY-Instanz hört. Default ist &amp;lt;code&amp;gt;fhemId=fhem&amp;lt;/code&amp;gt;.&lt;br /&gt;
;&amp;lt;code id=&amp;quot;def-prefix&amp;quot;&amp;gt;prefix&amp;lt;/code&amp;gt;&lt;br /&gt;
:Wird verwendet um auf FHEM-Seite zwischen mehreren Installationen des RHASSPY-Moduls zu unterscheiden. Praktisch, wenn man mehrere Instanzen von RHASSPY auf einer FHEM Installation laufen hat und z.B. verschiedene Bezeichner für Gruppen und Räume haben möchte (z.B. unterschiedliche Sprachen). Default ist &amp;lt;code&amp;gt;prefix=rhasspy&amp;lt;/code&amp;gt;.&lt;br /&gt;
;&amp;lt;code id=&amp;quot;def-usegenericattrs&amp;quot;&amp;gt;&#039;&#039;&#039;useGenericAttrs&#039;&#039;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
:Üblicherweise verwendet RHASSPY - wie auch einige andere FHEM Module für Sprachassistenten - das Attribut &#039;&#039;genericDeviceType&#039;&#039; um Schaltmöglichkeiten von Geräten automatisch zu erkennen. Dieser Parameter fügt das Attribut &#039;&#039;genericDeviceType&#039;&#039; zur globalen Attributliste hinzu. Der Wert 0 verhindert dieses hinzufügen. Default ist &amp;lt;code&amp;gt;useGenericAttrs=1&amp;lt;/code&amp;gt;.&lt;br /&gt;
;&amp;lt;code id=&amp;quot;def-encoding&amp;quot;&amp;gt;encoding&amp;lt;/code&amp;gt;&lt;br /&gt;
:Sollte es Probleme mit Umlauten geben, kann das Character-Encoding geändert werden. Default ist &amp;lt;code&amp;gt;encoding=utf8&amp;lt;/code&amp;gt;.&lt;br /&gt;
;&amp;lt;code id=&amp;quot;handlehotword&amp;quot;&amp;gt;handleHotword&amp;lt;/code&amp;gt;&lt;br /&gt;
:Triggert das Reading &#039;&#039;hotword&#039;&#039;, wenn ein Hotword erkannt wurde (und erstellt das Reading, falls noch nicht vorhanden). Weitere Informationen dazu stehen beim Attribut [[#attr-rhasspyhotwords|&#039;&#039;rhasspyHotwords&#039;&#039;]]. Default ist &amp;lt;code&amp;gt;handleHotword=0&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|Nach dem Definieren eines RHASSPY-Modules sollte das IODev manuell gesetzt werden um ein automatische IO-Zuweisung zu verhindern. Z.B. &amp;lt;code&amp;gt;attr &amp;lt;deviceName&amp;gt; IODev &amp;lt;m2client&amp;gt;&amp;lt;/code&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
;Beispiele:&lt;br /&gt;
Läuft Rhasspy auf der selben Maschine wie FHEM, die Sprache ist im &#039;&#039;global&#039;&#039;-Device bereits richtig eingestellt und der Standardraum entspricht der siteID, die in Rhasspy vergeben wurde:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;define Rhasspy RHASSPY&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Läuft Rhasspy auf einem anderen System wie FHEM, der Standard-Raum enspricht nicht dem, was Rhasspy liefert, die Sprache soll auch anders sein und es sollen sowohl Geräte mit vorhandenem &#039;&#039;genericDeviceType&#039;&#039; Attribut, als auch die Geräte &#039;&#039;device_a1&#039;&#039; und &#039;&#039;device_xy&#039;&#039; gesteuert werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;define Rhasspy RHASSPY baseUrl=http://192.168.1.210:12101 defaultRoom=&amp;quot;Büro Lisa&amp;quot; language=de devspec=genericDeviceType=.+,device_a1,device_xy handleHotword=1&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Set-Befehle (SET)==&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;set-customslot&amp;quot;&amp;gt;customSlot&amp;lt;/code&amp;gt;&lt;br /&gt;
:Erstellt einen neue - oder überschreibt einen alten - Slot in Rhasspy&lt;br /&gt;
:&amp;lt;code&amp;gt;slotname&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;slotdata&amp;lt;/code&amp;gt; sind verpflichtend&lt;br /&gt;
:&amp;lt;code&amp;gt;overwrite&amp;lt;/code&amp;gt; ist optional. Default ist &amp;lt;code&amp;gt;overwrite=true&amp;lt;/code&amp;gt;. Das Setzen eines anderes Wertes verhindert das Überschreiben einen bereits bestehenden Slot mit gleichem Namen.&lt;br /&gt;
:&amp;lt;code&amp;gt;training&amp;lt;/code&amp;gt; ist optional. Default ist &amp;lt;code&amp;gt;training=true&amp;lt;/code&amp;gt;. Das Setzen eines anderen Wertes verhindert ein Training von Rhasspy nach dem Speichern des Slots.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Beispiele:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; customSlot mySlot a,b,c overwrite training&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; customSlot slotname=mySlot slotdata=a,b,c overwrite=false&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;set-fetchsiteids&amp;quot;&amp;gt;fetchSiteIds&amp;lt;/code&amp;gt;&lt;br /&gt;
:Liest alle in Rhasspy vorhandenen siteIDs aus und speichert sie im Reading &#039;&#039;siteIds&#039;&#039;. Wird z.B. verwendet, um festzustellen, auf welchem Satelliten der User über das Ende eines Timers benachrichtigt werden soll.&lt;br /&gt;
:Muss immer ausgeführt werden, wenn eine neue siteId in Rhasspy hinzugefügt wird (neuer Satellit z.B.).&lt;br /&gt;
:&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; fetchSiteIds&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;set-play&amp;quot;&amp;gt;play&amp;lt;/code&amp;gt;&lt;br /&gt;
:Sendet eine WAV Datei an Rhasspy.&lt;br /&gt;
:&amp;lt;code&amp;gt;siteId&amp;lt;/code&amp;gt; und &amp;lt;path&amp;gt; sind verpflichtend!&lt;br /&gt;
:Optional kann die Anzahl der Wiederholungen (Default: 1) und die Dauer der Pause zwischen den jeweiligen Wiederholungen (Default: 15) angeben werden.&lt;br /&gt;
:&#039;&#039;Beispiele:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; play siteId=&amp;quot;default&amp;quot; path=&amp;quot;/opt/fhem/test.wav&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; play siteId=&amp;quot;default&amp;quot; path=&amp;quot;./test.wav&amp;quot; repeats=3 wait=20&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;set-speak&amp;quot;&amp;gt;speak&amp;lt;/code&amp;gt;&lt;br /&gt;
:Sendet einen Text an das TTS-Sytem, welches ihn dann als Sprache ausgibt.&lt;br /&gt;
:Beide Argumente &amp;lt;code&amp;gt;siteId&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;text&amp;lt;/code&amp;gt; sind verpflichtend!&lt;br /&gt;
:&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; speak siteId=&amp;quot;wohnzimmer&amp;quot; text=&amp;quot;This is a test&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;set-textcommand&amp;quot;&amp;gt;textCommand&amp;lt;/code&amp;gt;&lt;br /&gt;
:Sendet ein Text-Kommando an Rhasspy.&lt;br /&gt;
:&#039;&#039;&#039;Example:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; textCommand schalte das licht ein&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;set-trainrhasspy&amp;quot;&amp;gt;trainRhasspy&amp;lt;/code&amp;gt;&lt;br /&gt;
:Startet das Training von Rhasspy.&lt;br /&gt;
:&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; trainRhasspy&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;set-update&amp;quot;&amp;gt;update&amp;lt;/code&amp;gt;&lt;br /&gt;
:;&amp;lt;code id=&amp;quot;set-update-devicemap&amp;quot;&amp;gt;devicemap&amp;lt;/code&amp;gt;&lt;br /&gt;
::Wenn an der Konfiguration von RHASSPY oder an den von ihm gesteuerten Geräten etwas geändert wurde, muss dieser Befehl ausgeführt werden, um die Datenstruktur von RHASSPY zu aktualisieren, Rhasspy von den Änderungen zu informieren (Slots z.B.), ein Training zu starten, etc.&lt;br /&gt;
::&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update devicemap&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:;&amp;lt;code id=&amp;quot;set-update-devicemaponly&amp;quot;&amp;gt;devicemap_only&amp;lt;/code&amp;gt;&lt;br /&gt;
::Aktualisiert die Datenstruktur von RHASSPY. Es werden weder Slots in Rhasspy geändert, noch das Training gestartet.&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update devicemap_only&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:;&amp;lt;code id=&amp;quot;set-update-slots&amp;quot;&amp;gt;slots&amp;lt;/code&amp;gt;&lt;br /&gt;
::Aktualisiert (bzw. erstellt) alle Slots in Rhasspy mit den aktuellen Geräten, Räumen, usw.&lt;br /&gt;
::Erstellte/Aktualisierte Slots sind z.B.:&lt;br /&gt;
::*de.fhem.AllKeywords&lt;br /&gt;
::*de.fhem.Device&lt;br /&gt;
::*de.fhem.Device-&#039;&#039;genericDeviceType&#039;&#039;&lt;br /&gt;
::*de.fhem.Device-&#039;&#039;Intent&#039;&#039;&lt;br /&gt;
::*de.fhem.Group&lt;br /&gt;
::*de.fhem.Room&lt;br /&gt;
::*de.fhem.MediaChannels&lt;br /&gt;
::*de.fhem.Color&lt;br /&gt;
::*de.fhem.NumericType&lt;br /&gt;
::(Hinweis: Die ersten beiden Teile &#039;&#039;de&#039;&#039; und &#039;&#039;fhem&#039;&#039; hängen von der DEF des RHASSPY-Devices ab)&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update slots&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:;&amp;lt;code id=&amp;quot;set-update-slotsnotraining&amp;quot;&amp;gt;slots_no_training&amp;lt;/code&amp;gt;&lt;br /&gt;
::Wie &amp;lt;code&amp;gt;slots&amp;lt;/code&amp;gt;, aber ohne Training nach dem Update.&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update slots_no_training&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:;&amp;lt;code id=&amp;quot;set-update-language&amp;quot;&amp;gt;language&amp;lt;/code&amp;gt;&lt;br /&gt;
::Liest das das Sprach-File (&#039;&#039;languageFile&#039;&#039;) neu ein.&lt;br /&gt;
::Muss immer ausgeführt werden, wenn in diesem File oder dem Attribut &#039;&#039;languageFile&#039;&#039; etwas geändert wurde!&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update language&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:;&amp;lt;code id=&amp;quot;set-udpate-intentfilter&amp;quot;&amp;gt;intent_filter&amp;lt;/code&amp;gt;&lt;br /&gt;
::Setzt die Intent Filter, die vom Rhasspy Dialogue Manger verwendet werden zurück. Details dazu bei [[#attr-rhasspytweaks-intentfilter|intentFilter]] im &#039;&#039;rhasspyTweaks&#039;&#039;-Attribut.&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update intent_filter&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:;&amp;lt;code id=&amp;quot;set-update-all&amp;quot;&amp;gt;all&amp;lt;/code&amp;gt;&lt;br /&gt;
::Aktualisiert die Devicemap und das languageFile&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update all&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;set-volume&amp;quot;&amp;gt;volume&amp;lt;/code&amp;gt;&lt;br /&gt;
::Stellt die Lautstärke der gewünschten siteId auf einen Wert zwischen 0 and 1 (float).&lt;br /&gt;
::Beide Argumente &amp;lt;code&amp;gt;siteId&amp;lt;/code&amp;gt; &amp;lt;code&amp;gt;volume&amp;lt;/code&amp;gt; sind verpflichtend.&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; siteId=&amp;quot;default&amp;quot; volume=&amp;quot;0.5&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|Bitte nicht vergessen, dass nach jeder Änderung an RHASSPY oder an einem von RHASSPY gesteuerten Gerät ein &amp;lt;code&amp;gt;update devicemap&amp;lt;/code&amp;gt; ausgeführt werden muss!}}&lt;br /&gt;
&lt;br /&gt;
==Attribute (ATTR)==&lt;br /&gt;
Um RHASSPY zum Laufen zu bringen, müssen unterschiedliche Attribute gesetzt werden. Dabei gibt es&lt;br /&gt;
*Attribute, die im RHASSPY-Device selbst gesetzt werden müssen und&lt;br /&gt;
*Attribute, die in den Devices gesetzt werden müssen, die von RHASSPY kontrolliert werden sollen.&lt;br /&gt;
&lt;br /&gt;
Letztere werden im Abschnitt [[#FHEM-Devices für die Verwendung mit Rhasspy konfigurieren|FHEM-Devices für die Verwendung mit Rhasspy konfigurieren]] behandelt.&lt;br /&gt;
&lt;br /&gt;
In diesem Abschnitt werden die Attribute behandelt, die auf das RHASSPY-Device selbst wirken.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;attr-iodev&amp;quot;&amp;gt;IODev&amp;lt;/code&amp;gt;&lt;br /&gt;
:Das MQTT2_CLIENT Device, welches die MQTT-Nachrichten für RHASSPY liefert.&lt;br /&gt;
:&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;attr &amp;lt;rhasspyDevice&amp;gt; IODev rhasspyMQTT2&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;attr-forcenext&amp;quot;&amp;gt;forceNext&amp;lt;/code&amp;gt;&lt;br /&gt;
:Wenn dieses Attribut auf 1 gesetzt ist, leitet RHASSPY eingehende MQTT-Nachrichten an andere MQTT2-IO-Client Module wie MQTT2_DEVICE weiter, auch wenn das Topic zu einem von RHASSPY abonnierten passt.&lt;br /&gt;
:Standardmäßig werden diese Nachrichten nicht weitergeleitet um eine bessere Kompatibilität mit dem &#039;&#039;autocreate&#039;&#039;-Feature des MQTT2_DEVICE sicher zu stellen.&lt;br /&gt;
:Siehe dazu das {{Link2CmdRef|Anker=MQTT2_CLIENT-attr-clientOrder|Lang=en|Label=clientOrder}}-Attribut in der CommandRef zum MQTT2_CLIENT Device.&lt;br /&gt;
:Das Setzen dieses Attributs in einer RHASSPY-Instanz kann auch andere eventuell vorhandene RHASSPY-Instanzen beinflussen.&lt;br /&gt;
:Default ist &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;attr &amp;lt;rhasspyDevice&amp;gt; forceNext 1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;attr-languagefile&amp;quot;&amp;gt;languageFile&amp;lt;/code&amp;gt;&lt;br /&gt;
:Pfad zur Sprach-Datei&lt;br /&gt;
:Ist dieses Argument nicht gesetzt, wird ein Standard-Set an englischen Sätzen für die Sprachantworten verwendet.&lt;br /&gt;
:Die Datei selbst muss ein gültiges JSON-File sein, dass sich nach der Struktur aus den englischen Standardwerten richtet.&lt;br /&gt;
:Eine deutsche Beispiel-Datei ist in [https://svn.fhem.de/trac/browser/trunk/fhem/contrib/RHASSPY/rhasspy-de.cfg SVN] und [https://github.com/fhem/fhem-rhasspy/blob/dev/FHEM/rhasspy-de.cfg GitHub] vorhanden. Man kann aber einfach ein Dump der englischen Struktur machen (replace RHASSPY by your device&#039;s name: &amp;lt;code&amp;gt;{toJSON($defs{RHASSPY}-&amp;gt;{helper}{lng})}&amp;lt;/code&amp;gt;, das Ergebnis dann bearbeiten und es als eigenes languageFile verwenden.&lt;br /&gt;
:Im Standard-Set sind auch einige Variablen enthalten. Auch die können im eigenen File verwendet werden.&lt;br /&gt;
:languageFile erlaubt auch eine Kombination aus vorhandenen und eigenen Sätzen. Dazu können die eigenen Sätzen einfach im Sub-Tree &#039;&#039;user&#039;&#039; abgelegt werden.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Beispiel:&#039;&#039;&#039; (vorausgesetzt, die Sprach-Datei ist im selben Verzeichnis wie fhem.pl):&lt;br /&gt;
:&amp;lt;code&amp;gt;attr &amp;lt;rhasspyDevice&amp;gt; languageFile ./rhasspy-de.cfg&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;attr-response&amp;quot;&amp;gt;response&amp;lt;/code&amp;gt;&lt;br /&gt;
:&#039;&#039;&#039;Hinweis:&#039;&#039;&#039;: Die Verwendung dieses Attributs ist nicht mehr empfohlen. Bessere Alternative ist die Sprach-Datei.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Mit diesem Attribut können eigene Standardantworten definiert werden.&lt;br /&gt;
Mögliche Schlüsselwörter sind &amp;lt;code&amp;gt;DefaultError&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;NoActiveMediaDevice&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;DefaultConfirmation&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;DefaultError=&lt;br /&gt;
DefaultConfirmation=Klaro, mach ich&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;attr-rhasspyhotwords&amp;quot;&amp;gt;rhasspyHotwords&amp;lt;/code&amp;gt;&lt;br /&gt;
:Kann verwendet werden, um benutzerdefinierte Aktionen auszuführen, sobald ein bestimmtes Hotword erkannt wurde. Dazu sind keine speziellen Konfigurationsschritte in anderen FHEM Devices notwendig.&lt;br /&gt;
:Wenn mittels Attribut oder DEF aktiviert, wird ein Reading &#039;&#039;hotword&#039;&#039; erstellt und mit dem erkannten Hotword und der siteId befüllt um ein Event-Handling zu ermöglichen.&lt;br /&gt;
:&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Da bei den hotword messages für alle Teilnehmer dieselbe Topic-Structur verwendet wird, kann RHASSPY nicht unterscheiden, ob eine solche für diese Instanz relevant ist. Falls entsprechende Unterscheidungen gemacht werden sollen, muss dies vom User entsprechend konfiguriert werden, z.B. indem die subscriptions (am MQTT2_CLIENT) eingeschränkt werden oder indem nur jeweils andere hotword-Einträge für jede RHASSPY-Instanz genutzt werden.&lt;br /&gt;
:Ein Hotword pro Zeile, Syntax entweder einfach oder erweitert&lt;br /&gt;
 &lt;br /&gt;
:&#039;&#039;&#039;Beispiele:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;bumblebee_linux = set amplifier2 mute on&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;porcupine_linux = livingroom=&amp;quot;set amplifier mute on&amp;quot; default={Log3($DEVICE,3,&amp;quot;device $DEVICE - room $ROOM - value $VALUE&amp;quot;)}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Im ersten Beispiel wird der Befehl immer ausgeführt, wenn das Hotword &#039;&#039;bumblebee_linux&#039;&#039; erkannt wurde.&lt;br /&gt;
:Im zweiten nur, wenn das Hotword &#039;&#039;porcupine_linux&#039;&#039; in der siteId &#039;&#039;livingroom&#039;&#039; erkannt wurde.&lt;br /&gt;
:$DEVICE wird ausgewertet als der Name des RHASSPY Devices, $ROOM als siteId und $VALUE als das verwendete Hotword.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;attr-rhasspyintents&amp;quot;&amp;gt;rhasspyIntents&amp;lt;/code&amp;gt;&lt;br /&gt;
:Definiert einen benutzerdefinierten Intent.&lt;br /&gt;
:Ein Intent pro Zeile.&lt;br /&gt;
:&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;attr &amp;lt;rhasspyDevice&amp;gt; rhasspyIntents SetCustomIntentsTest=SetCustomIntentsTest(siteId,Type)&amp;lt;/code&amp;gt;&lt;br /&gt;
:in Kombination mit folgendem myUtils-Code&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub SetCustomIntentsTest {&lt;br /&gt;
my $room = shift;&lt;br /&gt;
my $type = shift;&lt;br /&gt;
Log3(&#039;rhasspy&#039;,3 , &amp;quot;RHASSPY: Room $room, Type $type&amp;quot;);&lt;br /&gt;
return &amp;quot;RHASSPY: Room $room, Type $type&amp;quot;;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
:schreibt einen Log-Eintrag nach jedem Aufruf dieses Intents.&lt;br /&gt;
:Die folgenden Argumente können dabei übergeben werden:&lt;br /&gt;
:*NAME =&amp;gt; Name des RHASSPY-Devices&lt;br /&gt;
:*DATA =&amp;gt; komplette JSON-$data (wie intern geparsed), in JSON kodiert&lt;br /&gt;
:*siteId, Device etc. =&amp;gt; jedes Element, das in JSON-$data existiert&lt;br /&gt;
:Wird von der Funktion ein einfacher Text zurück geliefert, wird dieser als &#039;&#039;response&#039;&#039; angesehen. Wenn der Rückgabewert nicht definiert ist, wird die Standard-&#039;&#039;response&#039;&#039; verwendet.&lt;br /&gt;
:Es kann aber auch ein HASH oder ARRAY übergeben werden.&lt;br /&gt;
:Im Falle eines ARRAYs wird das erste Element als &#039;&#039;response&#039;&#039; interpretiert und kann ein reiner Text sein, womit der Dialog beendet wird. Ist das erste Element ein HASH wird die Dialog-Session fortgesetzt. Eine offene Dialog-Session wird per Default nach 20 Sekunden beendet. Diese Zeitspanne kann aber auch geändert werden, in dem im ARRAY als zweiter Wert eine Zahl übergeben wird. Das zweite Element kann aber auch eine komma-getrennte Liste an Geräten sein, die geändert (geschalten) wurden. Das dient dazu, damit die Geräte auch Events liefern, was ansonsten nicht der Fall wäre. Siehe dazu den &amp;quot;d&amp;quot;-Parameter beim Attribut [[#attr-rhasspyshortcuts|rhasspyShortcuts]].&lt;br /&gt;
:Wird eine HASH-Datenstruktur (ggf. in $response innerhalb einer ARRAY-Struktur), um einen laufenden Dialog fortzusetzen, muss sichergestellt werden, dass alle erforderlichen Datenelemente enthalten sind, insbesondere &#039;&#039;intentFilter&#039;&#039;, falls die für den weiteren Dialog relevanten Intents eingeschränkt (oder erweitert) werden sollen. Dabei sollte möglichst der Intent &#039;&#039;CancelAction&#039;&#039; aktiv gehalten werden, damit der User die Option hat, den Dialog jederzeit aktiv zu beenden.&lt;br /&gt;
:Siehe dazu auch den Abschnitt [[#Eigene Intents erstellen]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;attr-rhasspyshortcuts&amp;quot;&amp;gt;rhasspyShortcuts&amp;lt;/code&amp;gt;&lt;br /&gt;
:Hiermit können benutzerdefinierte Sätze erstellt werden ohne die sentences.ini in Rhasspy bearbeiten zu müssen.&lt;br /&gt;
:Diese Shortcuts werden zu Rhasspy hochgeladen, sobald das &amp;lt;code&amp;gt;updateSlots&amp;lt;/code&amp;gt; [[#set-update|Set]]-Kommando ausgeführt wird.&lt;br /&gt;
:Ein Shortcut pro Zeile, Syntax ist entweder einfach oder erweitert.&lt;br /&gt;
:&#039;&#039;&#039;Beispiele:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;mute on=set amplifier2 mute on&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;lamp off={fhem(&amp;quot;set lampe1 off&amp;quot;)}&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;i=&amp;quot;du bist cool&amp;quot; f=&amp;quot;set $NAME speak siteId=&#039;livingroom&#039; text=&#039;danke dir! du bist noch viel cooler!&#039;&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;i=&amp;quot;schalte den ton aus&amp;quot; p={fhem (&amp;quot;set $NAME mute off&amp;quot;)} n=amplifier2 c=&amp;quot;soll ich den ton wirklich ausschalten?&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;i=&amp;quot;ich hab hunger&amp;quot; f=&amp;quot;set Herd on&amp;quot; d=&amp;quot;Herd&amp;quot; c=&amp;quot;möchtest du schweinsbraten?&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
:Erklärung zu den Abkürzungen:&lt;br /&gt;
:*&amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt; =&amp;gt; intent&lt;br /&gt;
::Zeilen, die mit &amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt; beginnen, werden als erweiterte Syntax interpretiert. Soll die erweiterte Syntax verwendet werden, ist das &amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt; also Pflicht!&lt;br /&gt;
:*&amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; =&amp;gt; FHEM Befehl&lt;br /&gt;
::Syntax wie von der FHEM Kommandozeile gewohnt&lt;br /&gt;
:*&amp;lt;code&amp;gt;p&amp;lt;/code&amp;gt; =&amp;gt; Perl Befehl&lt;br /&gt;
::Syntax wie von der FHEM Kommandozeile gewohnt, eingerahmt in geschwungenen Klammern (&amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt;). &amp;lt;code&amp;gt;p&amp;lt;/code&amp;gt; hat Vorrang vor &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt;&lt;br /&gt;
:*&amp;lt;code&amp;gt;d&amp;lt;/code&amp;gt; =&amp;gt; Device Name(en, Komma getrennt)&lt;br /&gt;
::Device Name(n), die an fhem.pl als upgedated übergeben werden sollen. Das wird benötigt um weitere Aktionen in FHEM und das Longpolling zu triggern.&lt;br /&gt;
::Hinweis: Wenn Perl-Funktionen aufgerufen werden, wird der Rückgabewert dieser Funktion verwendet, sofern kein explizites Device angegeben ist.&lt;br /&gt;
:*&amp;lt;code&amp;gt;r&amp;lt;/code&amp;gt; =&amp;gt; Response&lt;br /&gt;
::Sprachanwort, die ausgegeben wird. Ist &amp;lt;code&amp;gt;r&amp;lt;/code&amp;gt; nicht gesetzt, wird der Rückgabewert der aufgerufenen Funktion verwendet.&lt;br /&gt;
::In den Antwortsätze werden &#039;&#039;set magic&#039;&#039;-ähnliche Ersetzungen verarbeitet. Es ist also auch eine Zeile wie &amp;lt;code&amp;gt;i=&amp;quot;what&#039;s the time for sunrise&amp;quot; r=&amp;quot;at [Astro:SunRise] o&#039;clock&amp;quot;&amp;lt;/code&amp;gt; gültig.&lt;br /&gt;
::Mit den folgenden Abkürzungen kann auch nach einer Bestätigung für den Befehl gefragt werden:&lt;br /&gt;
::*&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt; =&amp;gt; Entweder Zahl oder Text. Wenn Zahl, wird sie als Timeout für den Abbruch des Dialogs behandelt. Wenn Text wird dieser als Sprachausgabe zur Bestätigung verwendet.&lt;br /&gt;
::*&amp;lt;code&amp;gt;ct&amp;lt;/code&amp;gt; =&amp;gt; Numerischer Wert für das Timeout des Dialogs in Sekunden. Default ist &amp;lt;code&amp;gt;15&amp;lt;/code&amp;gt;.&lt;br /&gt;
::Siehe [[#attr-rhasspytweaks-confirmintents|hier]] für weitere Informationen zu Bestätigungen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;attr-rhasspytweaks&amp;quot;&amp;gt;rhasspyTweaks&amp;lt;/code&amp;gt;&lt;br /&gt;
Mit diesen Einstellungen können benutzerdefinierte Optimierungen an RHASSPY vorgenommen werden.&lt;br /&gt;
&lt;br /&gt;
:*&amp;lt;code id=&amp;quot;attr-rhasspytweaks-timerlimits&amp;quot;&amp;gt;timerLimits&amp;lt;/code&amp;gt;&lt;br /&gt;
::Wird verwendet um den Timer anzuweisen mit z.B. &amp;quot;gestellt auf 30 Minuten&amp;quot; oder &amp;quot;gestellt auf 10:30&amp;quot; zu antworten&lt;br /&gt;
::&amp;lt;code&amp;gt;timerLimits=90,300,3000,2*HOURSECONDS,50&amp;lt;/code&amp;gt;&lt;br /&gt;
::Hierbei müssen fünf Werte gesetzt werden, die den Zeitgrenzen für Stufen in der Antwortstruktur &#039;&#039;timerSet&#039;&#039; entsprechen.&lt;br /&gt;
::Obiges Beispiel also würde dazu führen, unter einer eingestellten Zeit von 90 Sekunden mit der Sekundenangabe geantwortet wird. In Minuten und Sekunden solange der Timer kürzer als 300 Sekunden ist. Usw. Der letzte Wert ist das Limit in Sekunden, wenn der Timer im &amp;quot;Uhrzeit&amp;quot;-Format gestellt ist.&lt;br /&gt;
&lt;br /&gt;
:*&amp;lt;code id=&amp;quot;attr-rhasspytweaks-timersounds&amp;quot;&amp;gt;timerSounds&amp;lt;/code&amp;gt;&lt;br /&gt;
::Standardmäßig antwortet der Timer mit einer Sprachnachricht, wenn er abgelaufen ist. Soll lieber eine WAV-Datei verwendet werden, kann das hier eingestellt werden.&lt;br /&gt;
::&amp;lt;code&amp;gt;timerSounds= default=./yourfile1.wav eier=3:20:./yourfile2.wav kartoffeln=5:./yourfile3.wav&amp;lt;/code&amp;gt;&lt;br /&gt;
::Die Keys in dieser Code-Zeile sind Beispiele und deren Name - bis auf &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; frei wählbar. Der Name muss aber zu den &#039;&#039;Label&#039;&#039;-Tags für die Timer in den Rhasspy-Sentences passen.&lt;br /&gt;
::&amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; ist optional. Wenn gesetzt, wird dieses WAV-File für alle benannten Timer verwendet, für die kein Keyword in der Konfiguration ist.&lt;br /&gt;
::Die beiden Nummern sind optional. Die erste legt fest, wie oft die WAV-Datei wiederholt werden soll (Default: 5). Die zweite definiert die Pause in Sekunden zwischen den Wiederholungen (Default: 15). Ist nur eine Zahl gesetzt, wird diese als gewünschte Anzahl an Wiederholungen interpretiert.&lt;br /&gt;
&lt;br /&gt;
:*&amp;lt;code id=&amp;quot;attr-rhasspytweaks-updateslots&amp;quot;&amp;gt;updateSlots&amp;lt;/code&amp;gt;&lt;br /&gt;
::Ändert diverse Aspekte des Erstellens und Updatens von Slots&lt;br /&gt;
::*&amp;lt;code&amp;gt;noEmptySlots=1&amp;lt;/code&amp;gt;&lt;br /&gt;
:::Per Default generiert RHASSPY einen zusätzlichen Slot für jeden &#039;&#039;genericDeviceType&#039;&#039;, der erkannt wird. Unabhängig davon, ob er bei einem Gerät gesetzt ist. Das kann zu leeren Slots führen.&lt;br /&gt;
:::Ist der Wert &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;, werden keine leeren Slots erstellt.&lt;br /&gt;
::*&amp;lt;code&amp;gt;overwrite_all=false&amp;lt;/code&amp;gt;&lt;br /&gt;
:::RHASSPY überschreibt alle vorhandenen Slots wenn ein &amp;lt;code&amp;gt;updateSlots&amp;lt;/code&amp;gt; ausgeführt wird. Ist das nicht gewünscht, muss dieser Wert auf &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; gesetzt werden.&lt;br /&gt;
::*&amp;lt;code&amp;gt;timeouts&amp;lt;/code&amp;gt;&lt;br /&gt;
:::Die Keywörter &amp;lt;code&amp;gt;confirm&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; können verwendet werden, um das Standard-Timeouts (15s/20s) für Dialoge zu ändern.&lt;br /&gt;
:::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:::&amp;lt;code&amp;gt;timeouts: confirm=25 default=30&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:*&amp;lt;code id=&amp;quot;attr-rhasspytweaks-confirmintents&amp;quot;&amp;gt;confirmIntents&amp;lt;/code&amp;gt;&lt;br /&gt;
::Hiermit kann eingestellt werden, dass für bestimmte Intents immer ein Bestätigung erfragt wird. Unterstützt werden derzeit alle &amp;quot;set-&amp;quot;-Intents.&lt;br /&gt;
::Dazu werden &amp;lt;code&amp;gt;Intent&amp;lt;/code&amp;gt;=&amp;lt;code&amp;gt;regex&amp;lt;/code&amp;gt;-Paare verwendet.&lt;br /&gt;
:::&amp;lt;code&amp;gt;Intent&amp;lt;/code&amp;gt; ist der Name des gewünschten Intents&lt;br /&gt;
:::&amp;lt;code&amp;gt;regex&amp;lt;/code&amp;gt; ist eine Regex, die eine bestimmte Gruppe (für Gruppen-Intents) oder einen bestimmten Device-Namen beschreiben muss.&lt;br /&gt;
:::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:::&amp;lt;code&amp;gt;confirmIntents=SetOnOffGroup=light|blinds SetOnOff=blind.*&amp;lt;/code&amp;gt;&lt;br /&gt;
::Befehle werden nur nach einer positiven Bestätigung ausgeführt. Das bedeutet, es muss unbedingt ein &amp;lt;code&amp;gt;Mode:OK&amp;lt;/code&amp;gt;-Wert vom &#039;&#039;ConfirmAction&#039;&#039;-Intent gesendet werden. Jede andere Wert für &amp;lt;code&amp;gt;Mode&amp;lt;/code&amp;gt; wird als Abbruch gewertet. Es kann aber auch der eigene Intent &#039;&#039;CancelAction&#039;&#039; für den Abbruch verwendet werden.&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:ConfirmAction]&lt;br /&gt;
( yes, please do it | go on | that&#039;s ok | yes, please ){Mode:OK}&lt;br /&gt;
( don&#039;t do it after all ){Mode}&lt;br /&gt;
&lt;br /&gt;
[de.fhem:CancelAction]&lt;br /&gt;
( let it be | oh no | cancel | cancellation ){Mode:Cancel}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:*&amp;lt;code id=&amp;quot;attr-rhasspytweaks-confirmintentresponses&amp;quot;&amp;gt;confirmIntentResponses&amp;lt;/code&amp;gt;&lt;br /&gt;
::Üblicherweise ist die Bestätigungs-Frage ein &amp;quot;Echo&amp;quot; des ursprünglich gesprochenen Befehls. Dies kann für jeden Intent geändert werden,&lt;br /&gt;
::Dies kann für jeden Intent individuell angepaßt werden, wobei die Variablen $target, ($rawInput) und $Value verwendet werden können.&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;confirmIntentResponses=SetOnOffGroup=&amp;quot;wirklich die Gruppe $target $Value schalten&amp;quot; SetOnOff=&amp;quot;bestätige dass $target $Value geschaltet werden soll&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
::&amp;lt;code&amp;gt;$Value&amp;lt;/code&amp;gt; wird dabei mit den defaults aus dem &#039;&#039;words&#039;&#039; key in der languageFile übersetz (falls vorhanden). Weitere Optionen für Ersetzungen von &amp;lt;code&amp;gt;$Value&amp;lt;/code&amp;gt; sind für einzelne Devices über den [[#attr-rhasspyspecials-confirmvaluemap|confirmValueMap]] key im Attribut &#039;&#039;rhasspySpecials&#039;&#039; verfügbar.&lt;br /&gt;
&lt;br /&gt;
:*&amp;lt;code id=&amp;quot;attr-rhasspytweaks-intentfilter&amp;quot;&amp;gt;intentFilter&amp;lt;/code&amp;gt;&lt;br /&gt;
::Rhasspy aktiviert bei jedem Neustart alle ihm bekannten Intents. Da manche der von FHEM genutzten Intents nur in bestimmten Situationen (v.a. innerhalb offener Dialoge) benötigt werden, deaktiviert RHASSPY diese (derzeit: ConfirmAction, CancelAction, ChoiceRoom und ChoiceDevice beim Start, sowie jedes Mal, wenn erkannt wird, dass das Standardfiltering nicht wie erwartet funktioniert (was v.a. bei einem zwischenzeitlichen Rhasspy-Neustart der Fall sein kann). Über diesen Tweak können weitere Intents mit in diese automatisierte (De-) Aktivierung mit einbezogen werden. Entweder ist dabei einfach der Name (ohne die Zusätze aus &#039;&#039;language&#039;&#039; und &#039;&#039;fhemId&#039;&#039; anzugeben, oder eine explizite Anweisung zum ein- und Ausschalten (in der Form &amp;lt;code&amp;gt;intentname=true&amp;lt;/code&amp;gt;). Die 4 vorgenannten Standard-Intents können nicht über diesen Weg aktiviert werden. Details zur intern genutzten Rhasspy-Funktionalität sind in der [https://rhasspy.readthedocs.io/en/latest/reference/#dialogue-manager Rhasspy-Dokumentation] zu finden.&lt;br /&gt;
&lt;br /&gt;
:*&amp;lt;code id=&amp;quot;attr-rhasspytweaks-ignorekeywords&amp;quot;&amp;gt;ignoreKeywords&amp;lt;/code&amp;gt;&lt;br /&gt;
::Da in manchen der von RHASSPY automatisch ausgewerteten Attribute häufig auch eher technisch motivierte Angaben zu finden sind, kann über diesen Schlüssel verhindert werden, dass derartige Angaben bei der slot-Erstellung übergangen werden. Dies betrifft z.B. häufig anzutreffende &#039;&#039;room&#039;&#039;-Werte wie &#039;&#039;MQTT&#039;&#039;, &#039;&#039;alexa&#039;&#039;, &#039;&#039;homebridge&#039;&#039; oder &#039;&#039;googleassistant&#039;&#039;. Die hier angegebenen key-value-Paare werden als Negativ-Filter für die angegebenen Werte verwendet (derzeit nur für &#039;&#039;rooms&#039;&#039; und &#039;&#039;group&#039;&#039;). &#039;&#039;value&#039;&#039; wird dabei als (case-insensitive) regex behandelt, verglichen wird auf exakten match (es müssen also ggf. vorne bzw. hinten &#039;&#039;.*&#039;&#039; angefügt werden).&lt;br /&gt;
::Dieses &#039;&#039;&#039;Beispiel&#039;&#039;&#039; filtert daher die o.g. Räume aus und dazu noch die strukturierten Unterräume unterhalb &#039;&#039;Steuerung&#039;&#039;:&lt;br /&gt;
::&amp;lt;code&amp;gt;ignoreKeywords=rooms=mqtt.*|alexa|homebridge|googleassistant|steuerung-.&amp;lt;/code&amp;gt;&lt;br /&gt;
:* &amp;lt;code id=&amp;quot;attr-rhasspytweaks-ignorekeywords&amp;quot;&amp;gt;gdt2groups&amp;lt;/code&amp;gt;  Dieser Eintrag ermöglicht es, alle Geräte eines generichDeviceType innerhalb der automatischen Erfassung automatisch einer oder mehreren Gruppen zuzuordnen. Die Vorgaben in diesem Eintrag werden nicht übernommen, wenn am jeweiligen Einzelgerät  das Attribut &#039;&#039;rhasspyGroup&#039;&#039; gesetzt ist.  Hier eine deutschsprachige Vorbelegung als &#039;&#039;&#039;Beispiel&#039;&#039;&#039;: &amp;lt;code&amp;gt;gdt2groups= blind=rollläden,rollladen thermostat=heizkörper light=lichter,leuchten&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Readings / Events==&lt;br /&gt;
;&amp;lt;code&amp;gt;IODev&amp;lt;/code&amp;gt;&lt;br /&gt;
:Das eingestellte IO-Device&lt;br /&gt;
;&amp;lt;code&amp;gt;intents&amp;lt;/code&amp;gt;&lt;br /&gt;
:Eine Liste der in Rhasspy vorhandenen Intents&lt;br /&gt;
;&amp;lt;code&amp;gt;lastIntentPayload&amp;lt;/code&amp;gt;&lt;br /&gt;
:Inhalt des letzten Intents der von FHEM empfangen wurde&lt;br /&gt;
;&amp;lt;code&amp;gt;lastIntentTopic&amp;lt;/code&amp;gt;&lt;br /&gt;
:Das MQTT-Topic des letzten Intents&lt;br /&gt;
;&amp;lt;code&amp;gt;listening_roomname&amp;lt;/code&amp;gt;&lt;br /&gt;
:Ein Reading für jeden Raum bzw. jede siteId&lt;br /&gt;
:Wechselt auf 1 sobald ein Hotword erkannt wurde und zurück auf 0, sobald die Dialog-Session beendet ist.&lt;br /&gt;
:Kann z.B. verwendet werden, um den Ton eines TVs auszuschalten, während Rhasspy auf ein Kommando hört.&lt;br /&gt;
;&amp;lt;code&amp;gt;mute_roomname&amp;lt;/code&amp;gt;&lt;br /&gt;
:Zeigt an, ob ein Raum / eine siteId vom Intent &#039;&#039;SetMute&#039;&#039; stumm geschalten wurde und somit keine Befehle ausführt.&lt;br /&gt;
:Jeweils ein Reading für jede siteId.&lt;br /&gt;
:Default ist 0.&lt;br /&gt;
;&amp;lt;code&amp;gt;responseType&amp;lt;/code&amp;gt;&lt;br /&gt;
:Der Typ der letzten Antwort (text/voice).&lt;br /&gt;
:voiceResponse and textResponse&lt;br /&gt;
:Antwort auf das letzte Sprach-/Text-Kommando.&lt;br /&gt;
;&amp;lt;code&amp;gt;siteIds&amp;lt;/code&amp;gt;&lt;br /&gt;
:Listet alle siteIds auf.&lt;br /&gt;
:Kann mit [[#set-fetchsiteids|fetchSiteIds]] aktualisiert werden.&lt;br /&gt;
;&amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;&lt;br /&gt;
:Zeigt an ob RHASSPY mit Rhasspy verbunden ist&lt;br /&gt;
;&amp;lt;code&amp;gt;training&amp;lt;/code&amp;gt;&lt;br /&gt;
:Letzte zurückgelieferte Antwort auf einen [[#set-trainrhasspy|trainRhasspy]]-Befehl.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
;&amp;lt;code&amp;gt;updateSentences&amp;lt;/code&amp;gt;&lt;br /&gt;
:Letzte zurückgelieferte Antwort nach einem [[#set-update-slots|updateSlots]]-Befehl.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
;&amp;lt;code&amp;gt;updateSlots&amp;lt;/code&amp;gt;&lt;br /&gt;
:Letzte zurückgelieferte Antwort nach einem [[#set-update-slots|updateSlots]]-Befehl.&lt;br /&gt;
;&amp;lt;code&amp;gt;hotword&amp;lt;/code&amp;gt;&lt;br /&gt;
:Wenn aktiviert, beinhaltet dieses Reading das letzte verwendete Hotword und von welcher siteId es aufgerufen wurde.&lt;br /&gt;
;&amp;lt;code&amp;gt;voiceResponse&amp;lt;/code&amp;gt;&lt;br /&gt;
:Letze Sprach-Antwort auf einen Sprach-Befehl&lt;br /&gt;
&lt;br /&gt;
=== Benutzerdefinierte Readings ===&lt;br /&gt;
&lt;br /&gt;
There are some readings you may find useful to tweak some aspects of RHASSPY&#039;s logics:&lt;br /&gt;
*&amp;lt;code&amp;gt;siteId2room_&amp;lt;/code&amp;gt; Falls keine explizite Raum-Information in den an RHASSPY weitergegebenen Daten enthalten ist, ermittelt das Modul den Raum in der Regel aus dem Namen der &#039;&#039;siteId&#039;&#039;. So werden z.B. alle raumlosen Anweisungen von einem Satelliten names &#039;&#039;schlafzimmer&#039;&#039;, im Raum &#039;&#039;schlafzimmer&#039;&#039; ausgeführt werden (wenn möglich). Die Gruppenfunktion von Rhasspy wird unterstützt, so wird z.B. &#039;&#039;wohnzimmer.vorne&#039;&#039; ebenfalls automatisch dem Raum &#039;&#039;wohnzimmer&#039;&#039; zugeordnet. Über passende Angaben in &#039;&#039;siteId2room-Readings&#039;&#039; kann dieses Verhalten modifiziert werden:  &amp;lt;code&amp;gt;setreading siteId2room_mobile_phone1 wohnzimmer&amp;lt;/code&amp;gt; wird RHASSPY veranlassen, den Satelliten  &#039;&#039;mobile_phone1&#039;&#039; dem Raum &#039;&#039;wohnzimmer&#039;&#039; zuzuweisen. Hierzu ist in &#039;&#039;contrib&#039;&#039; auch eine Hilfsfunktion zu finden, mit der mobilen Satelliten per Sprachbefehl einem neuen Raum zugewiesen werden können.&lt;br /&gt;
*&amp;lt;code&amp;gt;siteId2doubleSpeak_&amp;lt;/code&amp;gt; RHASSPY antwortet immer über den Satelliten, von dem die jeweilige Sprachanweisung kam. Manchmal kann es erwünscht sein, zusätzliche Sprachrückmeldungen an einen weiteren Satelliten zu geben - z.B. weil der betreffende Lautsprecher (zeitweise) ausgeschaltet ist. Ist ein entsprechendes Reading gesetzt, erfolgen (zusätzliche!) Sprachausgaben an den dort als Readingwert angegebenen zweiten Satelliten; das Namensschema der Readings entspricht dem für site2room.&lt;br /&gt;
&lt;br /&gt;
== FHEM-Devices für die Verwendung mit Rhasspy konfigurieren ==&lt;br /&gt;
Um ein Gerät mit Rhasspy steuern zu können, muss Rhasspy einige Details über das Gerät kennen. Diese werden bekannt gemacht, in dem bei den Geräten Attribute gesetzt werden, die anschließend vom RHASSPY-Modul ausgewertet und an Rhasspy gesendet werden.&lt;br /&gt;
&lt;br /&gt;
Der einfachste - und empfohlene - Weg, dies zu erreichen, ist durch Setzen des Attributs &#039;&#039;&#039;&#039;&#039;genericDeviceType&#039;&#039;&#039;&#039;&#039;. Das Modul erkennt dann die möglichen Schalt - und Abfragemöglichkeiten des Gerätes automatisch.&lt;br /&gt;
&lt;br /&gt;
Sollte &#039;&#039;genericDeviceType&#039;&#039; (gDT) nicht ausreichen, gibt es noch weitere Attribute, die stattdessen oder ergänzend dazu verwendet werden können (z.b. rhasspyName, rhasspyRoom, ...). Die Namen dieser Attribute beginnen alle mit dem &#039;&#039;prefix&#039;&#039;, das in der DEF des RHASSPY-Moduls gesetzt wurde. Diese Dokumentation verwendet das Prefix &amp;lt;code&amp;gt;rhasspy&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Sind sowohl &#039;&#039;genericDeviceType&#039;&#039; als auch Spezial-Attribute vorhanden, werden die von gDT gesammelten Möglichkeiten durch die der Spezial-Attribute überschrieben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Wichtig:&#039;&#039;&#039;&lt;br /&gt;
*Nach JEDER Änderung an den folgenden Attributen muss ein &amp;lt;code&amp;gt;[[#set-update-devicemap|update devicemap]]&amp;lt;/code&amp;gt; ausgeführt werden. Sonst erfahren weder RHASSPY, noch Rhasspy von der Änderung.&lt;br /&gt;
*RHASSPY sammelt alle Informationen aus diesen Attributen in seinem eigenen Device-HASH. Dieser wird durch das &amp;lt;code&amp;gt;update devicemap&amp;lt;/code&amp;gt;-Kommando aktualisiert und kann mittels &amp;lt;code&amp;gt;[[List|list]]&amp;lt;/code&amp;gt;-Befehl angezeigt werden. Für diesen HASH werden alle Namen und sonstige &amp;quot;Labels&amp;quot; in Kleinbuchstaben umgewandelt. Sollte man Slots händisch befüllen, muss also darauf geachtet werden, dass Rhasspy ebenfalls Werte in Kleinbuchstaben liefert.&lt;br /&gt;
*Die Mindestvoraussetzungen für ein FHEM Device um mit RHASSPY zusammenzuarbeiten sind:&lt;br /&gt;
**Das Device muss von der devspec im Define des RHASSPY-Devices abgedeckt werden&lt;br /&gt;
**Es muss mindestens eines der folgenden Attribute (im Normalfall &#039;&#039;genericDeviceType&#039;&#039;) im Device gesetzt sein.&lt;br /&gt;
*Die Mapping-Logik (für Namen, mögliche Schaltzustände, etc.) ist wie folgt:&lt;br /&gt;
**Sind RHASSPY-spezifische Attribute gesetzt, werden ausschließlich diese verwendet. Natürlich nur für den Zweck des gesetzten Attributs. Ein gesetzter &#039;&#039;rhasspyName&#039;&#039; z.B. wird also nicht verhindern, dass die durch &#039;&#039;genericDeviceType&#039;&#039; ermittelten möglichen Schaltzustände ebenfalls gespeichert werden.&lt;br /&gt;
**Je spezifischer ein Attribut ist, desto eher wird überschreiben, was weniger speziell ist. Ein gesetzter &#039;&#039;alias&#039;&#039; wird also verhindern, dass der (technische) Device-Name verwendet wird. Aber ein gesetztes Attribut &#039;&#039;alexaName&#039;&#039;, &#039;&#039;gassistantName&#039;&#039; oder &#039;&#039;siriName&#039;&#039; wird (auch) den &#039;&#039;alias&#039;&#039; überschreiben. Sind zwei &amp;quot;gleichwertige&amp;quot; Attribute vorhanden (z.B. &#039;&#039;siriName&#039;&#039; und &#039;&#039;alexaName&#039;&#039;), werden beide verwendet.&lt;br /&gt;
*Attribut-Werte werden typischerweise &amp;quot;Zeile für Zeile&amp;quot; gelesen. Wobei gilt, eine Zeile pro Wert/Befehl/Funktionalität. Zeilenumbrüche &#039;&#039;&#039;müssen&#039;&#039;&#039; also an den richtigen Stellen gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;code&amp;gt;genericDeviceType&amp;lt;/code&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
Ist dieses Attribut gesetzt &#039;&#039;&#039;und&#039;&#039;&#039; entspricht der Devicename der devspec, wird RHASSPY das Mapping (und andere eventuell schon vorhandene Werte) automatisch ermitteln.&lt;br /&gt;
&lt;br /&gt;
Derzeit werden folgende Werte für das Attribut genericDeviceType unterstützt:&lt;br /&gt;
*switch&lt;br /&gt;
*light&lt;br /&gt;
*thermostat&lt;br /&gt;
*thermometer&lt;br /&gt;
*HumiditySensor&lt;br /&gt;
*blind/blinds/shutter&lt;br /&gt;
*media&lt;br /&gt;
*motion/contact/ContactSensor/lock/presence&lt;br /&gt;
&lt;br /&gt;
Wird &#039;&#039;genericDeviceType&#039;&#039; verwendet, werden unter anderem folgende Informationen gesammelt:&lt;br /&gt;
* der Name (&amp;lt;code&amp;gt;NAME&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;alias&amp;lt;/code&amp;gt;) des Devices&lt;br /&gt;
* der (FHEM-)Raum, in dem sich das Device befindet.&lt;br /&gt;
* die Gruppe, zu der das Device gehört (ggf. unter Beachtung des Schlüssels  &amp;lt;code id=&amp;quot;attr-rhasspytweaks-ignorekeywords&amp;quot;&amp;gt;gdt2groups&amp;lt;/code&amp;gt; aus &#039;&#039;rhasspyTweaks&#039;&#039;)&lt;br /&gt;
* wie Informationen vom Gerät abgefragt werden können&lt;br /&gt;
* wie Werte/Status am Gerät gesetzt werden können&lt;br /&gt;
&lt;br /&gt;
Die Verwendung von &#039;&#039;genericDeviceType&#039;&#039; ist der einfachste Weg, wie man FHEM-Devices dazu bringen kann, mit RHASSPY zusammenzuarbeiten. Manchmal liefert genericDeviceType aber nicht ausreichende oder nicht passende Informationen. In so einem Fall können die folgenden Attribute (zusätzlich) verwendet werden.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;code&amp;gt;rhasspyName&amp;lt;/code&amp;gt;===&lt;br /&gt;
Mit diesem Attribut kann der Name des Geräts eingestellt werden, mit dem es in einem Sprachbefehl angesprochen werden soll. Es können auch mehrere Namen - getrennt durch ein Komma - angegeben werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039; &amp;lt;code&amp;gt;attr &amp;lt;device&amp;gt; rhasspyName Lampe,Stehlampe,Wunderlicht&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es ist durchaus möglich, mehrere FHEM-Geräte mit dem selben Namen zu haben. Sie müssen dann nur in unterschiedlichen Räumen sein.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;code&amp;gt;rhasspyRoom&amp;lt;/code&amp;gt;===&lt;br /&gt;
Dieses Attribut kann verwendet werden, um Rhasspy mitzuteilen, in welchem physischem (oder logischen) Raum sich das Gerät befindet.&lt;br /&gt;
&lt;br /&gt;
Ist es nicht vorhanden, wird &amp;lt;code&amp;gt;alexaRoom&amp;lt;/code&amp;gt; oder das FHEM-Attribut &amp;lt;room&amp;gt; verwendet. Sind auch diese nicht vergeben, gehört das Gerät zum &amp;quot;Standard-Raum&amp;quot;, der im Define des RHASSPY-Devices angegeben wurde.&lt;br /&gt;
&lt;br /&gt;
Das Attribut ist nützlich, wenn man Sprachbefehle ohne explizite Raumangabe verwenden will. Gibt es z.B. ein Gerät mit dem Namen &#039;&#039;Lampe&#039;&#039; und dessen rhasspyRoom-Attribut ist gleich, wie die &#039;&#039;siteId&#039;&#039; von der aus der Sprachbefehl abgesetzt wird, reicht es zu sagen &amp;quot;Lampe ein&amp;quot;. Der Raum muss also nicht extra dazu gesagt werden.&lt;br /&gt;
&lt;br /&gt;
Es ist auch möglich, mehrere Raum-Namen zu vergeben sofern diese durch ein Komma voneinander getrennt werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039; &amp;lt;code&amp;gt;attr &amp;lt;device&amp;gt; rhasspyRoom livingroom&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hinweis: Wenn die &#039;&#039;siteId&#039;&#039; den Konventionen von Rhasspy zur Gruppierung von siteIds folgt (&#039;&#039;roomname.satellite&#039;&#039;), wird nur &amp;lt;code&amp;gt;roomname&amp;lt;/code&amp;gt; als Raum-Name angenommen. Beachte: Die automatisierte Zuweisung zu einem Raum kann durch &#039;&#039;siteId2room_.*&#039;&#039;-Readings modifiziert werden (s.o.). &lt;br /&gt;
===&amp;lt;code&amp;gt;rhasspyGroup&amp;lt;/code&amp;gt;===&lt;br /&gt;
Kommagetrennte Liste an Gruppen, zu denen das Gerät zugehörig ist&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039; &amp;lt;code&amp;gt;attr &amp;lt;device&amp;gt; rhasspyGroup Lampen,Beleuchtung Arbeitsfläche,Küchen Beleuchtung&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;code&amp;gt;rhasspyMapping&amp;lt;/code&amp;gt;===&lt;br /&gt;
Wenn die automatische Erkennung des richtigen Intents für ein Gerät nicht funktioniert oder nicht das gewünschte Ergebnis liefert, kann mit diesem Attribut angegeben werden, mit welchem Intent das Gerät gesteuert werden kann.&lt;br /&gt;
&lt;br /&gt;
Es ist möglich, mehrere verschiedene Intents pro Gerät zu verwenden. Es muss nur einfach eine neue Zeile für ein weiteres Mapping verwendet werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr &amp;lt;device&amp;gt; rhasspyMapping SetOnOff:cmdOn=on,cmdOff=off,response=&amp;quot;Alles klar&amp;quot;&lt;br /&gt;
GetOnOff:currentVal=state,valueOff=off&lt;br /&gt;
GetNumeric:currentVal=pct,type=brightness&lt;br /&gt;
SetNumeric:currentVal=brightness,cmd=brightness,minVal=0,maxVal=255,map=percent,step=1,type=brightness&lt;br /&gt;
Status:response=Die Helligkeit in der Küche ist bei [&amp;lt;device&amp;gt;:pct]&lt;br /&gt;
MediaControls:cmdPlay=play,cmdPause=pause,cmdStop=stop,cmdBack=previous,cmdFwd=next&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Formatierung von Befehlen und Readings innerhalb eines rhasspyMappings====&lt;br /&gt;
Manche Intents können FHEM-Kommandos oder -Readings verwenden, um Werte auszulesen oder zu setzen.&lt;br /&gt;
&lt;br /&gt;
Dabei gibt es drei Möglichkeiten, wie diese geschrieben werden können:&lt;br /&gt;
*Direktes Verwenden von SET-Kommando oder Reading des aktuellen Device:&lt;br /&gt;
:&amp;lt;code&amp;gt;cmd=on or currentReading=temperature&amp;lt;/code&amp;gt;&lt;br /&gt;
*Umleiten eines Kommando auf ein anderes Device oder Verwenden eines Readings aus einem anderen Gerät:&lt;br /&gt;
:&amp;lt;code&amp;gt;cmd=Otherdevice:on or currentReading=Otherdevice:temperature&amp;lt;/code&amp;gt;&lt;br /&gt;
*Perl-Code um einen Befehl auszuführen oder einen Wert zu setzen:&lt;br /&gt;
:Das ermöglicht sehr komplexe Anfragen.&lt;br /&gt;
:Der Code muss in geschwungenen Klammern sein.&lt;br /&gt;
:&amp;lt;code&amp;gt;{currentVal={ReadingsVal($DEVICE,&amp;quot;state&amp;quot;,0)}&amp;lt;/code&amp;gt;&lt;br /&gt;
:oder&lt;br /&gt;
:&amp;lt;code&amp;gt; cmd={fhem(&amp;quot;set $DEVICE dim $VALUE&amp;quot;)}&amp;lt;/code&amp;gt;&lt;br /&gt;
:$DEVICE ist das aktuelle FHEM-device. Der SetNumeric-Intent kann $VALUE für den Wert verwenden, der gesetzt werden soll.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;code&amp;gt;rhasspySpecials&amp;lt;/code&amp;gt;===&lt;br /&gt;
Dieses Attribut wirkt ähnlich wie [[#rhasspyTweaks| rhasspyTweaks]], verändert allerdings nur jeweils das Verhalten des Geräts, bei dem es gesetzt ist. Auch dieses Attribut wird zeilenweise eingelesen, es können ein oder mehrere der folgenden Optionen gesetzt werden:&lt;br /&gt;
&lt;br /&gt;
==== group ====&lt;br /&gt;
::Wird dieser Schlüssel gesetzt, wird das Gerät bei Gruppenaktionen nicht direkt adressiert, sondern die hier angegebene Gruppe. Details hierzu sind in [[RHASSPY/Vertiefung#Timing-Aspekte| Vertiefung - Timing-Aspekte]] zu finden.&lt;br /&gt;
&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;attr lamp1 rhasspySpecials group:async_delay=100 prio=1 group=lights&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== numericValueMap ====&lt;br /&gt;
::Ermöglicht es, statt der allgemeinen Methode zum Umgang mit numerischen Werten einzelnen Werten spezielle Kommandos zuzuweisen. Dies kann z.B. hilfreich sein, um spezielle Positionen für Rollladengeräte anzusteuern.&lt;br /&gt;
::&#039;&#039;&#039;Beispiel&#039;&#039;&#039;:&lt;br /&gt;
::&amp;lt;code&amp;gt;attr blind1 rhasspySpecials numericValueMap:10=&#039;Event Slit&#039; 50=&#039;myPosition&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
::führt dazu, dass ein numerischer Wert von 10 (im {Value}-key) das Kommando &amp;lt;code&amp;gt;set blind1 Event Slit&amp;lt;/code&amp;gt; ausführt.&lt;br /&gt;
&lt;br /&gt;
==== venetianBlind ====&lt;br /&gt;
Siehe [[RHASSPY/Vertiefung#Jalousien|Vertiefung - Jalousien]]&lt;br /&gt;
&lt;br /&gt;
==== colorCommandMap ====&lt;br /&gt;
Sowie **colorTempMap** und **colorForceHue2rgb**&lt;br /&gt;
Siehe [[RHASSPY/Vertiefung#Farben|Vertiefung - Farben]]&lt;br /&gt;
&lt;br /&gt;
==== priority ====&lt;br /&gt;
Ermöglicht es, Rückfragen zu vermeiden, wenn mehrere Geräte für bestimmte Aktionen in Frage kommen. Siehe [[RHASSPY/Vertiefung#Einer_statt_alle|Einer statt alle]]&lt;br /&gt;
&lt;br /&gt;
==== confirm ====&lt;br /&gt;
Ist eine Möglichkeit, Geräte nur nach Rückfrage und Bestätigung zu schalten (ähnlich wie &#039;&#039;confirmIntents&#039;&#039; in &#039;&#039;rhasspyTweaks&#039;&#039;). Es können entweder einfach nur Intent-Namen angegeben werden, oder Paare von **Intent** und zugehöriger **response**:&lt;br /&gt;
 SetOnOff=&amp;quot;Soll $target wirklich $Value geschaltet werden&amp;quot; SetScene&lt;br /&gt;
&lt;br /&gt;
==== confirmValueMap ====&lt;br /&gt;
Kann spezielle Übersetzungen für $Value enthalten, z.B. für Rollladen-Geräte:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;confirm: SetOnOff=&amp;quot;wirklich $Value $target&amp;quot;&lt;br /&gt;
confirmValueMap: on=öffnen off=schließen&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== scenes ====&lt;br /&gt;
Wird bei der automatisierten Erfassung erkannt, dass ein Gerät das Setzen von Szenen unterstützt, werden die erkannten Szenen-Namen an Rhasspy übergeben. Da diese häufig technischer Natur sind, eignen sie sich nicht für eine Spracherkennung. Über diesen Schlüssel können daher sprechbare Namen für jede Szene vergeben werden, und/oder einzelne bzw. alle Szenen von der Erkennung ausgenommen werden. Der Kenner &#039;&#039;none&#039;&#039; löscht die Szene von der Liste der übermittelten Szenen, wird die Kombination &#039;&#039;all=none&#039;&#039; angegeben, wird dieses Gerät insgesamt von der Vorbereitung für den Intent &#039;&#039;SetScene&#039;&#039; ausgeschlossen.&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;attr lamp1 rhasspySpecials scenes:scene2=&amp;quot;Kino zu zweit&amp;quot; scene3=Musik scene1=none scene4=none&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Siehe auch [[RHASSPY/Vertiefung#echte_Szenen|Vertiefung - echte Szenen]]. &lt;br /&gt;
&lt;br /&gt;
=== Veraltete Attribute ===&lt;br /&gt;
In der Regel sollte es ausreichen, die zu steuernden Devices über die oben genannten Attribute zu konfigurieren. Es gibt jedoch noch zwei ältere Methoden. Um diese zu verwenden, muss zuerst jeweils ein entsprechendes User-Attribut im FHEM-Device, das damit gesteuert werden soll, angelegt werden.&lt;br /&gt;
&lt;br /&gt;
====&amp;lt;code&amp;gt;rhasspyChannels&amp;lt;/code&amp;gt;====&lt;br /&gt;
Das Attribut wird vom Intent &#039;&#039;MediaControls&#039;&#039; verwendet. Es informiert den Intent darüber, welche (Medien-)Kanäle vorhanden sind und welcher FHEM-Befehl oder Perl-Code auszuführen ist, wenn auf diesen Kanal geschaltet werden soll.&lt;br /&gt;
&lt;br /&gt;
In diesem Attribut muss eine Zeile pro (Medien-)Kanal verwendet werden.&lt;br /&gt;
&lt;br /&gt;
Um rhasspyChannels zu verwenden, muss zuerst ein neues User-Attribut im FHEM-Device, das damit gesteuert werden soll, angelegt werden. Dafür kann z.B. dieses Beispiel verwendet werden: &amp;lt;code&amp;gt;attr &amp;lt;deviceName&amp;gt; userattr rhasspyChannels:textField-long&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr &amp;lt;device&amp;gt; rhasspyChannels orf eins=channel 201&lt;br /&gt;
orf zwei=channel 202&lt;br /&gt;
orf drei=channel 203&lt;br /&gt;
netflix=launchApp Netflix&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&amp;lt;code&amp;gt;rhasspyColors&amp;lt;/code&amp;gt;====&lt;br /&gt;
Ältere Methode, die verwendet werden kann, um Lichtfarben zu wechseln. Es wird nachdrücklich empfohlen, die neueren Methoden über die (nummerisch zu übergebenden) allgemeinen Farbwerte und/oder ein &#039;&#039;colorCommandMap&#039;&#039; oder &#039;&#039;colorTempMap&#039;&#039; (siehe &#039;&#039;rhasspySpecials&#039;&#039;) zu konfigurieren!&lt;br /&gt;
&lt;br /&gt;
Um das Mapping zu verwenden, muss zuerst ein User-Attribut am zu steuernden Gerät angelegt werden. Z.B. &amp;lt;code&amp;gt;attr &amp;lt;deviceName&amp;gt; userattr rhasspyChannels:textField-long&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Eine Zeile pro Farbe&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr lamp1 rhasspyColors rot=rgb FF0000&lt;br /&gt;
grün=rgb 008000&lt;br /&gt;
blau=rgb 0000FF&lt;br /&gt;
gelb=rgb FFFF00&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Intents ==&lt;br /&gt;
Intents werden verwendet um FHEM zu sagen, was es nach einem erhaltenen Sprach-/Textkommand unternehmen soll. Dieses Modul stellt einige Intents bereit.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Wichtig&lt;br /&gt;
:*Bei Tags (&amp;lt;code&amp;gt;Value&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;, etc.) ist die Schreibweise sehr wichtig! Die sind case-sensitive. Bitte daher genau so schreiben, wie sie in dieser Dokumentation vorkommen.&lt;br /&gt;
:*RHASSPY erstellt bei einem &amp;lt;code&amp;gt;update slots&amp;lt;/code&amp;gt; auch Slots je nach Möglichkeiten der Geräte oder Gruppen. Unterstützt ein Gerät zum Beispiel den Intent &#039;&#039;GetNumeric&#039;&#039;, wird auch ein Slot &amp;lt;code&amp;gt;de.fhem.Device-GetNumeric&amp;lt;/code&amp;gt; erstellt. Ein Gerät, dass ein- und ausgeschalten werden kann, wird im Slot &amp;lt;code&amp;gt;de.fhem.Device-SetOnOff&amp;lt;/code&amp;gt; untergebracht. Ein einzelnes Gerät kann sich auch in mehreren Slots befinden. Um eine möglichst genaue Spracherkennung zu gewährleisten, ist &#039;&#039;&#039;empfohlen&#039;&#039;&#039;, diese &#039;&#039;&#039;spezifischen Slots&#039;&#039;&#039; - statt einfach nur &amp;lt;code&amp;gt;de.fhem.Device&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;de.fhem.Group&amp;lt;/code&amp;gt; - &#039;&#039;&#039;zu verwenden&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetOnOff ===&lt;br /&gt;
Intent um Geräte zwischen zwei Zuständen (ein/aus, auf/zu, start/stop) zu schalten.&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
SetOnOff:cmdOn=on,cmdOff=off&lt;br /&gt;
SetOnOff:cmdOn=on,cmdOff=off,response=&amp;quot;Sir yes Sir&amp;quot;&lt;br /&gt;
SetOnOff:cmdOn=on,cmdOff=off,response=&amp;quot;$DEVICE now [$DEVICE:state]&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Argumente:&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdOn&amp;lt;/code&amp;gt; Befehl um das Gerät einzuschalten. Siehe [[#Formatierung von Befehlen und Readings innerhalb eines rhasspyMappings|Formatierung von Befehlen und Readings innerhalb eines rhasspyMappings]].&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdOff&amp;lt;/code&amp;gt; Befehl um das Gerät auszuschalten. Siehe [[#Formatierung von Befehlen und Readings innerhalb eines rhasspyMappings|Formatierung von Befehlen und Readings innerhalb eines rhasspyMappings]].&lt;br /&gt;
&lt;br /&gt;
Optionale Argumente:&lt;br /&gt;
*&amp;lt;code&amp;gt;response&amp;lt;/code&amp;gt; Eine benutzerdefinierte Antwort auf den Befehl&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
schalten das licht ein&lt;br /&gt;
schließe den rollladen im schlafzimmer&lt;br /&gt;
starte die kaffeemaschine&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetOnOff]&lt;br /&gt;
(schalte|schalt|mache|mach|stelle|stell|starte) [den|die|das] $de.fhem.Device-SetOnOff{Device} [[(im|in dem|auf dem|in der|auf der)] $de.fhem.Room{Room}] (an|ein){Value:on}&lt;br /&gt;
(schalte|schalt|mache|mach|stelle|stell) [den|die|das] $de.fhem.Device-SetOnOff{Device} [[(im|in dem|auf dem|in der|auf der)] $de.fhem.Room{Room}] aus{Value:off}&lt;br /&gt;
(fahre|fahr) [den|die|das] $de.fhem.Device-blind{Device} [[(im|in dem|auf dem|in der|auf der)] $de.fhem.Room{Room}] ((hoch|auf){Value:on}|(zu|runter){Value:off})&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verpflichtende Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Value:on&amp;lt;/code&amp;gt; und/oder &amp;lt;code&amp;gt;Value:off&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetOnOffGroup ===&lt;br /&gt;
Intent um Gruppen von Geräte zwischen zwei Zuständen zu schalten.&lt;br /&gt;
&lt;br /&gt;
Dafür ist ein SetOnOff-Mapping benötigt und alle gewünschten Geräte müssen dasselbe Attribut &amp;lt;code&amp;gt;group&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;rhasspyGroup&amp;lt;/code&amp;gt; haben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
schalte alle lampen in der küche aus&lt;br /&gt;
schließe alle rollläden im schlafzimmer&lt;br /&gt;
schalte alle lampen aus&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetOnOffGroup]&lt;br /&gt;
\[(schalt|mach)] (alle | sämtliche ) $de.fhem.Group-SetOnOff{Group} [[in|im|in der|auf der] [( überall:global | $de.fhem.Room ){Room}] ein{Value:on}&lt;br /&gt;
\[(schalt|mach)] (alle | sämtliche ) $de.fhem.Group-SetOnOff{Group} [[in|im|in der|auf der] [( überall:global | $de.fhem.Room ){Room}] aus{Value:off}&lt;br /&gt;
(öffne{Value:on}|schließe{Value:off}) (alle | sämtliche ) $de.fhem.Group-blind{Group} [[in|im|in der|auf der] [( überall:global{Room:global} | $de.fhem.Room{Room} )] &lt;br /&gt;
(fahr|fahre|mach|mache) [den|die|das] $de.fhem.Group-blind{Group} [[(im|in dem|in der)] ( überall:global{Room:global} | $de.fhem.Room{Room} )] ( auf{Value:on} | hoch{Value:on} | zu{Value:off} | runter{Value:off} )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verpflichtende Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Value:on&amp;lt;/code&amp;gt; und/oder &amp;lt;code&amp;gt;Value:off&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Group&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetTimedOnOff ===&lt;br /&gt;
Intent um Geräte für eine bestimmte Zeitspanne in einen bestimmten Zustand zu versetzten.&lt;br /&gt;
&lt;br /&gt;
Device muss ein SetOnOff-Mapping haben und die {{Link2CmdRef|Anker=setExtensions|Lang=de|Label=SetExtentions}} unterstützen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
schalte das licht für eine minute und dreißig sekunden aus&lt;br /&gt;
schalte die musik im bad bis zwei uhr ein&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetTimedOnOff]&lt;br /&gt;
schalte $de.fhem.Device-SetOnOff{Device} [$de.fhem.Room{Room}] für ([(1..60){Hour!int} (stunde|stunden)] [und] [(1..60){Min!int} (minute|minuten)] [und] [(1..60){Sec!int} (sekunde|sekunden)]) (ein{Value:on}|aus{Value:off})&lt;br /&gt;
schalte $de.fhem.Device-SetOnOff{Device} [$de.fhem.Room{Room}] bis (0..24){Hourabs!int} [(1..60){Min!int}] (ein{Value:on}|aus{Value:off})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verpflichtende Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Value&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Hour&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Min&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Sec&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Hourabs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetTimedOnOffGroup ===&lt;br /&gt;
Intent um eine Gruppe von Geräten für eine bestimmte Zeit zu schalten.&lt;br /&gt;
&lt;br /&gt;
Devices müssen ein SetOnOff-Mapping haben, in einer Gruppe sein und die {{Link2CmdRef|Anker=setExtensions|Lang=de|Label=SetExtentions}} unterstützen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
schalte alle lichter in der küche für fünfzig sekunden ein&lt;br /&gt;
schalte alle licher bis zwei uhr ein&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetTimedOnOffGroup]&lt;br /&gt;
schalte $de.fhem.Group-SetOnOff{Group} [$de.fhem.Room{Room}] für ([(1..60){Hour!int} (stunde|stunden)] [und] [(1..60){Min!int} (minute|minuten)] [und] [(1..60){Sec!int} (sekunde|sekunden)]) (ein{Value:on}|aus{Value:off})&lt;br /&gt;
schalte $de.fhem.Group-SetOnOff{Group} [$de.fhem.Room{Room}] bis (0..24){Hourabs!int} [(1..60){Min!int}] (ein{Value:on}|aus{Value:off})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verpflichtende Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Value&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Group&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Hour&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Min&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Sec&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Hourabs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GetOnOff ===&lt;br /&gt;
Intent um den aktuellen Zustand eines Gerätes zu erfragen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
GetOnOff:currentVal=state,valueOff=closed&lt;br /&gt;
GetOnOff:currentVal=state,valueOn=on&lt;br /&gt;
GetOnOff:currentVal=pct,valueOff=0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Argumente:&lt;br /&gt;
Hinweis: nur &amp;lt;code&amp;gt;valueOn&amp;lt;/code&amp;gt; ODER &amp;lt;code&amp;gt;valueOff&amp;lt;/code&amp;gt; müssen gesetzt werden. Der jeweils andere Wert bekommt den anderen Status.&lt;br /&gt;
*&amp;lt;code&amp;gt;currentVal&amp;lt;/code&amp;gt; Reading aus dem der aktuelle Status hervorgeht&lt;br /&gt;
*&amp;lt;code&amp;gt;valueOff&amp;lt;/code&amp;gt; Wert, der den Zustand &#039;&#039;aus&#039;&#039; beschreibt&lt;br /&gt;
*&amp;lt;code&amp;gt;valueOn&amp;lt;/code&amp;gt; Wert, der den Zustand &#039;&#039;an&#039;&#039; beschreibt&lt;br /&gt;
&lt;br /&gt;
Optionale Argumente:&lt;br /&gt;
*&amp;lt;code&amp;gt;response&amp;lt;/code&amp;gt; Eine benutzerdefinierte Antwort auf den Befehl&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
ist das licht im bad ein&lt;br /&gt;
ist das fenster im wohnzimmer geöffnet&lt;br /&gt;
läuft die waschmaschine&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[en.fhem:GetOnOff]&lt;br /&gt;
ist $de.fhem.Device-GetOnOff{Device} [$de.fhem.Room{Room}] (ein|geöffnet){State:on}&lt;br /&gt;
ist $de.fhem.Device-GetOnOff{Device} [$de.fhem.Room{Room}] (aus|geschlossen){State:off}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zustände &#039;&#039;ein&#039;&#039; und &#039;&#039;aus&#039;&#039; sollten in unterschiedlichen Sentences sein und müssen &amp;lt;code&amp;gt;{State:on}&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;{State:off}&amp;lt;/code&amp;gt; beinhalten.&lt;br /&gt;
&lt;br /&gt;
Verpflichtende Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;State:on&amp;lt;/code&amp;gt; und/oder &amp;lt;code&amp;gt;State:off&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetNumeric ===&lt;br /&gt;
Intent, um Lampen zu dimmen, Rollladengeräte zu positionieren, Lautstärken oder Solltemperaturen zu ändern, usw.. &lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
SetNumeric:currentVal=pct,cmd=dim,minVal=0,maxVal=99,step=25,type=brightness&lt;br /&gt;
SetNumeric:currentVal=volume,cmd=volume,minVal=0,maxVal=99,step=10,type=volume&lt;br /&gt;
SetNumeric:currentVal=brightness,cmd=brightness,minVal=0,maxVal=255,map=percent,step=1,type=brightness&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Argumente:&lt;br /&gt;
*&amp;lt;code&amp;gt;currentVal&amp;lt;/code&amp;gt; Reading, in dem der aktuelle Wert zu finden ist (wird zwingend benötigt).&lt;br /&gt;
*&amp;lt;code&amp;gt;part&amp;lt;/code&amp;gt; Kann genutzt werden, um den Wert aus **currentVal** in mehrere Teile zu zerlegen (getrennt wird am Leerzeichen). Z.B. wenn currentVal 23 C ist, wird **part=0** **23** ergeben. Optionaler Parameter.&lt;br /&gt;
*&amp;lt;code&amp;gt;cmd&amp;lt;/code&amp;gt; Das **Set**-Kommando des Geräts, das in Folge des Sprachkommandos ausgeführt werden soll. (Notwendiger Parameter).&lt;br /&gt;
*&amp;lt;code&amp;gt;minVal&amp;lt;/code&amp;gt; Niedrigster zugelassener Wert, optional.&lt;br /&gt;
*&amp;lt;code&amp;gt;maxVal&amp;lt;/code&amp;gt; Höchster zugelassener Wert, optional.&lt;br /&gt;
*&amp;lt;code&amp;gt;step&amp;lt;/code&amp;gt; Schrittweite für relative Änderungen wie &amp;lt;code&amp;gt;mach lauter&amp;lt;/code&amp;gt;. Optional. Default: 10.&lt;br /&gt;
*&amp;lt;code&amp;gt;map&amp;lt;/code&amp;gt; Derzeit wird ausschließlich die Angabe **percent** ausgewertet. Optionaler Parameter, der bewirkt, dass alle Angaben als Prozentwert (zwischen minVal und maxVal) interpretiert werden und entsprechend gerechnet wird. So wird z.B. eine Leuchte mit **minVal=0** und **maxVal=255** beim Befehl &amp;quot;stelle das Licht auf 50&amp;quot; dies so verstehen, als wäre die Anweisung &amp;quot;stelle das Licht auf 50 Prozent&amp;quot; gewesen. Das Licht wird daher auf 127 gestellt, und nicht auf (absolut) 50.&lt;br /&gt;
*&amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; Zur Unterscheidung, falls mehrere SetNumeric-Intents für das Gerät möglich sind. Empfohlener Parameter.&lt;br /&gt;
&lt;br /&gt;
Gut zu wissen:&lt;br /&gt;
Um Kommandos wie **lauter** oder **leiser** ohne Angabe eines Gerätes ausführen zu können, muss RHASSPY zunächst ermitteln, welches Gerät gerade überhaupt etwas wiedergibt ist. Daher nutzt es die GetOnOff-Mappings, um festzustellen, welches Gerät vom **type=volume** überhaupt angeschaltet ist. Dabei wird wie üblich zunächst im aktuellen rhasspyRoom gesucht, bevor die Suche außerhalb fortgesetzt wird.&lt;br /&gt;
Setzt man also Mappings manuell, ist es ratsam, auch ein **GetOnOff**-Mapping zu setzen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zulässige Typen sind:&lt;br /&gt;
*&amp;lt;code&amp;gt;brightness&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;setTarget&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;temperature&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;volume&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
Stelle das Licht auf 30 Prozent&lt;br /&gt;
Mach das Radio leiser&lt;br /&gt;
Stell die Temperatur im Wohnzimmer 2 Grad wärmer&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
(Beachte: Wenn wie hier im Beispiel reele Zahlen (mit Komma) ermöglicht werden sollen (&amp;quot;acht Komma fünf&amp;quot;), wird ein [[#Custom Converter für reelle Zahlen| Custom Converter für reelle Zahlen]] benötigt)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetNumeric]&lt;br /&gt;
den=(den|die|das)&lt;br /&gt;
cmdmulti=(schalte|schalt|mache|mach|stelle|stell)&lt;br /&gt;
rooms=([(im|in dem|auf dem|in der|auf der)] $de.fhem.Room{Room})&lt;br /&gt;
&amp;lt;cmdmulti&amp;gt; [&amp;lt;den&amp;gt;] $de.fhem.Device-SetNumeric{Device} auf (0..100){Value!int} [Prozent{Unit:percent}]&lt;br /&gt;
\[&amp;lt;cmdmulti&amp;gt;] [die Lautstärke [an|am]] [dem|&amp;lt;den&amp;gt;] $de.fhem.Device-media{Device} [&amp;lt;rooms&amp;gt;] [um] [(0..10){Value!float}] [dezibel{Unit:decibel}|Prozent{Unit:percent}] ( lauter:volUp | leiser:volDown ){Change}&lt;br /&gt;
&amp;lt;cmdmulti&amp;gt; [die Lautstärke [an|am]] [dem|&amp;lt;den&amp;gt;] [$de.fhem.Device-media{Device}] [&amp;lt;rooms&amp;gt;] [um] [(0..10){Value!float}] [dezibel{Unit:decibel}|Prozent{Unit:percent}] ( lauter:volUp | leiser:volDown ){Change}&lt;br /&gt;
&amp;lt;cmdmulti&amp;gt; [&amp;lt;den&amp;gt;] $de.fhem.Device-thermostat{Device} [&amp;lt;rooms&amp;gt;] [um] [(0..10){Value!int}] [Grad{Unit.degree}] ( wärmer:tempUp | kälter:tempDown ){Change}&lt;br /&gt;
&amp;lt;cmdmulti&amp;gt; [&amp;lt;den&amp;gt;] $de.fhem.Device-light{Device} [&amp;lt;rooms&amp;gt;] [um] [(0..30 [Komma:. 1..9]){Value!customFloat}] [Prozent{Unit:percent}] ( heller:lightUp | dunkler:lightDown){Change}&lt;br /&gt;
&amp;lt;cmdmulti&amp;gt; [&amp;lt;den&amp;gt;] ( $de.fhem.Device-light | $de.fhem.Device-media |$de.fhem.Device-blind){Device}  [&amp;lt;rooms&amp;gt;] auf [(0..30 [Komma:. 1..9]){Value!customFloat}]&lt;br /&gt;
( mehr{Change:lightUp} | weniger{Change:lightDown} ) $de.fhem.Device-light{Device} [&amp;lt;de.fhem:SetOnOff.rooms&amp;gt;]&lt;br /&gt;
( halte | stoppe | stop ) [&amp;lt;den&amp;gt;] $de.fhem.Device-blind{Device} [&amp;lt;de.fhem:SetOnOff.rooms&amp;gt;] [an] {Change:cmdStop}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Derzeit werden folgende Typen für das Feld &amp;lt;code&amp;gt;{Change}&amp;lt;/code&amp;gt; ausgewertet:&lt;br /&gt;
*&amp;lt;code&amp;gt;tempUp&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;tempDown&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;volUp&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;volDown&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;lightUp&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;lightDown&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;setUp&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;setDown&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notwendig sind:&lt;br /&gt;
*&amp;lt;code&amp;gt;Change&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Type&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Value&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Change&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Unit&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== SetNumericGroup ===&lt;br /&gt;
Intent, um Lampen zu dimmen, Rollladengeräte zu positionieren, Lautstärken oder Solltemperaturen zu ändern, usw.. Die Funktionsweise entspricht dabei dem des Intents &#039;&#039;SetNumeric&#039;&#039;, wobei eben statt eines einzelnen Devices eben ein oder mehrere Geräte über ihren Gruppennamen angesprochen werden. Statt des optionalen Tags &amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt; ist daher der Tag &amp;lt;code&amp;gt;Group&amp;lt;/code&amp;gt; zu übergeben.&lt;br /&gt;
Aus der Adressierung mehrerer Geräte ergeben sich einige Besonderheiten, die in der [[RHASSPY/Vertiefung]], dort speziell auch im Punkt [[RHASSPY/Vertiefung#Beispiel_SetOnOffGroup|Beispiel SetOnOffGroup]] näher erläutert sind. Wesentliche zu beachtende Aspekte sind:&lt;br /&gt;
* Vermeidung von Funk-Überschneidungen (&#039;&#039;Specials&#039;&#039; &#039;&#039;partOf&#039;&#039; und &#039;&#039;async_delay&#039;&#039;)&lt;br /&gt;
* Begrenzung der Gruppenzugehörigkeit durch die Raumzugehörigkeit (und die Aufhebung dieser Beschränkung durch die Übergabe des speziellen Raums &#039;&#039;global&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
=== GetNumeric ===&lt;br /&gt;
Intent, mit dem man Werte erfragen kann, wie z.B. die aktuelle Temperatur, Helligkeit, Lautstärke, ...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
GetNumeric:currentVal=temperature,part=1,type=temperature&lt;br /&gt;
GetNumeric:currentVal=pct,map=percent,minVal=0,maxVal=100,type=brightness&lt;br /&gt;
GetNumeric:currentVal=volume,type=volume&lt;br /&gt;
GetNumeric:currentVal=humidity,part=0,type=humidity&lt;br /&gt;
GetNumeric:currentVal=batteryPercent,type=battery&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Argumente:&lt;br /&gt;
*&amp;lt;code&amp;gt;currentVal&amp;lt;/code&amp;gt; Das Reading, das den abzufragenden Wert enthält&lt;br /&gt;
*&amp;lt;code&amp;gt;part&amp;lt;/code&amp;gt; Teile aus currentVal ableiten, indem am Leerzeichen getrennt wird. Ist &#039;&#039;currentVal&#039;&#039; beispielsweise &#039;&#039;23 C&#039;&#039;, entspricht &#039;&#039;part=1&#039;&#039; dem Wert &#039;&#039;23&#039;&#039;&lt;br /&gt;
*&amp;lt;code&amp;gt;map&amp;lt;/code&amp;gt; Die Funktionswiese entspricht dem &#039;&#039;SetNumeric&#039;&#039; Intent. Wandelt den vorhandenen Wert in eine Prozent-Angabe um.&lt;br /&gt;
*&amp;lt;code&amp;gt;minVal&amp;lt;/code&amp;gt; Niedrigster zulässiger Wert (nur benötigt, wenn &#039;&#039;map&#039;&#039; angegeben ist).&lt;br /&gt;
*&amp;lt;code&amp;gt;maxVal&amp;lt;/code&amp;gt; Höchster zulässiger Wert  (nur benötigt, wenn &#039;&#039;map&#039;&#039; angegeben ist).&lt;br /&gt;
*&amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; Dient der Unterscheidung zwischen mehreren GetNumeric-Anfragemöglichkeiten für dasselbe Gerät (auch relevant für SetNumeric-Anweisungen).&lt;br /&gt;
&lt;br /&gt;
Mögliche Abfragetypen:&lt;br /&gt;
*&amp;lt;code&amp;gt;humidity&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;battery&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;brightness&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;desired-temp&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;setTarget&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;soilMoisture&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;temperature&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;volume&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;waterLevel&amp;lt;/code&amp;gt;&lt;br /&gt;
Aus dem Abfragetypen ergibt sich die von RHASSPY ausgewählte Antwort.&lt;br /&gt;
&lt;br /&gt;
Beispiel Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
what is the temperature in the living room&lt;br /&gt;
how bright is the floor lamp&lt;br /&gt;
what is the volume of the tv&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
[en.fhem:GetNumeric]&lt;br /&gt;
#actual temperature&lt;br /&gt;
(what is|how high is) the temperature{Type:temperature} [$de.fhem.Device-GetNumeric{Device}] [$de.fhem.Room{Room}]&lt;br /&gt;
&lt;br /&gt;
#desired-temperature&lt;br /&gt;
\[what is the|how high is the] (desired temperature){Type:desired-temp} [$de.fhem.Device-GetNumeric{Device}] [$de.fhem.Room{Room}]&lt;br /&gt;
&lt;br /&gt;
#volume&lt;br /&gt;
(what is the|how high is the) volume{Type:volume} $de.fhem.Device-GetNumeric{Device} [$de.fhem.Room{Room}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Type&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional tags&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== GetState ===&lt;br /&gt;
Intent to get specific information of a device. The respone can be defined.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
GetState:response=&amp;quot;Temperature is [$DEVICE:temp] degree at [Thermo:hum] percent humidity&amp;quot;&lt;br /&gt;
GetState:response={my $value=ReadingsVal(&amp;quot;$DEVICE&amp;quot;,&amp;quot;brightness&amp;quot;,&amp;quot;&amp;quot;); return &amp;quot;Brightness is $value&amp;quot;;}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Options:&lt;br /&gt;
*&amp;lt;code&amp;gt;response&amp;lt;/code&amp;gt; Text for the response Rhassyp will give.&lt;br /&gt;
:To use values from FHEM use format [Device:Reading].&lt;br /&gt;
:A comma within the response has to be escaped (\, instead of ,).&lt;br /&gt;
:Or you can use Perl-code enclosed in curley brackets to define the response.&lt;br /&gt;
:Mixing text and Perl-code is not supported.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
How is the state of the thermostat in the kitchen&lt;br /&gt;
state light in livingroom&lt;br /&gt;
state washer&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:GetState]&lt;br /&gt;
\[how is the] (state) $de.fhem.Device{Device} [$de.fhem.Room{Room}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== MediaControls ===&lt;br /&gt;
Intent to control media devices&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mapping:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
MediaControls:cmdPlay=play,cmdPause=pause,cmdStop=stop,cmdBack=previous,cmdFwd=next&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Options:&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdPlay&amp;lt;/code&amp;gt; Play command of the device. See chapter Formatting Commands and Readings inside a rhasspyMapping.&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdPause&amp;lt;/code&amp;gt; Command to pause the device.&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdStop&amp;lt;/code&amp;gt; Command to stop the device.&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdFwd&amp;lt;/code&amp;gt; Command to skip to the next track/channel/etc.&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdBack&amp;lt;/code&amp;gt; Command to skip to the previous track/channel/etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note on issuing a voice-command without a room-name:&lt;br /&gt;
As described in the SetNumeric-Intent, it is recommended to define a GetOnOff-Mapping to use the MediaControls-Intent without a room name.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
skip to next track on the radio&lt;br /&gt;
pause&lt;br /&gt;
skip video on the dvd player&lt;br /&gt;
stop playback&lt;br /&gt;
next&lt;br /&gt;
previous&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:MediaControls]&lt;br /&gt;
(start){Command:cmdPlay} the playback [$de.fhem.Device-MediaControls{Device}]&lt;br /&gt;
(stop){Command:cmdStop} the playback [$de.fhem.Device-MediaControls{Device}]&lt;br /&gt;
(pause){Command:cmdPause} the playback [$de.fhem.Device-MediaControls{Device}]&lt;br /&gt;
(next){Command:Fwd} (song|title) [$de.fhem.Device-MediaControls{Device}]&lt;br /&gt;
(previous){Command:Back} (song|title) [$de.fhem.Device-MediaControls{Device}] [$de.fhem.Room{Room}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Command&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== MediaChannels ===&lt;br /&gt;
Intent to change radio-/tv channels, favorites, playlists, lightscenes, ...&lt;br /&gt;
&lt;br /&gt;
Instead of using the attribute rhasspyMapping, this intent is configured with an own attribute [[#rhasspyChannels]] in the respective device. Reason is the multiple-line-configuration.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
SWR3=favorite s_w_r_3&lt;br /&gt;
SWR1=favorite s_w_r_1&lt;br /&gt;
ARD=channel 204&lt;br /&gt;
Netflix=launchApp Netflix&lt;br /&gt;
Leselicht=set lightSceneWz scene Leselicht&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Notice on using the commands without a device name:&lt;br /&gt;
To start playback on a device without specifying the device name in the voice command, the module needs to know, which device should be used. Therefor it searches the attribute rhasspyChannels for suitable one. Devices in the actual or spoken room are preferred.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
play CNN on the radio in my office&lt;br /&gt;
switch to HBO&lt;br /&gt;
change channel on radio to BBC news&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[en.fhem:MediaChannels]&lt;br /&gt;
\[(play|switch to|change to)] ($de.fhem.MediaChannels){Channel} [($de.fhem.Device){Device}] [($de.fhem.Room){Room}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Channel&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetColor ===&lt;br /&gt;
Intent to change light colors&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Because of the multi-line settings, instead of configuring this intent with the attribute rhasspyMapping, a separate user-attribute [[#rhasspyColors]] is used.&lt;br /&gt;
&lt;br /&gt;
The content of the rhasspyColors uses the following format:&lt;br /&gt;
&amp;lt;code&amp;gt;Colorname=cmd&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Settings:&lt;br /&gt;
*&amp;lt;code&amp;gt;Colorname&amp;lt;/code&amp;gt; The name of the color you want to use in a voice-command&lt;br /&gt;
*&amp;lt;code&amp;gt;cmd&amp;lt;/code&amp;gt; The FHEM-command&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
red=rgb FF0000&lt;br /&gt;
green=rgb 00FF00&lt;br /&gt;
blue=rgb 0000FF&lt;br /&gt;
white=ct 3000&lt;br /&gt;
warm white=ct 2700&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
change light to green&lt;br /&gt;
lightstrip blue&lt;br /&gt;
color the light in the sleeping room white&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[en.fhem:SetColor]&lt;br /&gt;
\[change|color] $de.fhem.Device{Device} [$de.fhem.Room{Room}] $de.fhem.Color{Color}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Color&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional tags&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetColorGroup ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetScene ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GetTime ===&lt;br /&gt;
Intent um die Uhrzeit zu erfragen.&lt;br /&gt;
&lt;br /&gt;
Es werden keine Konfigurationen in FHEM benötigt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
wie spät ist es?&lt;br /&gt;
sag mir die uhrzeit&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:GetTime]&lt;br /&gt;
wie spät [ist es]&lt;br /&gt;
sag mir die uhrzeit&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GetDate ===&lt;br /&gt;
Intent um das aktuelle Datum zu erfragen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Keine FHEM Einstellungen nötig.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Satz:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
welcher tag ist heute&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:GetDate]&lt;br /&gt;
welcher tag ist heute&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetTimer ===&lt;br /&gt;
Intent to create a timer/countdown/alarm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This intent creates an AT-command in FHEM with the given time and - currently - speaks the sentences &amp;quot;timer expired&amp;quot; when it has expired.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
No FHEM-settings needed&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
Set timer in bedroom to five minutes&lt;br /&gt;
Set countdown in the kitchen to two hours&lt;br /&gt;
set timer to five and a half hours&lt;br /&gt;
set alarm to 5 o&#039; clock&lt;br /&gt;
set timer to 3 hours and 20 minutes&lt;br /&gt;
set timer to 1 hour, 30 minutes and 15 seconds&lt;br /&gt;
stop the timer in bedroom&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentence:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetTimer]&lt;br /&gt;
labels=(alarm|teetimer|countdown|timer)&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in) [((1..60){Hour!int} (hour|hours))] [and] [((1..60){Min!int} (minute|minutes))] [and] [((1..60){Sec!int} (second|seconds))]&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in) (1..60){Hour!int} and (a quarter{Min:15}|a half{Min:30}|three quarters{Min:45}) (hour|hours)&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in) (1..60){Min!int} and (a quarter{Sec:15}|a half{Sec:30}|three quarters{Sec:45}) (minute|minutes)&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in) ((the fourth){Min:15}|(half a){Min:30}|(three fourth){Min:45}) (hour)&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in) ((the fourth){Min:15}|(half a){Min:30}|(three fourth){Min:45}) (minute)&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in|at) (1..24){Hourabs!int} [(1..60){Min!int}] o clock&lt;br /&gt;
&lt;br /&gt;
(cancel|remove|stop|delete){CancelTimer} [&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags to set a timer:&lt;br /&gt;
*&amp;lt;code&amp;gt;Label&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Hour&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Hourabs&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Min&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Sec&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags to cancel a timer:&lt;br /&gt;
*&amp;lt;code&amp;gt;Label&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
rhasspyTweaks for Timer:&lt;br /&gt;
*&amp;lt;code&amp;gt;[[#attr-rhasspytweaks-timerlimits|timerLimits]]&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;[[#attr-rhasspytweaks-timersounds|timerSounds]]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetMute ===&lt;br /&gt;
Intent to disable/enable the processing of intents on a specific siteId. Rhasspy will still listen to the wakeword but will not process any intents.&lt;br /&gt;
&lt;br /&gt;
This intents creates a Reading &amp;lt;code&amp;gt;mute_siteId&amp;lt;/code&amp;gt; for every siteId it get&#039;s a voice-command from.&lt;br /&gt;
&lt;br /&gt;
No FHEM-settings needed&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
good night&lt;br /&gt;
be quiet&lt;br /&gt;
good morning&lt;br /&gt;
make noise&lt;br /&gt;
start listening&lt;br /&gt;
stop listening&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetMute]&lt;br /&gt;
(good night|be quiet){Value:on}&lt;br /&gt;
(good morning|make noise){Value:off}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hinweis: Die Felder &amp;lt;code&amp;gt;{Value:on}&amp;lt;/code&amp;gt; bzw. &amp;lt;code&amp;gt;{Value:off}&amp;lt;/code&amp;gt; sind verpflichtend und &#039;&#039;case sensitive&#039;&#039;, der Wert &#039;&#039;on&#039;&#039; bzw. &#039;&#039;off&#039;&#039; ist in Englisch anzugeben!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ConfirmAction ===&lt;br /&gt;
Dies ist - wie die drei folgenden Intents &#039;&#039;CancelAction&#039;&#039;, &#039;&#039;ChoiceRoom&#039;&#039; und &#039;&#039;ChoiceDevice&#039;&#039; auch - ein Intent, der im Rahmen von Dialogen benötigt wird. Siehe dazu auch [[RHASSPY/Vertiefung#Dialoge|Vertiefung - Dialoge]].&lt;br /&gt;
Rückgabe ist zwingend &amp;lt;code&amp;gt;{Mode}&amp;lt;/code&amp;gt; mit dem Wert &#039;&#039;OK&#039;&#039;, alles andere wird so behandelt, als wäre der Intent &#039;&#039;CancelAction&#039;&#039; ausgewählt worden.&lt;br /&gt;
&lt;br /&gt;
=== CancelAction ===&lt;br /&gt;
Siehe &#039;&#039;ConfirmAction&#039;&#039;. Dieser Intent muss nicht zwingend existieren, es kann auch ein unpassender Rückgabewert in &#039;&#039;ConfirmAction&#039;&#039; angegeben werden, um die Abbruch-Routinen für Dialoge zu starten.&lt;br /&gt;
&lt;br /&gt;
=== ChoiceRoom ===&lt;br /&gt;
Siehe &#039;&#039;ConfirmAction&#039;&#039;. Dient im Rahmen von Dialogen der Auswahl eines Raums.&lt;br /&gt;
&lt;br /&gt;
=== ChoiceDevice ===&lt;br /&gt;
Siehe &#039;&#039;ConfirmAction&#039;&#039;. Dient im Rahmen von Dialogen der Auswahl eines Gerätes.&lt;br /&gt;
&lt;br /&gt;
=== ReSpeak ===&lt;br /&gt;
Wiederholt den letzten Satz, den Rhasspy gesprochen hat. Um genauer zu sein: Spricht den Inhalt des FHEM Readings &amp;lt;code&amp;gt;voiceResponse&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Keine Einstellungen in FHEM benötigt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
was hast du gesagt&lt;br /&gt;
kannst du das wiederholen&lt;br /&gt;
ich habe dich nicht verstanden&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:ReSpeak]&lt;br /&gt;
was hast du gesagt&lt;br /&gt;
kannst du das [bitte] wiederholen&lt;br /&gt;
ich habe dich nicht verstanden&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Eigene Intents erstellen ==&lt;br /&gt;
Es ist auch möglich, eigene Intents zu erstellen, sollten die hier vorgestellten nicht reichen. Dafür gibt es zwei Wege: Für kleinere Intents können die Möglichkeiten von FHEMs [[99_myUtils_anlegen|99_myUtils.pm]] genutzt werden. Aufwendigere Intents können in jeweils eigenen Dateien abgelegt werden, die dann von RHASSPY ausgelesen werden.&lt;br /&gt;
=== Intents in 99_myUtils.pm ===&lt;br /&gt;
&lt;br /&gt;
Hier ein (veraltetes, siehe oben) Beispiel, mit dem die letzte &#039;&#039;voice response&#039;&#039; wiederholt werden kann.&lt;br /&gt;
&lt;br /&gt;
Ergänze deine 99_myUtils.pm mit folgender Funktion:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub Respeak(){&lt;br /&gt;
  #Credits to JensS&lt;br /&gt;
  my $name = &amp;quot;Rhasspy&amp;quot;; #Replace &amp;quot;Rhasspy&amp;quot; with the name of your RHASSPY-Device&lt;br /&gt;
  my $response = ReadingsVal($name,&amp;quot;voiceResponse&amp;quot;,&amp;quot;Ich kann mich leider nicht erinnern&amp;quot;);&lt;br /&gt;
  return $response;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ergänze im Attribut &#039;&#039;rhasspyIntents&#039;&#039; folgende Zeile (je Intent muss eine eigene Zeile verwendet werden):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
Respeak=Respeak()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ergänze einen neuen Intent in deinen &#039;&#039;sentence.ini&#039;&#039; an der Rhasspy base:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:Respeak]&lt;br /&gt;
was hast du gesagt&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Intents in eigenen Dateien ===&lt;br /&gt;
Beispiele: https://github.com/fhem/fhem-rhasspy/blob/main/FHEM/99_RHASSPY_Utils_Demo.pm&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: Raumwechsel ====&lt;br /&gt;
Erforderlichen Code in das Modulverzeichnis holen und laden: &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;{ Svn_GetFile(&#039;contrib/RHASSPY/99_RHASSPY_Utils_siteId2room.pm&#039;, &#039;FHEM/99_RHASSPY_Utils_siteId2room.pm&#039;,sub(){ RHASSPY_Utils_siteId2room_Initialize() }) }&amp;lt;/syntaxhighlight&amp;gt;Ergänze im Attribut &#039;&#039;rhasspyIntents&#039;&#039; folgende Zeile (je Intent muss eine eigene Zeile verwendet werden):&lt;br /&gt;
&amp;lt;syntaxhighlight  lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
siteId2room=RHASSPY::siteId2room::siteId2room(NAME,DATA)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Ergänze einen neuen Intent in deinen &#039;&#039;sentence.ini&#039;&#039; an der Rhasspy base:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:siteId2room]&lt;br /&gt;
( Ortswechsel  | begib dich ) ( ins | in den ) $de.fhem.Room{Room}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tipps &amp;amp; Tricks ==&lt;br /&gt;
===Custom Converter für reelle Zahlen===&lt;br /&gt;
Rhasspy kann (derzeit) keine gesprochenen reellen Nummern (z.B. 22,5) als Nummer erkennen. Stattdessen interpretiert es die Zahl als zwei Nummern und einen Punkt.&lt;br /&gt;
&lt;br /&gt;
Um reelle Nummern richtig zu verwenden, muss ein [https://rhasspy.readthedocs.io/en/latest/training/#converters Custom Converter] erstellt und in der sentences.ini verwendet werden.&lt;br /&gt;
&lt;br /&gt;
So ein Konverter kann erstellt werden, in dem unter &amp;lt;code&amp;gt;&amp;lt;profile&amp;gt;/converters&amp;lt;/code&amp;gt; ein neues File mit beliebigem Namen angelegt wird. Der Name muss aber dann auch genau so als Converter in der sentences.ini verwendet werden. Anschließend muss die Datei noch ausführbar gemacht werden.&lt;br /&gt;
&lt;br /&gt;
Z.B.:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
touch .config/rhasspy/profile/en/converters/customFloat&lt;br /&gt;
chmod +x .config/rhasspy/profile/en/converters/customFloat&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Folgender Beispiel-Code kann danach in die Datei geschrieben werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python3&lt;br /&gt;
import sys&lt;br /&gt;
import json&lt;br /&gt;
&lt;br /&gt;
# von Rhasspy als JSON übergebene/n Wert/e einlesen&lt;br /&gt;
args = json.load(sys.stdin)&lt;br /&gt;
&lt;br /&gt;
# wenn im deserialisierten JSON nur ein Wert ist, wird der als Ergebnis genommen&lt;br /&gt;
# sind mehrere Werte vorhanden (z.B. 22,.,5), werden die zu einem einzelnen String zusammen gesetzt&lt;br /&gt;
if type(args) == int:&lt;br /&gt;
    num = args&lt;br /&gt;
else:&lt;br /&gt;
    num = &amp;quot;&amp;quot;.join(str(s).strip() for s in args)&lt;br /&gt;
&lt;br /&gt;
# Ergebnis wird an Rhasspy übergeben&lt;br /&gt;
print(num)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nach einem Neustart von Rhasspy kann dieser Converter dann verwendet werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem.SetNumeric]&lt;br /&gt;
stelle die heizung auf (0..30 [komma:. 0..99]){Value!customFloat}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rhasspy speaks actual state of device after switching it===&lt;br /&gt;
JensS wrote a short script to let Rhasspy speak the actual state of a FHEM-device after switching it with a voice-command.&lt;br /&gt;
Add the following to your 99_myUtils.pm&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub ResponseOnOff($){&lt;br /&gt;
  my ($dev) = @_;&lt;br /&gt;
  my $room;&lt;br /&gt;
  my $state = lc(ReadingsVal($dev,&amp;quot;state&amp;quot;,&amp;quot;in unknown state&amp;quot;));&lt;br /&gt;
  my $name = (split(/,/,AttrVal($dev,&amp;quot;rhasspyName&amp;quot;,&amp;quot;error&amp;quot;)))[0];&lt;br /&gt;
  if (AttrVal($dev,&amp;quot;rhasspyRoom&amp;quot;,&amp;quot;&amp;quot;)){$room = &amp;quot; in &amp;quot;.(split(/,/,AttrVal($dev,&amp;quot;rhasspyRoom&amp;quot;,&amp;quot;&amp;quot;)))[0]};&lt;br /&gt;
  $state=~s/.*on/turned on/;&lt;br /&gt;
  $state=~s/.*off/turned off/;&lt;br /&gt;
  return &amp;quot;Ok - &amp;quot;.$name.$room.&amp;quot; is now &amp;quot;.$state&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
and add a response to the SetOnOff-Mapping of a device&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
SetOnOff:cmdOn=on,cmdOff=off,response={ResponseOnOff($DEVICE)}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [https://github.com/rhasspy/rhasspy Rhasspy auf Github]&lt;br /&gt;
* [https://rhasspy.readthedocs.io/en/latest/ offizielle Rhasspy Doku-Seite]&lt;br /&gt;
* [https://community.rhasspy.org/ Offizielles Rhasspy Forum]&lt;br /&gt;
* [https://github.com/fhem/fhem-rhasspy fhem-rhasspy Modul auf GitHub]&lt;br /&gt;
* [https://github.com/Romkabouter/ESP32-Rhasspy-Satellite ESP32-basierte Hardware als Satelliten]&lt;br /&gt;
* [https://github.com/razzo04/rhasspy-mobile-app App für Android-Satelliten]&lt;br /&gt;
* [https://www.youtube.com/watch?v=sWVl0ZoXZEo Video zu sentences.ini]&lt;br /&gt;
[[Kategorie:Sprachsteuerung]]&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=RHASSPY&amp;diff=37369</id>
		<title>RHASSPY</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=RHASSPY&amp;diff=37369"/>
		<updated>2022-03-29T15:42:51Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: /* GetNumeric */ - airHumidity auf humidity geändert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
Diese Seite beschreibt die Konfiguration und Verwendung des Moduls 10_RHASSPY.pm. &lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=Anbindung von FHEM an den Rhasspy Sprachassistenten&lt;br /&gt;
|ModType=contrib&lt;br /&gt;
|ModCmdRef=RHASSPY&lt;br /&gt;
|ModForumArea=Frontends/Sprachsteuerung&lt;br /&gt;
|ModFTopic=119447&lt;br /&gt;
|ModTechName=10_RHASSPY.pm&lt;br /&gt;
|ModOwner=Beta-User ({{Link2FU|9229|Forum}}/[[Benutzer Diskussion:Beta-User|Wiki]]), drhirn ({{Link2FU|15727|Forum}}/[[Benutzer Diskussion:Drhirn|Wiki]])&lt;br /&gt;
}}&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
[https://github.com/rhasspy/rhasspy Rhasspy] ist eine Open Source Server-Lösung für Spracherkennung und Sprachsteuerung, welche auf einem RaspBerry Pi oder einem anderen Debian-basierten Serversystem lauffähig ist. Es handelt sich dabei um eine Sammlung von Programmen (=Skripten in der Python-Sprechweise), die unter einer einheitlichen und sehr  flexiblen Benutzungsoberfläche zusammengefasst sind. Die Besonderheit an Rhasspy ist, dass es nach der Installation komplett offline betrieben werden kann. Es werden also keine Daten an einen Server im Internet geschickt, und für den Betrieb nur für FHEM werden nur moderate Hardwareanforderungen gestellt - ein aktueller Raspberry Pi ab Modell 3B+ sollte in der Regel genügen.&lt;br /&gt;
&lt;br /&gt;
Die Anbindung weiterer Räume ist über sogenannte &amp;quot;Satelliten&amp;quot; möglich. Dies kann z.B. ein Pi Zero mit Mikro und Lautsprecher sein, ein ESP32 mit entsprechender Hardware oder ein Mobiltelefon mit Android und der entsprechenden App.&lt;br /&gt;
&lt;br /&gt;
Rhasspy besteht aus vielen unterschiedlichen Modulen (Hot-Word Erkennung, Text-to-Speech, Speech-to-Text, Intent Erkennung, etc.). Alle diese Module kommunizieren miteinander über das [[MQTT|MQTT]]-Protokoll.&lt;br /&gt;
&lt;br /&gt;
Das Modul [[RHASSPY]] prüft Teile des MQTT-Traffics, konvertiert diese JSON-Nachrichten in FHEM-Befehle und sendet Nachrichten zurück an Rhasspy um z.B. Antworten über Text-to-Speech auszugeben.&lt;br /&gt;
&lt;br /&gt;
RHASSPY verwendet das Modul 00_MQTT2_CLIENT.pm um Nachrichten zu empfangen und zu senden. Daher ist es notwendig, eine Instanz dieses Moduls als FHEM-Device zu erstellen, bevor RHASSPY verwendet werden kann.&lt;br /&gt;
&lt;br /&gt;
Hervorgegangen ist RHASSPY aus dem Snips-Modul, nachdem Snips an Sonos verkauft und anschließend eingestellt wurde. Danke also an Thyraz, der die grundlegenden Arbeiten erledigt hat!&lt;br /&gt;
&lt;br /&gt;
=== Konventionen ===&lt;br /&gt;
{{Hinweis| In diesem Artikel und der CommandRef werden folgende Schreibweisen verwendet:&lt;br /&gt;
* &#039;&#039;&#039;[[RHASSPY]]&#039;&#039;&#039; bezieht sich auf das FHEM-Modul&lt;br /&gt;
* &#039;&#039;&#039;rhasspy&#039;&#039;&#039; bezieht sich auf das das FHEM-Device&lt;br /&gt;
* &#039;&#039;&#039;Rhasspy&#039;&#039;&#039; bezeichnet die (zentrale) Serverinstallation}}&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|Dialoge werden in RHASSPY verwaltet wie [https://rhasspy.readthedocs.io/en/latest/reference/#dialogue-manager hier] beschrieben. Dialoge werden also nicht funktionieren, sobald für das Dialogue-Management etwas anderes als &#039;&#039;RHASSPY&#039;&#039; eingestellt ist}}&lt;br /&gt;
&lt;br /&gt;
=== Erste Schritte ===&lt;br /&gt;
Die Installation und Erstinbetriebnahme von Rhasspy wird in einer Schnellstart-Anleitung erklärt: [[RHASSPY/Schnellstart]] Diese Anleitung sollte auch befolgt werden, wenn man sich sehr gut mit FHEM auskennt. Wer dies erfolgreich absolviert hat, kann gleich zu Abschnitt [[#Set-Befehle_.28SET.29|Set-Befehle (SET)]] weiterspringen, und/oder die [[RHASSPY/Vertiefung|Vertiefung]] durcharbeiten.&lt;br /&gt;
&lt;br /&gt;
=== Details zur Verwaltung des RHASSPY Moduls ===&lt;br /&gt;
Das Modul ist derzeit nicht in der &amp;quot;offiziellen&amp;quot; FHEM Distribution enthalten und muss daher manuell installiert werden. Dafür gibt es zwei Möglichkeiten.&lt;br /&gt;
&lt;br /&gt;
*Im Subversion Repository, kurz SVN von FHEM ist die jeweils aktuelle &amp;quot;stable&amp;quot; Version des Moduls im &#039;&#039;contrib&#039;&#039;-Zweig zu finden. Diese kann mit folgendem Befehl, der im FHEM Befehls-Eingabefeld einzugeben ist, heruntergeladen werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;{ Svn_GetFile(&#039;contrib/RHASSPY/10_RHASSPY.pm&#039;, &#039;FHEM/10_RHASSPY.pm&#039;) }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Genauere Informationen zu dieser Vorgangsweise finden sich unter [[Update#Einzelne_Dateien_aus_dem_SVN_holen]]. Nach Installation des Moduls muss FHEM neu gestartet werden.&lt;br /&gt;
*FHEM Update und GitHub&lt;br /&gt;
Im GitHub-Repository des Moduls gibt es zwei Branches &#039;&#039;main&#039;&#039; und &#039;&#039;dev&#039;&#039;. In &#039;&#039;main&#039;&#039; ist die stabile Version des Moduls, in &#039;&#039;dev&#039;&#039; die jeweils aktuelle Entwicklungsversion. Aus Gründen der Stabilität ist natürlich die aus &#039;&#039;main&#039;&#039; zu bevorzugen.&lt;br /&gt;
&lt;br /&gt;
Um das Modul zu installieren bzw. zu aktualisieren, kann der &#039;&#039;update&#039;&#039;-Mechanismus von FHEM genutzt werden. Dazu muss das Repository in der Liste der vom update-Befehl verarbeiteten Repositorien aufgenommen werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;update add https://raw.githubusercontent.com/fhem/fhem-rhasspy/main/controls_fhem-rhasspy.txt&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Anschließend kann mit folgendem Befehl das Modul installiert oder aktualisiert werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;update all https://raw.githubusercontent.com/fhem/fhem-rhasspy/main/controls_fhem-rhasspy.txt&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wählt man diesen Weg, wird das Modul auch automatisch aktualisiert, wenn ein Update von FHEM durchgeführt wird. Möchte man die Entwicklungsversion verwenden, muss in den beiden Befehlen &#039;&#039;main&#039;&#039; durch &#039;&#039;dev&#039;&#039; ersetzt werden.&lt;br /&gt;
&lt;br /&gt;
Weitere Informationen zu dieser Vorgangsweise in der stehen in der [https://fhem.de/commandref.html#update CommandRef] oder im [[Update|FHEM-Wiki]].&lt;br /&gt;
&lt;br /&gt;
Nach Installation des Moduls muss FHEM neu gestartet werden.&lt;br /&gt;
&lt;br /&gt;
== Einrichtung MQTT2_CLIENT ==&lt;br /&gt;
Rhasspy kommuniziert hauptsächlich über das [[MQTT]]-Protokoll. Und zwar sowohl Rhasspy-intern, wie auch mit FHEM. Da dies auch für die übertragene Sprache und Audio-Dateien gilt und es daher zu sehr viel MQTT-Verkehr kommt, sollte der Rhasspy-interne MQTT-Server verwendet werden. Daher ist die Einrichtung eines [[MQTT2_CLIENT]]-Devices notwendig, um die für FHEM relevanten Daten zu beziehen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zuerst muss ein MQTT2_CLIENT Device erstellt werden, welches sich mit dem MQTT-Server (Mosquitto) von Rhasspy verbindet:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;define &amp;lt;deviceName&amp;gt; MQTT2_CLIENT &amp;lt;ip-oder-hostname-des-mqtt-servers&amp;gt;:&amp;lt;port&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anschließend wird die &#039;&#039;clientOrder&#039;&#039; gesetzt, um die richtige Benachrichtigungsreihenfolge einzustellen. Wird das MQTT2_CLIENT Device nur für RHASSPY verwendet, reicht hier die Angabe &amp;lt;code&amp;gt;RHASSPY&amp;lt;/code&amp;gt;. Ansonsten müssen noch alle anderen Devices (z.B. &amp;lt;code&amp;gt;MQTT_GENERIC_BRIDGE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;MQTT2_DEVICE&amp;lt;/code&amp;gt;) angegeben werden.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;attr &amp;lt;deviceName&amp;gt; clientOrder RHASSPY [device2] [device3]&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Um die Topics einzuschränken, die das Device abonniert, müssen diese angegeben werden. Wird der MQTT-Server nur für RHASSPY verwendet, reicht die Angabe &amp;lt;code&amp;gt;setByTheProgram&amp;lt;/code&amp;gt;. Ansonsten müssen alle für RHASSPY notwendigen Topics eingefügt werden.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;attr &amp;lt;deviceName&amp;gt; subscriptions setByTheProgram&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
bzw.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;attr &amp;lt;deviceName&amp;gt; subscriptions hermes/intent/+ hermes/dialogueManager/sessionStarted hermes/dialogueManager/sessionEnded hermes/nlu/intentNotRecognized hermes/hotword/+/detected&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Beispiele&lt;br /&gt;
* Rhasspy-interner MQTT-Server wird mit seinem Standard-Port verwendet. Rhasspy läuft auf der selben Maschine wie FHEM. MQTT2_CLIENT wird nur für RHASSPY verwendet.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod rhasspyMQTT2 MQTT2_CLIENT localhost:12183&lt;br /&gt;
attr rhasspyMQTT2 clientOrder RHASSPY&lt;br /&gt;
attr rhasspyMQTT2 subscriptions setByTheProgram&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*Rhasspy läuft auf einem eigenen Server und verwendet einen externen MQTT Server mit eigener Port-Einstellung. MQTT2_CLIENT wird für RHASSPY, aber auch MQTT_GENERIC_BRIDGE und MQTT2_DEVICE verwendet.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod rhasspyMQTT2 MQTT2_CLIENT 192.168.1.122:1884&lt;br /&gt;
attr rhasspyMQTT2 clientOrder RHASSPY MQTT_GENERIC_BRIDGE MQTT2_DEVICE&lt;br /&gt;
attr rhasspyMQTT2 subscriptions hermes/intent/+ hermes/dialogueManager/sessionStarted hermes/dialogueManager/sessionEnded hermes/nlu/intentNotRecognized hermes/hotword/+/detected [zusätzliche Subscriptions für andere MQTT-Module]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Definition von RHASSPY (DEF)==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;define &amp;lt;name&amp;gt; RHASSPY &amp;lt;baseUrl&amp;gt; &amp;lt;devspec&amp;gt; &amp;lt;defaultRoom&amp;gt; &amp;lt;language&amp;gt; &amp;lt;fhemId&amp;gt; &amp;lt;prefix&amp;gt; &amp;lt;useGenericAttrs&amp;gt; &amp;lt;handleHotword&amp;gt; &amp;lt;encoding&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
{{Randnotiz|RNTyp=Info|RNText=RHASSPY verwendet sehr oft &amp;lt;parseParams&amp;gt;. Nicht nur im Define, sondern z.B. auch, um Attribut-Werte auszuwerten. Es sollten also alle Parameter im Define in der Form key=value angegeben werden.).}}{{Randnotiz|RNTyp=Info|RNText=RHASSPY führt jede Menge Daten aus unterschiedlichen Quellen zusammen um seine Funktion erfüllen zu können. Die endgültige Daten-Struktur, die RHASSPY verwendet, kann mittels des [[List|list]]-Kommandos angezeigt werden. Es wird empfohlen, sich diese Daten-Struktur auf jeden Fall anzusehen. Vor allem dann, wenn etwas nicht wie gewünscht funktioniert.}}&lt;br /&gt;
Alle Parameter sind &#039;&#039;&#039;optional&#039;&#039;&#039;. Die meisten werden im Normalfall gar nicht benötigt (z.B. &amp;lt;code&amp;gt;fhemId&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;prefix&amp;lt;/code&amp;gt;). Sollten sie aber verwendet und später geändert werden, kann es zu unvorhergesehenem Verhalten kommen. Speziell beim Einstieg in das Thema RHASSPY sollten nicht mehr, als die ersten drei verwendet werden. Ausgenommen eventuell noch &amp;lt;code&amp;gt;language&amp;lt;/code&amp;gt;, möchte man eine andere Sprache als Englisch oder Deutsch verwenden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;def-baseurl&amp;quot;&amp;gt;baseUrl&amp;lt;/code&amp;gt;&lt;br /&gt;
:Die URL zum Rhasspy-Webservice. Sollten eine Base und mehrere Satelliten verwendet werden, die URL zur Base. Bitte sicherstellen, dass die Adresse richtig ist (IP und Port)! Default ist &amp;lt;code&amp;gt;baseUrl=http://127.0.0.1:12101&amp;lt;/code&amp;gt;.&lt;br /&gt;
;&amp;lt;code id=&amp;quot;def-devspec&amp;quot;&amp;gt;devspec&amp;lt;/code&amp;gt;&lt;br /&gt;
:devspec der Geräte, die mit Rhasspy gesteuert werden sollen. Wenn der &#039;&#039;genericDeviceType&#039;&#039;-Support aktiviert ist, ist der Default &amp;lt;code&amp;gt;devspec=genericDeviceType=.+&amp;lt;/code&amp;gt;, sonst wird &amp;lt;code&amp;gt;devspec=room=Rhasspy&amp;lt;/code&amp;gt; verwendet. Ohne ein passendes Match in der devspec wird kein Gerät mit dem Modul interagieren, egal, ob sonst irgendwelche RHASSPY-spezifischen Attribute beim Gerät gesetzt sind. Genauere Informationen, wie z.B. eine Liste von Geräten oder Kombinationen aus Geräten und Räumen (z.B. &amp;lt;code&amp;gt;devspec=room=livingroom,room=bathroom,bedroomlamp&amp;lt;/code&amp;gt;) verwendet werden können, finden sich in der [https://commandref.fhem.de/commandref.html#devspec CommandRef].&lt;br /&gt;
;&amp;lt;code id=&amp;quot;def-defaultroom&amp;quot;&amp;gt;defaultRoom&amp;lt;/code&amp;gt;&lt;br /&gt;
:Der Name des Standard-Raumes, der verwendet wird, wenn im Sprachkommando kein Raum enthalten ist und auch kein passender für das Device gefunden werden kann. Default ist &amp;lt;code&amp;gt;defaultRoom=default&amp;lt;/code&amp;gt;.&lt;br /&gt;
;&amp;lt;code id=&amp;quot;def-language&amp;quot;&amp;gt;language&amp;lt;/code&amp;gt;&lt;br /&gt;
:Sprache, in der mit Rhasspy gesprochen wird. Der Standard-Wert hängt vom &#039;&#039;global&#039;&#039;-Device ab. Dieser ist standardmäßig &amp;lt;code&amp;gt;language=en&amp;lt;/code&amp;gt;.&lt;br /&gt;
;&amp;lt;code id=&amp;quot;def-fhemid&amp;quot;&amp;gt;fhemId&amp;lt;/code&amp;gt;&lt;br /&gt;
:Wird verwendet um auf MQTT-Seite zwischen mehreren Installationen des RHASSPY-Moduls zu unterscheiden. Ist auch ein Teil des Topic-Trees, auf den die jeweilige RHASSPY-Instanz hört. Default ist &amp;lt;code&amp;gt;fhemId=fhem&amp;lt;/code&amp;gt;.&lt;br /&gt;
;&amp;lt;code id=&amp;quot;def-prefix&amp;quot;&amp;gt;prefix&amp;lt;/code&amp;gt;&lt;br /&gt;
:Wird verwendet um auf FHEM-Seite zwischen mehreren Installationen des RHASSPY-Moduls zu unterscheiden. Praktisch, wenn man mehrere Instanzen von RHASSPY auf einer FHEM Installation laufen hat und z.B. verschiedene Bezeichner für Gruppen und Räume haben möchte (z.B. unterschiedliche Sprachen). Default ist &amp;lt;code&amp;gt;prefix=rhasspy&amp;lt;/code&amp;gt;.&lt;br /&gt;
;&amp;lt;code id=&amp;quot;def-usegenericattrs&amp;quot;&amp;gt;&#039;&#039;&#039;useGenericAttrs&#039;&#039;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
:Üblicherweise verwendet RHASSPY - wie auch einige andere FHEM Module für Sprachassistenten - das Attribut &#039;&#039;genericDeviceType&#039;&#039; um Schaltmöglichkeiten von Geräten automatisch zu erkennen. Dieser Parameter fügt das Attribut &#039;&#039;genericDeviceType&#039;&#039; zur globalen Attributliste hinzu. Der Wert 0 verhindert dieses hinzufügen. Default ist &amp;lt;code&amp;gt;useGenericAttrs=1&amp;lt;/code&amp;gt;.&lt;br /&gt;
;&amp;lt;code id=&amp;quot;def-encoding&amp;quot;&amp;gt;encoding&amp;lt;/code&amp;gt;&lt;br /&gt;
:Sollte es Probleme mit Umlauten geben, kann das Character-Encoding geändert werden. Default ist &amp;lt;code&amp;gt;encoding=utf8&amp;lt;/code&amp;gt;.&lt;br /&gt;
;&amp;lt;code id=&amp;quot;handlehotword&amp;quot;&amp;gt;handleHotword&amp;lt;/code&amp;gt;&lt;br /&gt;
:Triggert das Reading &#039;&#039;hotword&#039;&#039;, wenn ein Hotword erkannt wurde (und erstellt das Reading, falls noch nicht vorhanden). Weitere Informationen dazu stehen beim Attribut [[#attr-rhasspyhotwords|&#039;&#039;rhasspyHotwords&#039;&#039;]]. Default ist &amp;lt;code&amp;gt;handleHotword=0&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|Nach dem Definieren eines RHASSPY-Modules sollte das IODev manuell gesetzt werden um ein automatische IO-Zuweisung zu verhindern. Z.B. &amp;lt;code&amp;gt;attr &amp;lt;deviceName&amp;gt; IODev &amp;lt;m2client&amp;gt;&amp;lt;/code&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
;Beispiele:&lt;br /&gt;
Läuft Rhasspy auf der selben Maschine wie FHEM, die Sprache ist im &#039;&#039;global&#039;&#039;-Device bereits richtig eingestellt und der Standardraum entspricht der siteID, die in Rhasspy vergeben wurde:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;define Rhasspy RHASSPY&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Läuft Rhasspy auf einem anderen System wie FHEM, der Standard-Raum enspricht nicht dem, was Rhasspy liefert, die Sprache soll auch anders sein und es sollen sowohl Geräte mit vorhandenem &#039;&#039;genericDeviceType&#039;&#039; Attribut, als auch die Geräte &#039;&#039;device_a1&#039;&#039; und &#039;&#039;device_xy&#039;&#039; gesteuert werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;define Rhasspy RHASSPY baseUrl=http://192.168.1.210:12101 defaultRoom=&amp;quot;Büro Lisa&amp;quot; language=de devspec=genericDeviceType=.+,device_a1,device_xy handleHotword=1&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Set-Befehle (SET)==&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;set-customslot&amp;quot;&amp;gt;customSlot&amp;lt;/code&amp;gt;&lt;br /&gt;
:Erstellt einen neue - oder überschreibt einen alten - Slot in Rhasspy&lt;br /&gt;
:&amp;lt;code&amp;gt;slotname&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;slotdata&amp;lt;/code&amp;gt; sind verpflichtend&lt;br /&gt;
:&amp;lt;code&amp;gt;overwrite&amp;lt;/code&amp;gt; ist optional. Default ist &amp;lt;code&amp;gt;overwrite=true&amp;lt;/code&amp;gt;. Das Setzen eines anderes Wertes verhindert das Überschreiben einen bereits bestehenden Slot mit gleichem Namen.&lt;br /&gt;
:&amp;lt;code&amp;gt;training&amp;lt;/code&amp;gt; ist optional. Default ist &amp;lt;code&amp;gt;training=true&amp;lt;/code&amp;gt;. Das Setzen eines anderen Wertes verhindert ein Training von Rhasspy nach dem Speichern des Slots.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Beispiele:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; customSlot mySlot a,b,c overwrite training&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; customSlot slotname=mySlot slotdata=a,b,c overwrite=false&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;set-fetchsiteids&amp;quot;&amp;gt;fetchSiteIds&amp;lt;/code&amp;gt;&lt;br /&gt;
:Liest alle in Rhasspy vorhandenen siteIDs aus und speichert sie im Reading &#039;&#039;siteIds&#039;&#039;. Wird z.B. verwendet, um festzustellen, auf welchem Satelliten der User über das Ende eines Timers benachrichtigt werden soll.&lt;br /&gt;
:Muss immer ausgeführt werden, wenn eine neue siteId in Rhasspy hinzugefügt wird (neuer Satellit z.B.).&lt;br /&gt;
:&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; fetchSiteIds&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;set-play&amp;quot;&amp;gt;play&amp;lt;/code&amp;gt;&lt;br /&gt;
:Sendet eine WAV Datei an Rhasspy.&lt;br /&gt;
:&amp;lt;code&amp;gt;siteId&amp;lt;/code&amp;gt; und &amp;lt;path&amp;gt; sind verpflichtend!&lt;br /&gt;
:Optional kann die Anzahl der Wiederholungen (Default: 1) und die Dauer der Pause zwischen den jeweiligen Wiederholungen (Default: 15) angeben werden.&lt;br /&gt;
:&#039;&#039;Beispiele:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; play siteId=&amp;quot;default&amp;quot; path=&amp;quot;/opt/fhem/test.wav&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; play siteId=&amp;quot;default&amp;quot; path=&amp;quot;./test.wav&amp;quot; repeats=3 wait=20&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;set-speak&amp;quot;&amp;gt;speak&amp;lt;/code&amp;gt;&lt;br /&gt;
:Sendet einen Text an das TTS-Sytem, welches ihn dann als Sprache ausgibt.&lt;br /&gt;
:Beide Argumente &amp;lt;code&amp;gt;siteId&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;text&amp;lt;/code&amp;gt; sind verpflichtend!&lt;br /&gt;
:&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; speak siteId=&amp;quot;wohnzimmer&amp;quot; text=&amp;quot;This is a test&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;set-textcommand&amp;quot;&amp;gt;textCommand&amp;lt;/code&amp;gt;&lt;br /&gt;
:Sendet ein Text-Kommando an Rhasspy.&lt;br /&gt;
:&#039;&#039;&#039;Example:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; textCommand schalte das licht ein&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;set-trainrhasspy&amp;quot;&amp;gt;trainRhasspy&amp;lt;/code&amp;gt;&lt;br /&gt;
:Startet das Training von Rhasspy.&lt;br /&gt;
:&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; trainRhasspy&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;set-update&amp;quot;&amp;gt;update&amp;lt;/code&amp;gt;&lt;br /&gt;
:;&amp;lt;code id=&amp;quot;set-update-devicemap&amp;quot;&amp;gt;devicemap&amp;lt;/code&amp;gt;&lt;br /&gt;
::Wenn an der Konfiguration von RHASSPY oder an den von ihm gesteuerten Geräten etwas geändert wurde, muss dieser Befehl ausgeführt werden, um die Datenstruktur von RHASSPY zu aktualisieren, Rhasspy von den Änderungen zu informieren (Slots z.B.), ein Training zu starten, etc.&lt;br /&gt;
::&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update devicemap&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:;&amp;lt;code id=&amp;quot;set-update-devicemaponly&amp;quot;&amp;gt;devicemap_only&amp;lt;/code&amp;gt;&lt;br /&gt;
::Aktualisiert die Datenstruktur von RHASSPY. Es werden weder Slots in Rhasspy geändert, noch das Training gestartet.&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update devicemap_only&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:;&amp;lt;code id=&amp;quot;set-update-slots&amp;quot;&amp;gt;slots&amp;lt;/code&amp;gt;&lt;br /&gt;
::Aktualisiert (bzw. erstellt) alle Slots in Rhasspy mit den aktuellen Geräten, Räumen, usw.&lt;br /&gt;
::Erstellte/Aktualisierte Slots sind z.B.:&lt;br /&gt;
::*de.fhem.AllKeywords&lt;br /&gt;
::*de.fhem.Device&lt;br /&gt;
::*de.fhem.Device-&#039;&#039;genericDeviceType&#039;&#039;&lt;br /&gt;
::*de.fhem.Device-&#039;&#039;Intent&#039;&#039;&lt;br /&gt;
::*de.fhem.Group&lt;br /&gt;
::*de.fhem.Room&lt;br /&gt;
::*de.fhem.MediaChannels&lt;br /&gt;
::*de.fhem.Color&lt;br /&gt;
::*de.fhem.NumericType&lt;br /&gt;
::(Hinweis: Die ersten beiden Teile &#039;&#039;de&#039;&#039; und &#039;&#039;fhem&#039;&#039; hängen von der DEF des RHASSPY-Devices ab)&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update slots&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:;&amp;lt;code id=&amp;quot;set-update-slotsnotraining&amp;quot;&amp;gt;slots_no_training&amp;lt;/code&amp;gt;&lt;br /&gt;
::Wie &amp;lt;code&amp;gt;slots&amp;lt;/code&amp;gt;, aber ohne Training nach dem Update.&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update slots_no_training&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:;&amp;lt;code id=&amp;quot;set-update-language&amp;quot;&amp;gt;language&amp;lt;/code&amp;gt;&lt;br /&gt;
::Liest das das Sprach-File (&#039;&#039;languageFile&#039;&#039;) neu ein.&lt;br /&gt;
::Muss immer ausgeführt werden, wenn in diesem File oder dem Attribut &#039;&#039;languageFile&#039;&#039; etwas geändert wurde!&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update language&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:;&amp;lt;code id=&amp;quot;set-udpate-intentfilter&amp;quot;&amp;gt;intent_filter&amp;lt;/code&amp;gt;&lt;br /&gt;
::Setzt die Intent Filter, die vom Rhasspy Dialogue Manger verwendet werden zurück. Details dazu bei [[#attr-rhasspytweaks-intentfilter|intentFilter]] im &#039;&#039;rhasspyTweaks&#039;&#039;-Attribut.&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update intent_filter&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:;&amp;lt;code id=&amp;quot;set-update-all&amp;quot;&amp;gt;all&amp;lt;/code&amp;gt;&lt;br /&gt;
::Aktualisiert die Devicemap und das languageFile&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update all&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;set-volume&amp;quot;&amp;gt;volume&amp;lt;/code&amp;gt;&lt;br /&gt;
::Stellt die Lautstärke der gewünschten siteId auf einen Wert zwischen 0 and 1 (float).&lt;br /&gt;
::Beide Argumente &amp;lt;code&amp;gt;siteId&amp;lt;/code&amp;gt; &amp;lt;code&amp;gt;volume&amp;lt;/code&amp;gt; sind verpflichtend.&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; siteId=&amp;quot;default&amp;quot; volume=&amp;quot;0.5&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|Bitte nicht vergessen, dass nach jeder Änderung an RHASSPY oder an einem von RHASSPY gesteuerten Gerät ein &amp;lt;code&amp;gt;update devicemap&amp;lt;/code&amp;gt; ausgeführt werden muss!}}&lt;br /&gt;
&lt;br /&gt;
==Attribute (ATTR)==&lt;br /&gt;
Um RHASSPY zum Laufen zu bringen, müssen unterschiedliche Attribute gesetzt werden. Dabei gibt es&lt;br /&gt;
*Attribute, die im RHASSPY-Device selbst gesetzt werden müssen und&lt;br /&gt;
*Attribute, die in den Devices gesetzt werden müssen, die von RHASSPY kontrolliert werden sollen.&lt;br /&gt;
&lt;br /&gt;
Letztere werden im Abschnitt [[#FHEM-Devices für die Verwendung mit Rhasspy konfigurieren|FHEM-Devices für die Verwendung mit Rhasspy konfigurieren]] behandelt.&lt;br /&gt;
&lt;br /&gt;
In diesem Abschnitt werden die Attribute behandelt, die auf das RHASSPY-Device selbst wirken.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;attr-iodev&amp;quot;&amp;gt;IODev&amp;lt;/code&amp;gt;&lt;br /&gt;
:Das MQTT2_CLIENT Device, welches die MQTT-Nachrichten für RHASSPY liefert.&lt;br /&gt;
:&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;attr &amp;lt;rhasspyDevice&amp;gt; IODev rhasspyMQTT2&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;attr-forcenext&amp;quot;&amp;gt;forceNext&amp;lt;/code&amp;gt;&lt;br /&gt;
:Wenn dieses Attribut auf 1 gesetzt ist, leitet RHASSPY eingehende MQTT-Nachrichten an andere MQTT2-IO-Client Module wie MQTT2_DEVICE weiter, auch wenn das Topic zu einem von RHASSPY abonnierten passt.&lt;br /&gt;
:Standardmäßig werden diese Nachrichten nicht weitergeleitet um eine bessere Kompatibilität mit dem &#039;&#039;autocreate&#039;&#039;-Feature des MQTT2_DEVICE sicher zu stellen.&lt;br /&gt;
:Siehe dazu das {{Link2CmdRef|Anker=MQTT2_CLIENT-attr-clientOrder|Lang=en|Label=clientOrder}}-Attribut in der CommandRef zum MQTT2_CLIENT Device.&lt;br /&gt;
:Das Setzen dieses Attributs in einer RHASSPY-Instanz kann auch andere eventuell vorhandene RHASSPY-Instanzen beinflussen.&lt;br /&gt;
:Default ist &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;attr &amp;lt;rhasspyDevice&amp;gt; forceNext 1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;attr-languagefile&amp;quot;&amp;gt;languageFile&amp;lt;/code&amp;gt;&lt;br /&gt;
:Pfad zur Sprach-Datei&lt;br /&gt;
:Ist dieses Argument nicht gesetzt, wird ein Standard-Set an englischen Sätzen für die Sprachantworten verwendet.&lt;br /&gt;
:Die Datei selbst muss ein gültiges JSON-File sein, dass sich nach der Struktur aus den englischen Standardwerten richtet.&lt;br /&gt;
:Eine deutsche Beispiel-Datei ist in [https://svn.fhem.de/trac/browser/trunk/fhem/contrib/RHASSPY/rhasspy-de.cfg SVN] und [https://github.com/fhem/fhem-rhasspy/blob/dev/FHEM/rhasspy-de.cfg GitHub] vorhanden. Man kann aber einfach ein Dump der englischen Struktur machen (replace RHASSPY by your device&#039;s name: &amp;lt;code&amp;gt;{toJSON($defs{RHASSPY}-&amp;gt;{helper}{lng})}&amp;lt;/code&amp;gt;, das Ergebnis dann bearbeiten und es als eigenes languageFile verwenden.&lt;br /&gt;
:Im Standard-Set sind auch einige Variablen enthalten. Auch die können im eigenen File verwendet werden.&lt;br /&gt;
:languageFile erlaubt auch eine Kombination aus vorhandenen und eigenen Sätzen. Dazu können die eigenen Sätzen einfach im Sub-Tree &#039;&#039;user&#039;&#039; abgelegt werden.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Beispiel:&#039;&#039;&#039; (vorausgesetzt, die Sprach-Datei ist im selben Verzeichnis wie fhem.pl):&lt;br /&gt;
:&amp;lt;code&amp;gt;attr &amp;lt;rhasspyDevice&amp;gt; languageFile ./rhasspy-de.cfg&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;attr-response&amp;quot;&amp;gt;response&amp;lt;/code&amp;gt;&lt;br /&gt;
:&#039;&#039;&#039;Hinweis:&#039;&#039;&#039;: Die Verwendung dieses Attributs ist nicht mehr empfohlen. Bessere Alternative ist die Sprach-Datei.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Mit diesem Attribut können eigene Standardantworten definiert werden.&lt;br /&gt;
Mögliche Schlüsselwörter sind &amp;lt;code&amp;gt;DefaultError&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;NoActiveMediaDevice&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;DefaultConfirmation&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;DefaultError=&lt;br /&gt;
DefaultConfirmation=Klaro, mach ich&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;attr-rhasspyhotwords&amp;quot;&amp;gt;rhasspyHotwords&amp;lt;/code&amp;gt;&lt;br /&gt;
:Kann verwendet werden, um benutzerdefinierte Aktionen auszuführen, sobald ein bestimmtes Hotword erkannt wurde. Dazu sind keine speziellen Konfigurationsschritte in anderen FHEM Devices notwendig.&lt;br /&gt;
:Wenn mittels Attribut oder DEF aktiviert, wird ein Reading &#039;&#039;hotword&#039;&#039; erstellt und mit dem erkannten Hotword und der siteId befüllt um ein Event-Handling zu ermöglichen.&lt;br /&gt;
:&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Da bei den hotword messages für alle Teilnehmer dieselbe Topic-Structur verwendet wird, kann RHASSPY nicht unterscheiden, ob eine solche für diese Instanz relevant ist. Falls entsprechende Unterscheidungen gemacht werden sollen, muss dies vom User entsprechend konfiguriert werden, z.B. indem die subscriptions (am MQTT2_CLIENT) eingeschränkt werden oder indem nur jeweils andere hotword-Einträge für jede RHASSPY-Instanz genutzt werden.&lt;br /&gt;
:Ein Hotword pro Zeile, Syntax entweder einfach oder erweitert&lt;br /&gt;
 &lt;br /&gt;
:&#039;&#039;&#039;Beispiele:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;bumblebee_linux = set amplifier2 mute on&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;porcupine_linux = livingroom=&amp;quot;set amplifier mute on&amp;quot; default={Log3($DEVICE,3,&amp;quot;device $DEVICE - room $ROOM - value $VALUE&amp;quot;)}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Im ersten Beispiel wird der Befehl immer ausgeführt, wenn das Hotword &#039;&#039;bumblebee_linux&#039;&#039; erkannt wurde.&lt;br /&gt;
:Im zweiten nur, wenn das Hotword &#039;&#039;porcupine_linux&#039;&#039; in der siteId &#039;&#039;livingroom&#039;&#039; erkannt wurde.&lt;br /&gt;
:$DEVICE wird ausgewertet als der Name des RHASSPY Devices, $ROOM als siteId und $VALUE als das verwendete Hotword.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;attr-rhasspyintents&amp;quot;&amp;gt;rhasspyIntents&amp;lt;/code&amp;gt;&lt;br /&gt;
:Definiert einen benutzerdefinierten Intent.&lt;br /&gt;
:Ein Intent pro Zeile.&lt;br /&gt;
:&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;attr &amp;lt;rhasspyDevice&amp;gt; rhasspyIntents SetCustomIntentsTest=SetCustomIntentsTest(siteId,Type)&amp;lt;/code&amp;gt;&lt;br /&gt;
:in Kombination mit folgendem myUtils-Code&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub SetCustomIntentsTest {&lt;br /&gt;
my $room = shift;&lt;br /&gt;
my $type = shift;&lt;br /&gt;
Log3(&#039;rhasspy&#039;,3 , &amp;quot;RHASSPY: Room $room, Type $type&amp;quot;);&lt;br /&gt;
return &amp;quot;RHASSPY: Room $room, Type $type&amp;quot;;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
:schreibt einen Log-Eintrag nach jedem Aufruf dieses Intents.&lt;br /&gt;
:Die folgenden Argumente können dabei übergeben werden:&lt;br /&gt;
:*NAME =&amp;gt; Name des RHASSPY-Devices&lt;br /&gt;
:*DATA =&amp;gt; komplette JSON-$data (wie intern geparsed), in JSON kodiert&lt;br /&gt;
:*siteId, Device etc. =&amp;gt; jedes Element, das in JSON-$data existiert&lt;br /&gt;
:Wird von der Funktion ein einfacher Text zurück geliefert, wird dieser als &#039;&#039;response&#039;&#039; angesehen. Wenn der Rückgabewert nicht definiert ist, wird die Standard-&#039;&#039;response&#039;&#039; verwendet.&lt;br /&gt;
:Es kann aber auch ein HASH oder ARRAY übergeben werden.&lt;br /&gt;
:Im Falle eines ARRAYs wird das erste Element als &#039;&#039;response&#039;&#039; interpretiert und kann ein reiner Text sein, womit der Dialog beendet wird. Ist das erste Element ein HASH wird die Dialog-Session fortgesetzt. Eine offene Dialog-Session wird per Default nach 20 Sekunden beendet. Diese Zeitspanne kann aber auch geändert werden, in dem im ARRAY als zweiter Wert eine Zahl übergeben wird. Das zweite Element kann aber auch eine komma-getrennte Liste an Geräten sein, die geändert (geschalten) wurden. Das dient dazu, damit die Geräte auch Events liefern, was ansonsten nicht der Fall wäre. Siehe dazu den &amp;quot;d&amp;quot;-Parameter beim Attribut [[#attr-rhasspyshortcuts|rhasspyShortcuts]].&lt;br /&gt;
:Wird eine HASH-Datenstruktur (ggf. in $response innerhalb einer ARRAY-Struktur), um einen laufenden Dialog fortzusetzen, muss sichergestellt werden, dass alle erforderlichen Datenelemente enthalten sind, insbesondere &#039;&#039;intentFilter&#039;&#039;, falls die für den weiteren Dialog relevanten Intents eingeschränkt (oder erweitert) werden sollen. Dabei sollte möglichst der Intent &#039;&#039;CancelAction&#039;&#039; aktiv gehalten werden, damit der User die Option hat, den Dialog jederzeit aktiv zu beenden.&lt;br /&gt;
:Siehe dazu auch den Abschnitt [[#Eigene Intents erstellen]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;attr-rhasspyshortcuts&amp;quot;&amp;gt;rhasspyShortcuts&amp;lt;/code&amp;gt;&lt;br /&gt;
:Hiermit können benutzerdefinierte Sätze erstellt werden ohne die sentences.ini in Rhasspy bearbeiten zu müssen.&lt;br /&gt;
:Diese Shortcuts werden zu Rhasspy hochgeladen, sobald das &amp;lt;code&amp;gt;updateSlots&amp;lt;/code&amp;gt; [[#set-update|Set]]-Kommando ausgeführt wird.&lt;br /&gt;
:Ein Shortcut pro Zeile, Syntax ist entweder einfach oder erweitert.&lt;br /&gt;
:&#039;&#039;&#039;Beispiele:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;mute on=set amplifier2 mute on&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;lamp off={fhem(&amp;quot;set lampe1 off&amp;quot;)}&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;i=&amp;quot;du bist cool&amp;quot; f=&amp;quot;set $NAME speak siteId=&#039;livingroom&#039; text=&#039;danke dir! du bist noch viel cooler!&#039;&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;i=&amp;quot;schalte den ton aus&amp;quot; p={fhem (&amp;quot;set $NAME mute off&amp;quot;)} n=amplifier2 c=&amp;quot;soll ich den ton wirklich ausschalten?&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;i=&amp;quot;ich hab hunger&amp;quot; f=&amp;quot;set Herd on&amp;quot; d=&amp;quot;Herd&amp;quot; c=&amp;quot;möchtest du schweinsbraten?&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
:Erklärung zu den Abkürzungen:&lt;br /&gt;
:*&amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt; =&amp;gt; intent&lt;br /&gt;
::Zeilen, die mit &amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt; beginnen, werden als erweiterte Syntax interpretiert. Soll die erweiterte Syntax verwendet werden, ist das &amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt; also Pflicht!&lt;br /&gt;
:*&amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; =&amp;gt; FHEM Befehl&lt;br /&gt;
::Syntax wie von der FHEM Kommandozeile gewohnt&lt;br /&gt;
:*&amp;lt;code&amp;gt;p&amp;lt;/code&amp;gt; =&amp;gt; Perl Befehl&lt;br /&gt;
::Syntax wie von der FHEM Kommandozeile gewohnt, eingerahmt in geschwungenen Klammern (&amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt;). &amp;lt;code&amp;gt;p&amp;lt;/code&amp;gt; hat Vorrang vor &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt;&lt;br /&gt;
:*&amp;lt;code&amp;gt;d&amp;lt;/code&amp;gt; =&amp;gt; Device Name(en, Komma getrennt)&lt;br /&gt;
::Device Name(n), die an fhem.pl als upgedated übergeben werden sollen. Das wird benötigt um weitere Aktionen in FHEM und das Longpolling zu triggern.&lt;br /&gt;
::Hinweis: Wenn Perl-Funktionen aufgerufen werden, wird der Rückgabewert dieser Funktion verwendet, sofern kein explizites Device angegeben ist.&lt;br /&gt;
:*&amp;lt;code&amp;gt;r&amp;lt;/code&amp;gt; =&amp;gt; Response&lt;br /&gt;
::Sprachanwort, die ausgegeben wird. Ist &amp;lt;code&amp;gt;r&amp;lt;/code&amp;gt; nicht gesetzt, wird der Rückgabewert der aufgerufenen Funktion verwendet.&lt;br /&gt;
::In den Antwortsätze werden &#039;&#039;set magic&#039;&#039;-ähnliche Ersetzungen verarbeitet. Es ist also auch eine Zeile wie &amp;lt;code&amp;gt;i=&amp;quot;what&#039;s the time for sunrise&amp;quot; r=&amp;quot;at [Astro:SunRise] o&#039;clock&amp;quot;&amp;lt;/code&amp;gt; gültig.&lt;br /&gt;
::Mit den folgenden Abkürzungen kann auch nach einer Bestätigung für den Befehl gefragt werden:&lt;br /&gt;
::*&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt; =&amp;gt; Entweder Zahl oder Text. Wenn Zahl, wird sie als Timeout für den Abbruch des Dialogs behandelt. Wenn Text wird dieser als Sprachausgabe zur Bestätigung verwendet.&lt;br /&gt;
::*&amp;lt;code&amp;gt;ct&amp;lt;/code&amp;gt; =&amp;gt; Numerischer Wert für das Timeout des Dialogs in Sekunden. Default ist &amp;lt;code&amp;gt;15&amp;lt;/code&amp;gt;.&lt;br /&gt;
::Siehe [[#attr-rhasspytweaks-confirmintents|hier]] für weitere Informationen zu Bestätigungen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;attr-rhasspytweaks&amp;quot;&amp;gt;rhasspyTweaks&amp;lt;/code&amp;gt;&lt;br /&gt;
Mit diesen Einstellungen können benutzerdefinierte Optimierungen an RHASSPY vorgenommen werden.&lt;br /&gt;
&lt;br /&gt;
:*&amp;lt;code id=&amp;quot;attr-rhasspytweaks-timerlimits&amp;quot;&amp;gt;timerLimits&amp;lt;/code&amp;gt;&lt;br /&gt;
::Wird verwendet um den Timer anzuweisen mit z.B. &amp;quot;gestellt auf 30 Minuten&amp;quot; oder &amp;quot;gestellt auf 10:30&amp;quot; zu antworten&lt;br /&gt;
::&amp;lt;code&amp;gt;timerLimits=90,300,3000,2*HOURSECONDS,50&amp;lt;/code&amp;gt;&lt;br /&gt;
::Hierbei müssen fünf Werte gesetzt werden, die den Zeitgrenzen für Stufen in der Antwortstruktur &#039;&#039;timerSet&#039;&#039; entsprechen.&lt;br /&gt;
::Obiges Beispiel also würde dazu führen, unter einer eingestellten Zeit von 90 Sekunden mit der Sekundenangabe geantwortet wird. In Minuten und Sekunden solange der Timer kürzer als 300 Sekunden ist. Usw. Der letzte Wert ist das Limit in Sekunden, wenn der Timer im &amp;quot;Uhrzeit&amp;quot;-Format gestellt ist.&lt;br /&gt;
&lt;br /&gt;
:*&amp;lt;code id=&amp;quot;attr-rhasspytweaks-timersounds&amp;quot;&amp;gt;timerSounds&amp;lt;/code&amp;gt;&lt;br /&gt;
::Standardmäßig antwortet der Timer mit einer Sprachnachricht, wenn er abgelaufen ist. Soll lieber eine WAV-Datei verwendet werden, kann das hier eingestellt werden.&lt;br /&gt;
::&amp;lt;code&amp;gt;timerSounds= default=./yourfile1.wav eier=3:20:./yourfile2.wav kartoffeln=5:./yourfile3.wav&amp;lt;/code&amp;gt;&lt;br /&gt;
::Die Keys in dieser Code-Zeile sind Beispiele und deren Name - bis auf &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; frei wählbar. Der Name muss aber zu den &#039;&#039;Label&#039;&#039;-Tags für die Timer in den Rhasspy-Sentences passen.&lt;br /&gt;
::&amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; ist optional. Wenn gesetzt, wird dieses WAV-File für alle benannten Timer verwendet, für die kein Keyword in der Konfiguration ist.&lt;br /&gt;
::Die beiden Nummern sind optional. Die erste legt fest, wie oft die WAV-Datei wiederholt werden soll (Default: 5). Die zweite definiert die Pause in Sekunden zwischen den Wiederholungen (Default: 15). Ist nur eine Zahl gesetzt, wird diese als gewünschte Anzahl an Wiederholungen interpretiert.&lt;br /&gt;
&lt;br /&gt;
:*&amp;lt;code id=&amp;quot;attr-rhasspytweaks-updateslots&amp;quot;&amp;gt;updateSlots&amp;lt;/code&amp;gt;&lt;br /&gt;
::Ändert diverse Aspekte des Erstellens und Updatens von Slots&lt;br /&gt;
::*&amp;lt;code&amp;gt;noEmptySlots=1&amp;lt;/code&amp;gt;&lt;br /&gt;
:::Per Default generiert RHASSPY einen zusätzlichen Slot für jeden &#039;&#039;genericDeviceType&#039;&#039;, der erkannt wird. Unabhängig davon, ob er bei einem Gerät gesetzt ist. Das kann zu leeren Slots führen.&lt;br /&gt;
:::Ist der Wert &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;, werden keine leeren Slots erstellt.&lt;br /&gt;
::*&amp;lt;code&amp;gt;overwrite_all=false&amp;lt;/code&amp;gt;&lt;br /&gt;
:::RHASSPY überschreibt alle vorhandenen Slots wenn ein &amp;lt;code&amp;gt;updateSlots&amp;lt;/code&amp;gt; ausgeführt wird. Ist das nicht gewünscht, muss dieser Wert auf &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; gesetzt werden.&lt;br /&gt;
::*&amp;lt;code&amp;gt;timeouts&amp;lt;/code&amp;gt;&lt;br /&gt;
:::Die Keywörter &amp;lt;code&amp;gt;confirm&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; können verwendet werden, um das Standard-Timeouts (15s/20s) für Dialoge zu ändern.&lt;br /&gt;
:::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:::&amp;lt;code&amp;gt;timeouts: confirm=25 default=30&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:*&amp;lt;code id=&amp;quot;attr-rhasspytweaks-confirmintents&amp;quot;&amp;gt;confirmIntents&amp;lt;/code&amp;gt;&lt;br /&gt;
::Hiermit kann eingestellt werden, dass für bestimmte Intents immer ein Bestätigung erfragt wird. Unterstützt werden derzeit alle &amp;quot;set-&amp;quot;-Intents.&lt;br /&gt;
::Dazu werden &amp;lt;code&amp;gt;Intent&amp;lt;/code&amp;gt;=&amp;lt;code&amp;gt;regex&amp;lt;/code&amp;gt;-Paare verwendet.&lt;br /&gt;
:::&amp;lt;code&amp;gt;Intent&amp;lt;/code&amp;gt; ist der Name des gewünschten Intents&lt;br /&gt;
:::&amp;lt;code&amp;gt;regex&amp;lt;/code&amp;gt; ist eine Regex, die eine bestimmte Gruppe (für Gruppen-Intents) oder einen bestimmten Device-Namen beschreiben muss.&lt;br /&gt;
:::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:::&amp;lt;code&amp;gt;confirmIntents=SetOnOffGroup=light|blinds SetOnOff=blind.*&amp;lt;/code&amp;gt;&lt;br /&gt;
::Befehle werden nur nach einer positiven Bestätigung ausgeführt. Das bedeutet, es muss unbedingt ein &amp;lt;code&amp;gt;Mode:OK&amp;lt;/code&amp;gt;-Wert vom &#039;&#039;ConfirmAction&#039;&#039;-Intent gesendet werden. Jede andere Wert für &amp;lt;code&amp;gt;Mode&amp;lt;/code&amp;gt; wird als Abbruch gewertet. Es kann aber auch der eigene Intent &#039;&#039;CancelAction&#039;&#039; für den Abbruch verwendet werden.&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:ConfirmAction]&lt;br /&gt;
( yes, please do it | go on | that&#039;s ok | yes, please ){Mode:OK}&lt;br /&gt;
( don&#039;t do it after all ){Mode}&lt;br /&gt;
&lt;br /&gt;
[de.fhem:CancelAction]&lt;br /&gt;
( let it be | oh no | cancel | cancellation ){Mode:Cancel}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:*&amp;lt;code id=&amp;quot;attr-rhasspytweaks-confirmintentresponses&amp;quot;&amp;gt;confirmIntentResponses&amp;lt;/code&amp;gt;&lt;br /&gt;
::Üblicherweise ist die Bestätigungs-Frage ein &amp;quot;Echo&amp;quot; des ursprünglich gesprochenen Befehls. Dies kann für jeden Intent geändert werden,&lt;br /&gt;
::Dies kann für jeden Intent individuell angepaßt werden, wobei die Variablen $target, ($rawInput) und $Value verwendet werden können.&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;confirmIntentResponses=SetOnOffGroup=&amp;quot;wirklich die Gruppe $target $Value schalten&amp;quot; SetOnOff=&amp;quot;bestätige dass $target $Value geschaltet werden soll&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
::&amp;lt;code&amp;gt;$Value&amp;lt;/code&amp;gt; wird dabei mit den defaults aus dem &#039;&#039;words&#039;&#039; key in der languageFile übersetz (falls vorhanden). Weitere Optionen für Ersetzungen von &amp;lt;code&amp;gt;$Value&amp;lt;/code&amp;gt; sind für einzelne Devices über den [[#attr-rhasspyspecials-confirmvaluemap|confirmValueMap]] key im Attribut &#039;&#039;rhasspySpecials&#039;&#039; verfügbar.&lt;br /&gt;
&lt;br /&gt;
:*&amp;lt;code id=&amp;quot;attr-rhasspytweaks-intentfilter&amp;quot;&amp;gt;intentFilter&amp;lt;/code&amp;gt;&lt;br /&gt;
::Rhasspy aktiviert bei jedem Neustart alle ihm bekannten Intents. Da manche der von FHEM genutzten Intents nur in bestimmten Situationen (v.a. innerhalb offener Dialoge) benötigt werden, deaktiviert RHASSPY diese (derzeit: ConfirmAction, CancelAction, ChoiceRoom und ChoiceDevice beim Start, sowie jedes Mal, wenn erkannt wird, dass das Standardfiltering nicht wie erwartet funktioniert (was v.a. bei einem zwischenzeitlichen Rhasspy-Neustart der Fall sein kann). Über diesen Tweak können weitere Intents mit in diese automatisierte (De-) Aktivierung mit einbezogen werden. Entweder ist dabei einfach der Name (ohne die Zusätze aus &#039;&#039;language&#039;&#039; und &#039;&#039;fhemId&#039;&#039; anzugeben, oder eine explizite Anweisung zum ein- und Ausschalten (in der Form &amp;lt;code&amp;gt;intentname=true&amp;lt;/code&amp;gt;). Die 4 vorgenannten Standard-Intents können nicht über diesen Weg aktiviert werden. Details zur intern genutzten Rhasspy-Funktionalität sind in der [https://rhasspy.readthedocs.io/en/latest/reference/#dialogue-manager Rhasspy-Dokumentation] zu finden.&lt;br /&gt;
&lt;br /&gt;
:*&amp;lt;code id=&amp;quot;attr-rhasspytweaks-ignorekeywords&amp;quot;&amp;gt;ignoreKeywords&amp;lt;/code&amp;gt;&lt;br /&gt;
::Da in manchen der von RHASSPY automatisch ausgewerteten Attribute häufig auch eher technisch motivierte Angaben zu finden sind, kann über diesen Schlüssel verhindert werden, dass derartige Angaben bei der slot-Erstellung übergangen werden. Dies betrifft z.B. häufig anzutreffende &#039;&#039;room&#039;&#039;-Werte wie &#039;&#039;MQTT&#039;&#039;, &#039;&#039;alexa&#039;&#039;, &#039;&#039;homebridge&#039;&#039; oder &#039;&#039;googleassistant&#039;&#039;. Die hier angegebenen key-value-Paare werden als Negativ-Filter für die angegebenen Werte verwendet (derzeit nur für &#039;&#039;rooms&#039;&#039; und &#039;&#039;group&#039;&#039;). &#039;&#039;value&#039;&#039; wird dabei als (case-insensitive) regex behandelt, verglichen wird auf exakten match (es müssen also ggf. vorne bzw. hinten &#039;&#039;.*&#039;&#039; angefügt werden).&lt;br /&gt;
::Dieses &#039;&#039;&#039;Beispiel&#039;&#039;&#039; filtert daher die o.g. Räume aus und dazu noch die strukturierten Unterräume unterhalb &#039;&#039;Steuerung&#039;&#039;:&lt;br /&gt;
::&amp;lt;code&amp;gt;ignoreKeywords=rooms=mqtt.*|alexa|homebridge|googleassistant|steuerung-.&amp;lt;/code&amp;gt;&lt;br /&gt;
:* &amp;lt;code id=&amp;quot;attr-rhasspytweaks-ignorekeywords&amp;quot;&amp;gt;gdt2groups&amp;lt;/code&amp;gt;  Dieser Eintrag ermöglicht es, alle Geräte eines generichDeviceType innerhalb der automatischen Erfassung automatisch einer oder mehreren Gruppen zuzuordnen. Die Vorgaben in diesem Eintrag werden nicht übernommen, wenn am jeweiligen Einzelgerät  das Attribut &#039;&#039;rhasspyGroup&#039;&#039; gesetzt ist.  Hier eine deutschsprachige Vorbelegung als &#039;&#039;&#039;Beispiel&#039;&#039;&#039;: &amp;lt;code&amp;gt;gdt2groups= blind=rollläden,rollladen thermostat=heizkörper light=lichter,leuchten&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Readings / Events==&lt;br /&gt;
;&amp;lt;code&amp;gt;IODev&amp;lt;/code&amp;gt;&lt;br /&gt;
:Das eingestellte IO-Device&lt;br /&gt;
;&amp;lt;code&amp;gt;intents&amp;lt;/code&amp;gt;&lt;br /&gt;
:Eine Liste der in Rhasspy vorhandenen Intents&lt;br /&gt;
;&amp;lt;code&amp;gt;lastIntentPayload&amp;lt;/code&amp;gt;&lt;br /&gt;
:Inhalt des letzten Intents der von FHEM empfangen wurde&lt;br /&gt;
;&amp;lt;code&amp;gt;lastIntentTopic&amp;lt;/code&amp;gt;&lt;br /&gt;
:Das MQTT-Topic des letzten Intents&lt;br /&gt;
;&amp;lt;code&amp;gt;listening_roomname&amp;lt;/code&amp;gt;&lt;br /&gt;
:Ein Reading für jeden Raum bzw. jede siteId&lt;br /&gt;
:Wechselt auf 1 sobald ein Hotword erkannt wurde und zurück auf 0, sobald die Dialog-Session beendet ist.&lt;br /&gt;
:Kann z.B. verwendet werden, um den Ton eines TVs auszuschalten, während Rhasspy auf ein Kommando hört.&lt;br /&gt;
;&amp;lt;code&amp;gt;mute_roomname&amp;lt;/code&amp;gt;&lt;br /&gt;
:Zeigt an, ob ein Raum / eine siteId vom Intent &#039;&#039;SetMute&#039;&#039; stumm geschalten wurde und somit keine Befehle ausführt.&lt;br /&gt;
:Jeweils ein Reading für jede siteId.&lt;br /&gt;
:Default ist 0.&lt;br /&gt;
;&amp;lt;code&amp;gt;responseType&amp;lt;/code&amp;gt;&lt;br /&gt;
:Der Typ der letzten Antwort (text/voice).&lt;br /&gt;
:voiceResponse and textResponse&lt;br /&gt;
:Antwort auf das letzte Sprach-/Text-Kommando.&lt;br /&gt;
;&amp;lt;code&amp;gt;siteIds&amp;lt;/code&amp;gt;&lt;br /&gt;
:Listet alle siteIds auf.&lt;br /&gt;
:Kann mit [[#set-fetchsiteids|fetchSiteIds]] aktualisiert werden.&lt;br /&gt;
;&amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;&lt;br /&gt;
:Zeigt an ob RHASSPY mit Rhasspy verbunden ist&lt;br /&gt;
;&amp;lt;code&amp;gt;training&amp;lt;/code&amp;gt;&lt;br /&gt;
:Letzte zurückgelieferte Antwort auf einen [[#set-trainrhasspy|trainRhasspy]]-Befehl.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
;&amp;lt;code&amp;gt;updateSentences&amp;lt;/code&amp;gt;&lt;br /&gt;
:Letzte zurückgelieferte Antwort nach einem [[#set-update-slots|updateSlots]]-Befehl.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
;&amp;lt;code&amp;gt;updateSlots&amp;lt;/code&amp;gt;&lt;br /&gt;
:Letzte zurückgelieferte Antwort nach einem [[#set-update-slots|updateSlots]]-Befehl.&lt;br /&gt;
;&amp;lt;code&amp;gt;hotword&amp;lt;/code&amp;gt;&lt;br /&gt;
:Wenn aktiviert, beinhaltet dieses Reading das letzte verwendete Hotword und von welcher siteId es aufgerufen wurde.&lt;br /&gt;
;&amp;lt;code&amp;gt;voiceResponse&amp;lt;/code&amp;gt;&lt;br /&gt;
:Letze Sprach-Antwort auf einen Sprach-Befehl&lt;br /&gt;
&lt;br /&gt;
=== Benutzerdefinierte Readings ===&lt;br /&gt;
&lt;br /&gt;
There are some readings you may find useful to tweak some aspects of RHASSPY&#039;s logics:&lt;br /&gt;
*&amp;lt;code&amp;gt;siteId2room_&amp;lt;/code&amp;gt; Falls keine explizite Raum-Information in den an RHASSPY weitergegebenen Daten enthalten ist, ermittelt das Modul den Raum in der Regel aus dem Namen der &#039;&#039;siteId&#039;&#039;. So werden z.B. alle raumlosen Anweisungen von einem Satelliten names &#039;&#039;schlafzimmer&#039;&#039;, im Raum &#039;&#039;schlafzimmer&#039;&#039; ausgeführt werden (wenn möglich). Die Gruppenfunktion von Rhasspy wird unterstützt, so wird z.B. &#039;&#039;wohnzimmer.vorne&#039;&#039; ebenfalls automatisch dem Raum &#039;&#039;wohnzimmer&#039;&#039; zugeordnet. Über passende Angaben in &#039;&#039;siteId2room-Readings&#039;&#039; kann dieses Verhalten modifiziert werden:  &amp;lt;code&amp;gt;setreading siteId2room_mobile_phone1 wohnzimmer&amp;lt;/code&amp;gt; wird RHASSPY veranlassen, den Satelliten  &#039;&#039;mobile_phone1&#039;&#039; dem Raum &#039;&#039;wohnzimmer&#039;&#039; zuzuweisen. Hierzu ist in &#039;&#039;contrib&#039;&#039; auch eine Hilfsfunktion zu finden, mit der mobilen Satelliten per Sprachbefehl einem neuen Raum zugewiesen werden können.&lt;br /&gt;
*&amp;lt;code&amp;gt;siteId2doubleSpeak_&amp;lt;/code&amp;gt; RHASSPY antwortet immer über den Satelliten, von dem die jeweilige Sprachanweisung kam. Manchmal kann es erwünscht sein, zusätzliche Sprachrückmeldungen an einen weiteren Satelliten zu geben - z.B. weil der betreffende Lautsprecher (zeitweise) ausgeschaltet ist. Ist ein entsprechendes Reading gesetzt, erfolgen (zusätzliche!) Sprachausgaben an den dort als Readingwert angegebenen zweiten Satelliten; das Namensschema der Readings entspricht dem für site2room.&lt;br /&gt;
&lt;br /&gt;
== FHEM-Devices für die Verwendung mit Rhasspy konfigurieren ==&lt;br /&gt;
Um ein Gerät mit Rhasspy steuern zu können, muss Rhasspy einige Details über das Gerät kennen. Diese werden bekannt gemacht, in dem bei den Geräten Attribute gesetzt werden, die anschließend vom RHASSPY-Modul ausgewertet und an Rhasspy gesendet werden.&lt;br /&gt;
&lt;br /&gt;
Der einfachste - und empfohlene - Weg, dies zu erreichen, ist durch Setzen des Attributs &#039;&#039;&#039;&#039;&#039;genericDeviceType&#039;&#039;&#039;&#039;&#039;. Das Modul erkennt dann die möglichen Schalt - und Abfragemöglichkeiten des Gerätes automatisch.&lt;br /&gt;
&lt;br /&gt;
Sollte &#039;&#039;genericDeviceType&#039;&#039; (gDT) nicht ausreichen, gibt es noch weitere Attribute, die stattdessen oder ergänzend dazu verwendet werden können (z.b. rhasspyName, rhasspyRoom, ...). Die Namen dieser Attribute beginnen alle mit dem &#039;&#039;prefix&#039;&#039;, das in der DEF des RHASSPY-Moduls gesetzt wurde. Diese Dokumentation verwendet das Prefix &amp;lt;code&amp;gt;rhasspy&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Sind sowohl &#039;&#039;genericDeviceType&#039;&#039; als auch Spezial-Attribute vorhanden, werden die von gDT gesammelten Möglichkeiten durch die der Spezial-Attribute überschrieben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Wichtig:&#039;&#039;&#039;&lt;br /&gt;
*Nach JEDER Änderung an den folgenden Attributen muss ein &amp;lt;code&amp;gt;[[#set-update-devicemap|update devicemap]]&amp;lt;/code&amp;gt; ausgeführt werden. Sonst erfahren weder RHASSPY, noch Rhasspy von der Änderung.&lt;br /&gt;
*RHASSPY sammelt alle Informationen aus diesen Attributen in seinem eigenen Device-HASH. Dieser wird durch das &amp;lt;code&amp;gt;update devicemap&amp;lt;/code&amp;gt;-Kommando aktualisiert und kann mittels &amp;lt;code&amp;gt;[[List|list]]&amp;lt;/code&amp;gt;-Befehl angezeigt werden. Für diesen HASH werden alle Namen und sonstige &amp;quot;Labels&amp;quot; in Kleinbuchstaben umgewandelt. Sollte man Slots händisch befüllen, muss also darauf geachtet werden, dass Rhasspy ebenfalls Werte in Kleinbuchstaben liefert.&lt;br /&gt;
*Die Mindestvoraussetzungen für ein FHEM Device um mit RHASSPY zusammenzuarbeiten sind:&lt;br /&gt;
**Das Device muss von der devspec im Define des RHASSPY-Devices abgedeckt werden&lt;br /&gt;
**Es muss mindestens eines der folgenden Attribute (im Normalfall &#039;&#039;genericDeviceType&#039;&#039;) im Device gesetzt sein.&lt;br /&gt;
*Die Mapping-Logik (für Namen, mögliche Schaltzustände, etc.) ist wie folgt:&lt;br /&gt;
**Sind RHASSPY-spezifische Attribute gesetzt, werden ausschließlich diese verwendet. Natürlich nur für den Zweck des gesetzten Attributs. Ein gesetzter &#039;&#039;rhasspyName&#039;&#039; z.B. wird also nicht verhindern, dass die durch &#039;&#039;genericDeviceType&#039;&#039; ermittelten möglichen Schaltzustände ebenfalls gespeichert werden.&lt;br /&gt;
**Je spezifischer ein Attribut ist, desto eher wird überschreiben, was weniger speziell ist. Ein gesetzter &#039;&#039;alias&#039;&#039; wird also verhindern, dass der (technische) Device-Name verwendet wird. Aber ein gesetztes Attribut &#039;&#039;alexaName&#039;&#039;, &#039;&#039;gassistantName&#039;&#039; oder &#039;&#039;siriName&#039;&#039; wird (auch) den &#039;&#039;alias&#039;&#039; überschreiben. Sind zwei &amp;quot;gleichwertige&amp;quot; Attribute vorhanden (z.B. &#039;&#039;siriName&#039;&#039; und &#039;&#039;alexaName&#039;&#039;), werden beide verwendet.&lt;br /&gt;
*Attribut-Werte werden typischerweise &amp;quot;Zeile für Zeile&amp;quot; gelesen. Wobei gilt, eine Zeile pro Wert/Befehl/Funktionalität. Zeilenumbrüche &#039;&#039;&#039;müssen&#039;&#039;&#039; also an den richtigen Stellen gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;code&amp;gt;genericDeviceType&amp;lt;/code&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
Ist dieses Attribut gesetzt &#039;&#039;&#039;und&#039;&#039;&#039; entspricht der Devicename der devspec, wird RHASSPY das Mapping (und andere eventuell schon vorhandene Werte) automatisch ermitteln.&lt;br /&gt;
&lt;br /&gt;
Derzeit werden folgende Werte für das Attribut genericDeviceType unterstützt:&lt;br /&gt;
*switch&lt;br /&gt;
*light&lt;br /&gt;
*thermostat&lt;br /&gt;
*thermometer&lt;br /&gt;
*HumiditySensor&lt;br /&gt;
*blind/blinds/shutter&lt;br /&gt;
*media&lt;br /&gt;
*motion/contact/ContactSensor/lock/presence&lt;br /&gt;
&lt;br /&gt;
Wird &#039;&#039;genericDeviceType&#039;&#039; verwendet, werden unter anderem folgende Informationen gesammelt:&lt;br /&gt;
* der Name (&amp;lt;code&amp;gt;NAME&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;alias&amp;lt;/code&amp;gt;) des Devices&lt;br /&gt;
* der (FHEM-)Raum, in dem sich das Device befindet.&lt;br /&gt;
* die Gruppe, zu der das Device gehört (ggf. unter Beachtung des Schlüssels  &amp;lt;code id=&amp;quot;attr-rhasspytweaks-ignorekeywords&amp;quot;&amp;gt;gdt2groups&amp;lt;/code&amp;gt; aus &#039;&#039;rhasspyTweaks&#039;&#039;)&lt;br /&gt;
* wie Informationen vom Gerät abgefragt werden können&lt;br /&gt;
* wie Werte/Status am Gerät gesetzt werden können&lt;br /&gt;
&lt;br /&gt;
Die Verwendung von &#039;&#039;genericDeviceType&#039;&#039; ist der einfachste Weg, wie man FHEM-Devices dazu bringen kann, mit RHASSPY zusammenzuarbeiten. Manchmal liefert genericDeviceType aber nicht ausreichende oder nicht passende Informationen. In so einem Fall können die folgenden Attribute (zusätzlich) verwendet werden.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;code&amp;gt;rhasspyName&amp;lt;/code&amp;gt;===&lt;br /&gt;
Mit diesem Attribut kann der Name des Geräts eingestellt werden, mit dem es in einem Sprachbefehl angesprochen werden soll. Es können auch mehrere Namen - getrennt durch ein Komma - angegeben werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039; &amp;lt;code&amp;gt;attr &amp;lt;device&amp;gt; rhasspyName Lampe,Stehlampe,Wunderlicht&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es ist durchaus möglich, mehrere FHEM-Geräte mit dem selben Namen zu haben. Sie müssen dann nur in unterschiedlichen Räumen sein.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;code&amp;gt;rhasspyRoom&amp;lt;/code&amp;gt;===&lt;br /&gt;
Dieses Attribut kann verwendet werden, um Rhasspy mitzuteilen, in welchem physischem (oder logischen) Raum sich das Gerät befindet.&lt;br /&gt;
&lt;br /&gt;
Ist es nicht vorhanden, wird &amp;lt;code&amp;gt;alexaRoom&amp;lt;/code&amp;gt; oder das FHEM-Attribut &amp;lt;room&amp;gt; verwendet. Sind auch diese nicht vergeben, gehört das Gerät zum &amp;quot;Standard-Raum&amp;quot;, der im Define des RHASSPY-Devices angegeben wurde.&lt;br /&gt;
&lt;br /&gt;
Das Attribut ist nützlich, wenn man Sprachbefehle ohne explizite Raumangabe verwenden will. Gibt es z.B. ein Gerät mit dem Namen &#039;&#039;Lampe&#039;&#039; und dessen rhasspyRoom-Attribut ist gleich, wie die &#039;&#039;siteId&#039;&#039; von der aus der Sprachbefehl abgesetzt wird, reicht es zu sagen &amp;quot;Lampe ein&amp;quot;. Der Raum muss also nicht extra dazu gesagt werden.&lt;br /&gt;
&lt;br /&gt;
Es ist auch möglich, mehrere Raum-Namen zu vergeben sofern diese durch ein Komma voneinander getrennt werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039; &amp;lt;code&amp;gt;attr &amp;lt;device&amp;gt; rhasspyRoom livingroom&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hinweis: Wenn die &#039;&#039;siteId&#039;&#039; den Konventionen von Rhasspy zur Gruppierung von siteIds folgt (&#039;&#039;roomname.satellite&#039;&#039;), wird nur &amp;lt;code&amp;gt;roomname&amp;lt;/code&amp;gt; als Raum-Name angenommen. Beachte: Die automatisierte Zuweisung zu einem Raum kann durch &#039;&#039;siteId2room_.*&#039;&#039;-Readings modifiziert werden (s.o.). &lt;br /&gt;
===&amp;lt;code&amp;gt;rhasspyGroup&amp;lt;/code&amp;gt;===&lt;br /&gt;
Kommagetrennte Liste an Gruppen, zu denen das Gerät zugehörig ist&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039; &amp;lt;code&amp;gt;attr &amp;lt;device&amp;gt; rhasspyGroup Lampen,Beleuchtung Arbeitsfläche,Küchen Beleuchtung&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;code&amp;gt;rhasspyMapping&amp;lt;/code&amp;gt;===&lt;br /&gt;
Wenn die automatische Erkennung des richtigen Intents für ein Gerät nicht funktioniert oder nicht das gewünschte Ergebnis liefert, kann mit diesem Attribut angegeben werden, mit welchem Intent das Gerät gesteuert werden kann.&lt;br /&gt;
&lt;br /&gt;
Es ist möglich, mehrere verschiedene Intents pro Gerät zu verwenden. Es muss nur einfach eine neue Zeile für ein weiteres Mapping verwendet werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr &amp;lt;device&amp;gt; rhasspyMapping SetOnOff:cmdOn=on,cmdOff=off,response=&amp;quot;Alles klar&amp;quot;&lt;br /&gt;
GetOnOff:currentVal=state,valueOff=off&lt;br /&gt;
GetNumeric:currentVal=pct,type=brightness&lt;br /&gt;
SetNumeric:currentVal=brightness,cmd=brightness,minVal=0,maxVal=255,map=percent,step=1,type=brightness&lt;br /&gt;
Status:response=Die Helligkeit in der Küche ist bei [&amp;lt;device&amp;gt;:pct]&lt;br /&gt;
MediaControls:cmdPlay=play,cmdPause=pause,cmdStop=stop,cmdBack=previous,cmdFwd=next&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Formatierung von Befehlen und Readings innerhalb eines rhasspyMappings====&lt;br /&gt;
Manche Intents können FHEM-Kommandos oder -Readings verwenden, um Werte auszulesen oder zu setzen.&lt;br /&gt;
&lt;br /&gt;
Dabei gibt es drei Möglichkeiten, wie diese geschrieben werden können:&lt;br /&gt;
*Direktes Verwenden von SET-Kommando oder Reading des aktuellen Device:&lt;br /&gt;
:&amp;lt;code&amp;gt;cmd=on or currentReading=temperature&amp;lt;/code&amp;gt;&lt;br /&gt;
*Umleiten eines Kommando auf ein anderes Device oder Verwenden eines Readings aus einem anderen Gerät:&lt;br /&gt;
:&amp;lt;code&amp;gt;cmd=Otherdevice:on or currentReading=Otherdevice:temperature&amp;lt;/code&amp;gt;&lt;br /&gt;
*Perl-Code um einen Befehl auszuführen oder einen Wert zu setzen:&lt;br /&gt;
:Das ermöglicht sehr komplexe Anfragen.&lt;br /&gt;
:Der Code muss in geschwungenen Klammern sein.&lt;br /&gt;
:&amp;lt;code&amp;gt;{currentVal={ReadingsVal($DEVICE,&amp;quot;state&amp;quot;,0)}&amp;lt;/code&amp;gt;&lt;br /&gt;
:oder&lt;br /&gt;
:&amp;lt;code&amp;gt; cmd={fhem(&amp;quot;set $DEVICE dim $VALUE&amp;quot;)}&amp;lt;/code&amp;gt;&lt;br /&gt;
:$DEVICE ist das aktuelle FHEM-device. Der SetNumeric-Intent kann $VALUE für den Wert verwenden, der gesetzt werden soll.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;code&amp;gt;rhasspySpecials&amp;lt;/code&amp;gt;===&lt;br /&gt;
Dieses Attribut wirkt ähnlich wie [[#rhasspyTweaks| rhasspyTweaks]], verändert allerdings nur jeweils das Verhalten des Geräts, bei dem es gesetzt ist. Auch dieses Attribut wird zeilenweise eingelesen, es können ein oder mehrere der folgenden Optionen gesetzt werden:&lt;br /&gt;
&lt;br /&gt;
==== group ====&lt;br /&gt;
::Wird dieser Schlüssel gesetzt, wird das Gerät bei Gruppenaktionen nicht direkt adressiert, sondern die hier angegebene Gruppe. Details hierzu sind in [[RHASSPY/Vertiefung#Timing-Aspekte| Vertiefung - Timing-Aspekte]] zu finden.&lt;br /&gt;
&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;attr lamp1 rhasspySpecials group:async_delay=100 prio=1 group=lights&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== numericValueMap ====&lt;br /&gt;
::Ermöglicht es, statt der allgemeinen Methode zum Umgang mit numerischen Werten einzelnen Werten spezielle Kommandos zuzuweisen. Dies kann z.B. hilfreich sein, um spezielle Positionen für Rollladengeräte anzusteuern.&lt;br /&gt;
::&#039;&#039;&#039;Beispiel&#039;&#039;&#039;:&lt;br /&gt;
::&amp;lt;code&amp;gt;attr blind1 rhasspySpecials numericValueMap:10=&#039;Event Slit&#039; 50=&#039;myPosition&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
::führt dazu, dass ein numerischer Wert von 10 (im {Value}-key) das Kommando &amp;lt;code&amp;gt;set blind1 Event Slit&amp;lt;/code&amp;gt; ausführt.&lt;br /&gt;
&lt;br /&gt;
==== venetianBlind ====&lt;br /&gt;
Siehe [[RHASSPY/Vertiefung#Jalousien|Vertiefung - Jalousien]]&lt;br /&gt;
&lt;br /&gt;
==== colorCommandMap ====&lt;br /&gt;
Sowie **colorTempMap** und **colorForceHue2rgb**&lt;br /&gt;
Siehe [[RHASSPY/Vertiefung#Farben|Vertiefung - Farben]]&lt;br /&gt;
&lt;br /&gt;
==== priority ====&lt;br /&gt;
Ermöglicht es, Rückfragen zu vermeiden, wenn mehrere Geräte für bestimmte Aktionen in Frage kommen. Siehe [[RHASSPY/Vertiefung#Einer_statt_alle|Einer statt alle]]&lt;br /&gt;
&lt;br /&gt;
==== confirm ====&lt;br /&gt;
Ist eine Möglichkeit, Geräte nur nach Rückfrage und Bestätigung zu schalten (ähnlich wie &#039;&#039;confirmIntents&#039;&#039; in &#039;&#039;rhasspyTweaks&#039;&#039;). Es können entweder einfach nur Intent-Namen angegeben werden, oder Paare von **Intent** und zugehöriger **response**:&lt;br /&gt;
 SetOnOff=&amp;quot;Soll $target wirklich $Value geschaltet werden&amp;quot; SetScene&lt;br /&gt;
&lt;br /&gt;
==== confirmValueMap ====&lt;br /&gt;
Kann spezielle Übersetzungen für $Value enthalten, z.B. für Rollladen-Geräte:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;confirm: SetOnOff=&amp;quot;wirklich $Value $target&amp;quot;&lt;br /&gt;
confirmValueMap: on=öffnen off=schließen&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== scenes ====&lt;br /&gt;
Wird bei der automatisierten Erfassung erkannt, dass ein Gerät das Setzen von Szenen unterstützt, werden die erkannten Szenen-Namen an Rhasspy übergeben. Da diese häufig technischer Natur sind, eignen sie sich nicht für eine Spracherkennung. Über diesen Schlüssel können daher sprechbare Namen für jede Szene vergeben werden, und/oder einzelne bzw. alle Szenen von der Erkennung ausgenommen werden. Der Kenner &#039;&#039;none&#039;&#039; löscht die Szene von der Liste der übermittelten Szenen, wird die Kombination &#039;&#039;all=none&#039;&#039; angegeben, wird dieses Gerät insgesamt von der Vorbereitung für den Intent &#039;&#039;SetScene&#039;&#039; ausgeschlossen.&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;attr lamp1 rhasspySpecials scenes:scene2=&amp;quot;Kino zu zweit&amp;quot; scene3=Musik scene1=none scene4=none&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Siehe auch [[RHASSPY/Vertiefung#echte_Szenen|Vertiefung - echte Szenen]]. &lt;br /&gt;
&lt;br /&gt;
=== Veraltete Attribute ===&lt;br /&gt;
In der Regel sollte es ausreichen, die zu steuernden Devices über die oben genannten Attribute zu konfigurieren. Es gibt jedoch noch zwei ältere Methoden. Um diese zu verwenden, muss zuerst jeweils ein entsprechendes User-Attribut im FHEM-Device, das damit gesteuert werden soll, angelegt werden.&lt;br /&gt;
&lt;br /&gt;
====&amp;lt;code&amp;gt;rhasspyChannels&amp;lt;/code&amp;gt;====&lt;br /&gt;
Das Attribut wird vom Intent &#039;&#039;MediaControls&#039;&#039; verwendet. Es informiert den Intent darüber, welche (Medien-)Kanäle vorhanden sind und welcher FHEM-Befehl oder Perl-Code auszuführen ist, wenn auf diesen Kanal geschaltet werden soll.&lt;br /&gt;
&lt;br /&gt;
In diesem Attribut muss eine Zeile pro (Medien-)Kanal verwendet werden.&lt;br /&gt;
&lt;br /&gt;
Um rhasspyChannels zu verwenden, muss zuerst ein neues User-Attribut im FHEM-Device, das damit gesteuert werden soll, angelegt werden. Dafür kann z.B. dieses Beispiel verwendet werden: &amp;lt;code&amp;gt;attr &amp;lt;deviceName&amp;gt; userattr rhasspyChannels:textField-long&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr &amp;lt;device&amp;gt; rhasspyChannels orf eins=channel 201&lt;br /&gt;
orf zwei=channel 202&lt;br /&gt;
orf drei=channel 203&lt;br /&gt;
netflix=launchApp Netflix&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&amp;lt;code&amp;gt;rhasspyColors&amp;lt;/code&amp;gt;====&lt;br /&gt;
Ältere Methode, die verwendet werden kann, um Lichtfarben zu wechseln. Es wird nachdrücklich empfohlen, die neueren Methoden über die (nummerisch zu übergebenden) allgemeinen Farbwerte und/oder ein &#039;&#039;colorCommandMap&#039;&#039; oder &#039;&#039;colorTempMap&#039;&#039; (siehe &#039;&#039;rhasspySpecials&#039;&#039;) zu konfigurieren!&lt;br /&gt;
&lt;br /&gt;
Um das Mapping zu verwenden, muss zuerst ein User-Attribut am zu steuernden Gerät angelegt werden. Z.B. &amp;lt;code&amp;gt;attr &amp;lt;deviceName&amp;gt; userattr rhasspyChannels:textField-long&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Eine Zeile pro Farbe&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr lamp1 rhasspyColors rot=rgb FF0000&lt;br /&gt;
grün=rgb 008000&lt;br /&gt;
blau=rgb 0000FF&lt;br /&gt;
gelb=rgb FFFF00&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Intents ==&lt;br /&gt;
Intents werden verwendet um FHEM zu sagen, was es nach einem erhaltenen Sprach-/Textkommand unternehmen soll. Dieses Modul stellt einige Intents bereit.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Wichtig&lt;br /&gt;
:*Bei Tags (&amp;lt;code&amp;gt;Value&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;, etc.) ist die Schreibweise sehr wichtig! Die sind case-sensitive. Bitte daher genau so schreiben, wie sie in dieser Dokumentation vorkommen.&lt;br /&gt;
:*RHASSPY erstellt bei einem &amp;lt;code&amp;gt;update slots&amp;lt;/code&amp;gt; auch Slots je nach Möglichkeiten der Geräte oder Gruppen. Unterstützt ein Gerät zum Beispiel den Intent &#039;&#039;GetNumeric&#039;&#039;, wird auch ein Slot &amp;lt;code&amp;gt;de.fhem.Device-GetNumeric&amp;lt;/code&amp;gt; erstellt. Ein Gerät, dass ein- und ausgeschalten werden kann, wird im Slot &amp;lt;code&amp;gt;de.fhem.Device-SetOnOff&amp;lt;/code&amp;gt; untergebracht. Ein einzelnes Gerät kann sich auch in mehreren Slots befinden. Um eine möglichst genaue Spracherkennung zu gewährleisten, ist &#039;&#039;&#039;empfohlen&#039;&#039;&#039;, diese &#039;&#039;&#039;spezifischen Slots&#039;&#039;&#039; - statt einfach nur &amp;lt;code&amp;gt;de.fhem.Device&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;de.fhem.Group&amp;lt;/code&amp;gt; - &#039;&#039;&#039;zu verwenden&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetOnOff ===&lt;br /&gt;
Intent um Geräte zwischen zwei Zuständen (ein/aus, auf/zu, start/stop) zu schalten.&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
SetOnOff:cmdOn=on,cmdOff=off&lt;br /&gt;
SetOnOff:cmdOn=on,cmdOff=off,response=&amp;quot;Sir yes Sir&amp;quot;&lt;br /&gt;
SetOnOff:cmdOn=on,cmdOff=off,response=&amp;quot;$DEVICE now [$DEVICE:state]&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Argumente:&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdOn&amp;lt;/code&amp;gt; Befehl um das Gerät einzuschalten. Siehe [[#Formatierung von Befehlen und Readings innerhalb eines rhasspyMappings|Formatierung von Befehlen und Readings innerhalb eines rhasspyMappings]].&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdOff&amp;lt;/code&amp;gt; Befehl um das Gerät auszuschalten. Siehe [[#Formatierung von Befehlen und Readings innerhalb eines rhasspyMappings|Formatierung von Befehlen und Readings innerhalb eines rhasspyMappings]].&lt;br /&gt;
&lt;br /&gt;
Optionale Argumente:&lt;br /&gt;
*&amp;lt;code&amp;gt;response&amp;lt;/code&amp;gt; Eine benutzerdefinierte Antwort auf den Befehl&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
schalten das licht ein&lt;br /&gt;
schließe den rollladen im schlafzimmer&lt;br /&gt;
starte die kaffeemaschine&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetOnOff]&lt;br /&gt;
(schalte|schalt|mache|mach|stelle|stell|starte) [den|die|das] $de.fhem.Device-SetOnOff{Device} [[(im|in dem|auf dem|in der|auf der)] $de.fhem.Room{Room}] (an|ein){Value:on}&lt;br /&gt;
(schalte|schalt|mache|mach|stelle|stell) [den|die|das] $de.fhem.Device-SetOnOff{Device} [[(im|in dem|auf dem|in der|auf der)] $de.fhem.Room{Room}] aus{Value:off}&lt;br /&gt;
(fahre|fahr) [den|die|das] $de.fhem.Device-blind{Device} [[(im|in dem|auf dem|in der|auf der)] $de.fhem.Room{Room}] ((hoch|auf){Value:on}|(zu|runter){Value:off})&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verpflichtende Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Value:on&amp;lt;/code&amp;gt; und/oder &amp;lt;code&amp;gt;Value:off&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetOnOffGroup ===&lt;br /&gt;
Intent um Gruppen von Geräte zwischen zwei Zuständen zu schalten.&lt;br /&gt;
&lt;br /&gt;
Dafür ist ein SetOnOff-Mapping benötigt und alle gewünschten Geräte müssen dasselbe Attribut &amp;lt;code&amp;gt;group&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;rhasspyGroup&amp;lt;/code&amp;gt; haben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
schalte alle lampen in der küche aus&lt;br /&gt;
schließe alle rollläden im schlafzimmer&lt;br /&gt;
schalte alle lampen aus&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetOnOffGroup]&lt;br /&gt;
\[(schalt|mach)] (alle | sämtliche ) $de.fhem.Group-SetOnOff{Group} [[in|im|in der|auf der] [( überall:global | $de.fhem.Room ){Room}] ein{Value:on}&lt;br /&gt;
\[(schalt|mach)] (alle | sämtliche ) $de.fhem.Group-SetOnOff{Group} [[in|im|in der|auf der] [( überall:global | $de.fhem.Room ){Room}] aus{Value:off}&lt;br /&gt;
(öffne{Value:on}|schließe{Value:off}) (alle | sämtliche ) $de.fhem.Group-blind{Group} [[in|im|in der|auf der] [( überall:global{Room:global} | $de.fhem.Room{Room} )] &lt;br /&gt;
(fahr|fahre|mach|mache) [den|die|das] $de.fhem.Group-blind{Group} [[(im|in dem|in der)] ( überall:global{Room:global} | $de.fhem.Room{Room} )] ( auf{Value:on} | hoch{Value:on} | zu{Value:off} | runter{Value:off} )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verpflichtende Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Value:on&amp;lt;/code&amp;gt; und/oder &amp;lt;code&amp;gt;Value:off&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Group&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetTimedOnOff ===&lt;br /&gt;
Intent um Geräte für eine bestimmte Zeitspanne in einen bestimmten Zustand zu versetzten.&lt;br /&gt;
&lt;br /&gt;
Device muss ein SetOnOff-Mapping haben und die {{Link2CmdRef|Anker=setExtensions|Lang=de|Label=SetExtentions}} unterstützen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
schalte das licht für eine minute und dreißig sekunden aus&lt;br /&gt;
schalte die musik im bad bis zwei uhr ein&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetTimedOnOff]&lt;br /&gt;
schalte $de.fhem.Device-SetOnOff{Device} [$de.fhem.Room{Room}] für ([(1..60){Hour!int} (stunde|stunden)] [und] [(1..60){Min!int} (minute|minuten)] [und] [(1..60){Sec!int} (sekunde|sekunden)]) (ein{Value:on}|aus{Value:off})&lt;br /&gt;
schalte $de.fhem.Device-SetOnOff{Device} [$de.fhem.Room{Room}] bis (0..24){Hourabs!int} [(1..60){Min!int}] (ein{Value:on}|aus{Value:off})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verpflichtende Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Value&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Hour&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Min&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Sec&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Hourabs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetTimedOnOffGroup ===&lt;br /&gt;
Intent um eine Gruppe von Geräten für eine bestimmte Zeit zu schalten.&lt;br /&gt;
&lt;br /&gt;
Devices müssen ein SetOnOff-Mapping haben, in einer Gruppe sein und die {{Link2CmdRef|Anker=setExtensions|Lang=de|Label=SetExtentions}} unterstützen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
schalte alle lichter in der küche für fünfzig sekunden ein&lt;br /&gt;
schalte alle licher bis zwei uhr ein&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetTimedOnOffGroup]&lt;br /&gt;
schalte $de.fhem.Group-SetOnOff{Group} [$de.fhem.Room{Room}] für ([(1..60){Hour!int} (stunde|stunden)] [und] [(1..60){Min!int} (minute|minuten)] [und] [(1..60){Sec!int} (sekunde|sekunden)]) (ein{Value:on}|aus{Value:off})&lt;br /&gt;
schalte $de.fhem.Group-SetOnOff{Group} [$de.fhem.Room{Room}] bis (0..24){Hourabs!int} [(1..60){Min!int}] (ein{Value:on}|aus{Value:off})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verpflichtende Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Value&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Group&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Hour&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Min&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Sec&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Hourabs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GetOnOff ===&lt;br /&gt;
Intent um den aktuellen Zustand eines Gerätes zu erfragen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
GetOnOff:currentVal=state,valueOff=closed&lt;br /&gt;
GetOnOff:currentVal=state,valueOn=on&lt;br /&gt;
GetOnOff:currentVal=pct,valueOff=0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Argumente:&lt;br /&gt;
Hinweis: nur &amp;lt;code&amp;gt;valueOn&amp;lt;/code&amp;gt; ODER &amp;lt;code&amp;gt;valueOff&amp;lt;/code&amp;gt; müssen gesetzt werden. Der jeweils andere Wert bekommt den anderen Status.&lt;br /&gt;
*&amp;lt;code&amp;gt;currentVal&amp;lt;/code&amp;gt; Reading aus dem der aktuelle Status hervorgeht&lt;br /&gt;
*&amp;lt;code&amp;gt;valueOff&amp;lt;/code&amp;gt; Wert, der den Zustand &#039;&#039;aus&#039;&#039; beschreibt&lt;br /&gt;
*&amp;lt;code&amp;gt;valueOn&amp;lt;/code&amp;gt; Wert, der den Zustand &#039;&#039;an&#039;&#039; beschreibt&lt;br /&gt;
&lt;br /&gt;
Optionale Argumente:&lt;br /&gt;
*&amp;lt;code&amp;gt;response&amp;lt;/code&amp;gt; Eine benutzerdefinierte Antwort auf den Befehl&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
ist das licht im bad ein&lt;br /&gt;
ist das fenster im wohnzimmer geöffnet&lt;br /&gt;
läuft die waschmaschine&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[en.fhem:GetOnOff]&lt;br /&gt;
ist $de.fhem.Device-GetOnOff{Device} [$de.fhem.Room{Room}] (ein|geöffnet){State:on}&lt;br /&gt;
ist $de.fhem.Device-GetOnOff{Device} [$de.fhem.Room{Room}] (aus|geschlossen){State:off}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zustände &#039;&#039;ein&#039;&#039; und &#039;&#039;aus&#039;&#039; sollten in unterschiedlichen Sentences sein und müssen &amp;lt;code&amp;gt;{State:on}&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;{State:off}&amp;lt;/code&amp;gt; beinhalten.&lt;br /&gt;
&lt;br /&gt;
Verpflichtende Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;State:on&amp;lt;/code&amp;gt; und/oder &amp;lt;code&amp;gt;State:off&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetNumeric ===&lt;br /&gt;
Intent, um Lampen zu dimmen, Rollladengeräte zu positionieren, Lautstärken oder Solltemperaturen zu ändern, usw.. &lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
SetNumeric:currentVal=pct,cmd=dim,minVal=0,maxVal=99,step=25,type=brightness&lt;br /&gt;
SetNumeric:currentVal=volume,cmd=volume,minVal=0,maxVal=99,step=10,type=volume&lt;br /&gt;
SetNumeric:currentVal=brightness,cmd=brightness,minVal=0,maxVal=255,map=percent,step=1,type=brightness&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Argumente:&lt;br /&gt;
*&amp;lt;code&amp;gt;currentVal&amp;lt;/code&amp;gt; Reading, in dem der aktuelle Wert zu finden ist (wird zwingend benötigt).&lt;br /&gt;
*&amp;lt;code&amp;gt;part&amp;lt;/code&amp;gt; Kann genutzt werden, um den Wert aus **currentVal** in mehrere Teile zu zerlegen (getrennt wird am Leerzeichen). Z.B. wenn currentVal 23 C ist, wird **part=0** **23** ergeben. Optionaler Parameter.&lt;br /&gt;
*&amp;lt;code&amp;gt;cmd&amp;lt;/code&amp;gt; Das **Set**-Kommando des Geräts, das in Folge des Sprachkommandos ausgeführt werden soll. (Notwendiger Parameter).&lt;br /&gt;
*&amp;lt;code&amp;gt;minVal&amp;lt;/code&amp;gt; Niedrigster zugelassener Wert, optional.&lt;br /&gt;
*&amp;lt;code&amp;gt;maxVal&amp;lt;/code&amp;gt; Höchster zugelassener Wert, optional.&lt;br /&gt;
*&amp;lt;code&amp;gt;step&amp;lt;/code&amp;gt; Schrittweite für relative Änderungen wie &amp;lt;code&amp;gt;mach lauter&amp;lt;/code&amp;gt;. Optional. Default: 10.&lt;br /&gt;
*&amp;lt;code&amp;gt;map&amp;lt;/code&amp;gt; Derzeit wird ausschließlich die Angabe **percent** ausgewertet. Optionaler Parameter, der bewirkt, dass alle Angaben als Prozentwert (zwischen minVal und maxVal) interpretiert werden und entsprechend gerechnet wird. So wird z.B. eine Leuchte mit **minVal=0** und **maxVal=255** beim Befehl &amp;quot;stelle das Licht auf 50&amp;quot; dies so verstehen, als wäre die Anweisung &amp;quot;stelle das Licht auf 50 Prozent&amp;quot; gewesen. Das Licht wird daher auf 127 gestellt, und nicht auf (absolut) 50.&lt;br /&gt;
*&amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; Zur Unterscheidung, falls mehrere SetNumeric-Intents für das Gerät möglich sind. Empfohlener Parameter.&lt;br /&gt;
&lt;br /&gt;
Gut zu wissen:&lt;br /&gt;
Um Kommandos wie **lauter** oder **leiser** ohne Angabe eines Gerätes ausführen zu können, muss RHASSPY zunächst ermitteln, welches Gerät gerade überhaupt etwas wiedergibt ist. Daher nutzt es die GetOnOff-Mappings, um festzustellen, welches Gerät vom **type=volume** überhaupt angeschaltet ist. Dabei wird wie üblich zunächst im aktuellen rhasspyRoom gesucht, bevor die Suche außerhalb fortgesetzt wird.&lt;br /&gt;
Setzt man also Mappings manuell, ist es ratsam, auch ein **GetOnOff**-Mapping zu setzen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zulässige Typen sind:&lt;br /&gt;
*&amp;lt;code&amp;gt;brightness&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;setTarget&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;temperature&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;volume&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
Stelle das Licht auf 30 Prozent&lt;br /&gt;
Mach das Radio leiser&lt;br /&gt;
Stell die Temperatur im Wohnzimmer 2 Grad wärmer&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
(Beachte: Wenn wie hier im Beispiel reele Zahlen (mit Komma) ermöglicht werden sollen (&amp;quot;acht Komma fünf&amp;quot;), wird ein [[#Custom Converter für reelle Zahlen| Custom Converter für reelle Zahlen]] benötigt)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetNumeric]&lt;br /&gt;
den=(den|die|das)&lt;br /&gt;
cmdmulti=(schalte|schalt|mache|mach|stelle|stell)&lt;br /&gt;
rooms=([(im|in dem|auf dem|in der|auf der)] $de.fhem.Room{Room})&lt;br /&gt;
&amp;lt;cmdmulti&amp;gt; [&amp;lt;den&amp;gt;] $de.fhem.Device-SetNumeric{Device} auf (0..100){Value!int} [Prozent{Unit:percent}]&lt;br /&gt;
\[&amp;lt;cmdmulti&amp;gt;] [die Lautstärke [an|am]] [dem|&amp;lt;den&amp;gt;] $de.fhem.Device-media{Device} [&amp;lt;rooms&amp;gt;] [um] [(0..10){Value!float}] [dezibel{Unit:decibel}|Prozent{Unit:percent}] ( lauter:volUp | leiser:volDown ){Change}&lt;br /&gt;
&amp;lt;cmdmulti&amp;gt; [die Lautstärke [an|am]] [dem|&amp;lt;den&amp;gt;] [$de.fhem.Device-media{Device}] [&amp;lt;rooms&amp;gt;] [um] [(0..10){Value!float}] [dezibel{Unit:decibel}|Prozent{Unit:percent}] ( lauter:volUp | leiser:volDown ){Change}&lt;br /&gt;
&amp;lt;cmdmulti&amp;gt; [&amp;lt;den&amp;gt;] $de.fhem.Device-thermostat{Device} [&amp;lt;rooms&amp;gt;] [um] [(0..10){Value!int}] [Grad{Unit.degree}] ( wärmer:tempUp | kälter:tempDown ){Change}&lt;br /&gt;
&amp;lt;cmdmulti&amp;gt; [&amp;lt;den&amp;gt;] $de.fhem.Device-light{Device} [&amp;lt;rooms&amp;gt;] [um] [(0..30 [Komma:. 1..9]){Value!customFloat}] [Prozent{Unit:percent}] ( heller:lightUp | dunkler:lightDown){Change}&lt;br /&gt;
&amp;lt;cmdmulti&amp;gt; [&amp;lt;den&amp;gt;] ( $de.fhem.Device-light | $de.fhem.Device-media |$de.fhem.Device-blind){Device}  [&amp;lt;rooms&amp;gt;] auf [(0..30 [Komma:. 1..9]){Value!customFloat}]&lt;br /&gt;
( mehr{Change:lightUp} | weniger{Change:lightDown} ) $de.fhem.Device-light{Device} [&amp;lt;de.fhem:SetOnOff.rooms&amp;gt;]&lt;br /&gt;
( halte | stoppe | stop ) [&amp;lt;den&amp;gt;] $de.fhem.Device-blind{Device} [&amp;lt;de.fhem:SetOnOff.rooms&amp;gt;] [an] {Change:cmdStop}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Derzeit werden folgende Typen für das Feld &amp;lt;code&amp;gt;{Change}&amp;lt;/code&amp;gt; ausgewertet:&lt;br /&gt;
*&amp;lt;code&amp;gt;tempUp&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;tempDown&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;volUp&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;volDown&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;lightUp&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;lightDown&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;setUp&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;setDown&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notwendig sind:&lt;br /&gt;
*&amp;lt;code&amp;gt;Change&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Type&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Value&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Change&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Unit&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== SetNumericGroup ===&lt;br /&gt;
Intent, um Lampen zu dimmen, Rollladengeräte zu positionieren, Lautstärken oder Solltemperaturen zu ändern, usw.. Die Funktionsweise entspricht dabei dem des Intents &#039;&#039;SetNumeric&#039;&#039;, wobei eben statt eines einzelnen Devices eben ein oder mehrere Geräte über ihren Gruppennamen angesprochen werden. Statt des optionalen Tags &amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt; ist daher der Tag &amp;lt;code&amp;gt;Group&amp;lt;/code&amp;gt; zu übergeben.&lt;br /&gt;
Aus der Adressierung mehrerer Geräte ergeben sich einige Besonderheiten, die in der [[RHASSPY/Vertiefung]], dort speziell auch im Punkt [[RHASSPY/Vertiefung#Beispiel_SetOnOffGroup|Beispiel SetOnOffGroup]] näher erläutert sind. Wesentliche zu beachtende Aspekte sind:&lt;br /&gt;
* Vermeidung von Funk-Überschneidungen (&#039;&#039;Specials&#039;&#039; &#039;&#039;partOf&#039;&#039; und &#039;&#039;async_delay&#039;&#039;)&lt;br /&gt;
* Begrenzung der Gruppenzugehörigkeit durch die Raumzugehörigkeit (und die Aufhebung dieser Beschränkung durch die Übergabe des speziellen Raums &#039;&#039;global&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
=== GetNumeric ===&lt;br /&gt;
Intent, mit dem man Werte erfragen kann, wie z.B. die aktuelle Temperatur, Helligkeit, Lautstärke, ...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
GetNumeric:currentVal=temperature,part=1,type=temperature&lt;br /&gt;
GetNumeric:currentVal=pct,map=percent,minVal=0,maxVal=100,type=brightness&lt;br /&gt;
GetNumeric:currentVal=volume,type=volume&lt;br /&gt;
GetNumeric:currentVal=humidity,part=0,type=humidity&lt;br /&gt;
GetNumeric:currentVal=batteryPercent,type=battery&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Argumente:&lt;br /&gt;
*&amp;lt;code&amp;gt;currentVal&amp;lt;/code&amp;gt; Das Reading, das den abzufragenden Wert enthält&lt;br /&gt;
*&amp;lt;code&amp;gt;part&amp;lt;/code&amp;gt; Teile aus currentVal ableiten, indem am Leerzeichen getrennt wird. Ist &#039;&#039;currentVal&#039;&#039; beispielsweise &#039;&#039;23 C&#039;&#039;, entspricht &#039;&#039;part=1&#039;&#039; dem Wert &#039;&#039;23&#039;&#039;&lt;br /&gt;
*&amp;lt;code&amp;gt;map&amp;lt;/code&amp;gt; Die Funktionswiese entspricht dem &#039;&#039;SetNumeric&#039;&#039; Intent. Wandelt den vorhandenen Wert in eine Prozent-Angabe um.&lt;br /&gt;
*&amp;lt;code&amp;gt;minVal&amp;lt;/code&amp;gt; Niedrigster zulässiger Wert (nur benötigt, wenn &#039;&#039;map&#039;&#039; angegeben ist).&lt;br /&gt;
*&amp;lt;code&amp;gt;maxVal&amp;lt;/code&amp;gt; Höchster zulässiger Wert  (nur benötigt, wenn &#039;&#039;map&#039;&#039; angegeben ist).&lt;br /&gt;
*&amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; Dient der Unterscheidung zwischen mehreren GetNumeric-Anfragemöglichkeiten für dasselbe Gerät (auch relevant für SetNumeric-Anweisungen).&lt;br /&gt;
&lt;br /&gt;
Mögliche Abfragetypen:&lt;br /&gt;
*&amp;lt;code&amp;gt;humidity&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;battery&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;brightness&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;desired-temp&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;setTarget&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;soilMoisture&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;temperature&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;volume&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;waterLevel&amp;lt;/code&amp;gt;&lt;br /&gt;
Aus dem Abfragetypen ergibt sich die von RHASSPY ausgewählte Antwort.&lt;br /&gt;
&lt;br /&gt;
Beispiel Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
what is the temperature in the living room&lt;br /&gt;
how bright is the floor lamp&lt;br /&gt;
what is the volume of the tv&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
[en.fhem:GetNumeric]&lt;br /&gt;
#actual temperature&lt;br /&gt;
(what is|how high is) the temperature{Type:temperature} [$de.fhem.Device-GetNumeric{Device}] [$de.fhem.Room{Room}]&lt;br /&gt;
&lt;br /&gt;
#desired-temperature&lt;br /&gt;
\[what is the|how high is the] (desired temperature){Type:desired-temp} [$de.fhem.Device-GetNumeric{Device}] [$de.fhem.Room{Room}]&lt;br /&gt;
&lt;br /&gt;
#volume&lt;br /&gt;
(what is the|how high is the) volume{Type:volume} $de.fhem.Device-GetNumeric{Device} [$de.fhem.Room{Room}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Type&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional tags&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== GetState ===&lt;br /&gt;
Intent to get specific information of a device. The respone can be defined.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
GetState:response=&amp;quot;Temperature is [$DEVICE:temp] degree at [Thermo:hum] percent humidity&amp;quot;&lt;br /&gt;
GetState:response={my $value=ReadingsVal(&amp;quot;$DEVICE&amp;quot;,&amp;quot;brightness&amp;quot;,&amp;quot;&amp;quot;); return &amp;quot;Brightness is $value&amp;quot;;}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Options:&lt;br /&gt;
*&amp;lt;code&amp;gt;response&amp;lt;/code&amp;gt; Text for the response Rhassyp will give.&lt;br /&gt;
:To use values from FHEM use format [Device:Reading].&lt;br /&gt;
:A comma within the response has to be escaped (\, instead of ,).&lt;br /&gt;
:Or you can use Perl-code enclosed in curley brackets to define the response.&lt;br /&gt;
:Mixing text and Perl-code is not supported.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
How is the state of the thermostat in the kitchen&lt;br /&gt;
state light in livingroom&lt;br /&gt;
state washer&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:GetState]&lt;br /&gt;
\[how is the] (state) $de.fhem.Device{Device} [$de.fhem.Room{Room}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== MediaControls ===&lt;br /&gt;
Intent to control media devices&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mapping:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
MediaControls:cmdPlay=play,cmdPause=pause,cmdStop=stop,cmdBack=previous,cmdFwd=next&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Options:&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdPlay&amp;lt;/code&amp;gt; Play command of the device. See chapter Formatting Commands and Readings inside a rhasspyMapping.&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdPause&amp;lt;/code&amp;gt; Command to pause the device.&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdStop&amp;lt;/code&amp;gt; Command to stop the device.&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdFwd&amp;lt;/code&amp;gt; Command to skip to the next track/channel/etc.&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdBack&amp;lt;/code&amp;gt; Command to skip to the previous track/channel/etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note on issuing a voice-command without a room-name:&lt;br /&gt;
As described in the SetNumeric-Intent, it is recommended to define a GetOnOff-Mapping to use the MediaControls-Intent without a room name.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
skip to next track on the radio&lt;br /&gt;
pause&lt;br /&gt;
skip video on the dvd player&lt;br /&gt;
stop playback&lt;br /&gt;
next&lt;br /&gt;
previous&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:MediaControls]&lt;br /&gt;
(start){Command:cmdPlay} the playback [$de.fhem.Device-MediaControls{Device}]&lt;br /&gt;
(stop){Command:cmdStop} the playback [$de.fhem.Device-MediaControls{Device}]&lt;br /&gt;
(pause){Command:cmdPause} the playback [$de.fhem.Device-MediaControls{Device}]&lt;br /&gt;
(next){Command:Fwd} (song|title) [$de.fhem.Device-MediaControls{Device}]&lt;br /&gt;
(previous){Command:Back} (song|title) [$de.fhem.Device-MediaControls{Device}] [$de.fhem.Room{Room}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Command&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== MediaChannels ===&lt;br /&gt;
Intent to change radio-/tv channels, favorites, playlists, lightscenes, ...&lt;br /&gt;
&lt;br /&gt;
Instead of using the attribute rhasspyMapping, this intent is configured with an own attribute [[#rhasspyChannels]] in the respective device. Reason is the multiple-line-configuration.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
SWR3=favorite s_w_r_3&lt;br /&gt;
SWR1=favorite s_w_r_1&lt;br /&gt;
ARD=channel 204&lt;br /&gt;
Netflix=launchApp Netflix&lt;br /&gt;
Leselicht=set lightSceneWz scene Leselicht&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Notice on using the commands without a device name:&lt;br /&gt;
To start playback on a device without specifying the device name in the voice command, the module needs to know, which device should be used. Therefor it searches the attribute rhasspyChannels for suitable one. Devices in the actual or spoken room are preferred.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
play CNN on the radio in my office&lt;br /&gt;
switch to HBO&lt;br /&gt;
change channel on radio to BBC news&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[en.fhem:MediaChannels]&lt;br /&gt;
\[(play|switch to|change to)] ($de.fhem.MediaChannels){Channel} [($de.fhem.Device){Device}] [($de.fhem.Room){Room}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Channel&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetColor ===&lt;br /&gt;
Intent to change light colors&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Because of the multi-line settings, instead of configuring this intent with the attribute rhasspyMapping, a separate user-attribute [[#rhasspyColors]] is used.&lt;br /&gt;
&lt;br /&gt;
The content of the rhasspyColors uses the following format:&lt;br /&gt;
&amp;lt;code&amp;gt;Colorname=cmd&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Settings:&lt;br /&gt;
*&amp;lt;code&amp;gt;Colorname&amp;lt;/code&amp;gt; The name of the color you want to use in a voice-command&lt;br /&gt;
*&amp;lt;code&amp;gt;cmd&amp;lt;/code&amp;gt; The FHEM-command&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
red=rgb FF0000&lt;br /&gt;
green=rgb 00FF00&lt;br /&gt;
blue=rgb 0000FF&lt;br /&gt;
white=ct 3000&lt;br /&gt;
warm white=ct 2700&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
change light to green&lt;br /&gt;
lightstrip blue&lt;br /&gt;
color the light in the sleeping room white&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[en.fhem:SetColor]&lt;br /&gt;
\[change|color] $de.fhem.Device{Device} [$de.fhem.Room{Room}] $de.fhem.Color{Color}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Color&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional tags&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetColorGroup ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetScene ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GetTime ===&lt;br /&gt;
Intent um die Uhrzeit zu erfragen.&lt;br /&gt;
&lt;br /&gt;
Es werden keine Konfigurationen in FHEM benötigt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
wie spät ist es?&lt;br /&gt;
sag mir die uhrzeit&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:GetTime]&lt;br /&gt;
wie spät [ist es]&lt;br /&gt;
sag mir die uhrzeit&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GetDate ===&lt;br /&gt;
Intent um das aktuelle Datum zu erfragen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Keine FHEM Einstellungen nötig.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Satz:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
welcher tag ist heute&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:GetDate]&lt;br /&gt;
welcher tag ist heute&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetTimer ===&lt;br /&gt;
Intent to create a timer/countdown/alarm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This intent creates an AT-command in FHEM with the given time and - currently - speaks the sentences &amp;quot;timer expired&amp;quot; when it has expired.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
No FHEM-settings needed&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
Set timer in bedroom to five minutes&lt;br /&gt;
Set countdown in the kitchen to two hours&lt;br /&gt;
set timer to five and a half hours&lt;br /&gt;
set alarm to 5 o&#039; clock&lt;br /&gt;
set timer to 3 hours and 20 minutes&lt;br /&gt;
set timer to 1 hour, 30 minutes and 15 seconds&lt;br /&gt;
stop the timer in bedroom&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentence:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetTimer]&lt;br /&gt;
labels=(alarm|teetimer|countdown|timer)&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in) [((1..60){Hour!int} (hour|hours))] [and] [((1..60){Min!int} (minute|minutes))] [and] [((1..60){Sec!int} (second|seconds))]&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in) (1..60){Hour!int} and (a quarter{Min:15}|a half{Min:30}|three quarters{Min:45}) (hour|hours)&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in) (1..60){Min!int} and (a quarter{Sec:15}|a half{Sec:30}|three quarters{Sec:45}) (minute|minutes)&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in) ((the fourth){Min:15}|(half a){Min:30}|(three fourth){Min:45}) (hour)&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in) ((the fourth){Min:15}|(half a){Min:30}|(three fourth){Min:45}) (minute)&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in|at) (1..24){Hourabs!int} [(1..60){Min!int}] o clock&lt;br /&gt;
&lt;br /&gt;
(cancel|remove|stop|delete){CancelTimer} [&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags to set a timer:&lt;br /&gt;
*&amp;lt;code&amp;gt;Label&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Hour&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Hourabs&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Min&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Sec&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags to cancel a timer:&lt;br /&gt;
*&amp;lt;code&amp;gt;Label&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
rhasspyTweaks for Timer:&lt;br /&gt;
*&amp;lt;code&amp;gt;[[#attr-rhasspytweaks-timerlimits|timerLimits]]&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;[[#attr-rhasspytweaks-timersounds|timerSounds]]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetMute ===&lt;br /&gt;
Intent to disable/enable the processing of intents on a specific siteId. Rhasspy will still listen to the wakeword but will not process any intents.&lt;br /&gt;
&lt;br /&gt;
This intents creates a Reading &amp;lt;code&amp;gt;mute_siteId&amp;lt;/code&amp;gt; for every siteId it get&#039;s a voice-command from.&lt;br /&gt;
&lt;br /&gt;
No FHEM-settings needed&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
good night&lt;br /&gt;
be quiet&lt;br /&gt;
good morning&lt;br /&gt;
make noise&lt;br /&gt;
start listening&lt;br /&gt;
stop listening&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetMute]&lt;br /&gt;
(good night|be quiet){Value:on}&lt;br /&gt;
(good morning|make noise){Value:off}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hinweis: Die Felder &amp;lt;code&amp;gt;{Value:on}&amp;lt;/code&amp;gt; bzw. &amp;lt;code&amp;gt;{Value:off}&amp;lt;/code&amp;gt; sind verpflichtend und &#039;&#039;case sensitive&#039;&#039;, der Wert &#039;&#039;on&#039;&#039; bzw. &#039;&#039;off&#039;&#039; ist in Englisch anzugeben!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ConfirmAction ===&lt;br /&gt;
Dies ist - wie die drei folgenden Intents &#039;&#039;CancelAction&#039;&#039;, &#039;&#039;ChoiceRoom&#039;&#039; und &#039;&#039;ChoiceDevice&#039;&#039; auch - ein Intent, der im Rahmen von Dialogen benötigt wird. Siehe dazu auch [[RHASSPY/Vertiefung#Dialoge|Vertiefung - Dialoge]].&lt;br /&gt;
Rückgabe ist zwingend &amp;lt;code&amp;gt;{Mode}&amp;lt;/code&amp;gt; mit dem Wert &#039;&#039;OK&#039;&#039;, alles andere wird so behandelt, als wäre der Intent &#039;&#039;CancelAction&#039;&#039; ausgewählt worden.&lt;br /&gt;
&lt;br /&gt;
=== CancelAction ===&lt;br /&gt;
Siehe &#039;&#039;ConfirmAction&#039;&#039;. Dieser Intent muss nicht zwingend existieren, es kann auch ein unpassender Rückgabewert in &#039;&#039;ConfirmAction&#039;&#039; angegeben werden, um die Abbruch-Routinen für Dialoge zu starten.&lt;br /&gt;
&lt;br /&gt;
=== ChoiceRoom ===&lt;br /&gt;
Siehe &#039;&#039;ConfirmAction&#039;&#039;. Dient im Rahmen von Dialogen der Auswahl eines Raums.&lt;br /&gt;
&lt;br /&gt;
=== ChoiceDevice ===&lt;br /&gt;
Siehe &#039;&#039;ConfirmAction&#039;&#039;. Dient im Rahmen von Dialogen der Auswahl eines Gerätes.&lt;br /&gt;
&lt;br /&gt;
=== ReSpeak ===&lt;br /&gt;
Wiederholt den letzten Satz, den Rhasspy gesprochen hat. Um genauer zu sein: Spricht den Inhalt des FHEM Readings &amp;lt;code&amp;gt;voiceResponse&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Keine Einstellungen in FHEM benötigt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
was hast du gesagt&lt;br /&gt;
kannst du das wiederholen&lt;br /&gt;
ich habe dich nicht verstanden&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:ReSpeak]&lt;br /&gt;
was hast du gesagt&lt;br /&gt;
kannst du das [bitte] wiederholen&lt;br /&gt;
ich habe dich nicht verstanden&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Eigene Intents erstellen ==&lt;br /&gt;
Es ist auch möglich, eigene Intents zu erstellen, sollten die hier vorgestellten nicht reichen. Dafür gibt es zwei Wege: Für kleinere Intents können die Möglichkeiten von FHEMs [[99_myUtils_anlegen|99_myUtils.pm]] genutzt werden. Aufwendigere Intents können in jeweils eigenen Dateien abgelegt werden, die dann von RHASSPY ausgelesen werden.&lt;br /&gt;
=== Intents in 99_myUtils.pm ===&lt;br /&gt;
&lt;br /&gt;
Hier ein (veraltetes, siehe oben) Beispiel, mit dem die letzte &#039;&#039;voice response&#039;&#039; wiederholt werden kann.&lt;br /&gt;
&lt;br /&gt;
Ergänze deine 99_myUtils.pm mit folgender Funktion:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub Respeak(){&lt;br /&gt;
  #Credits to JensS&lt;br /&gt;
  my $name = &amp;quot;Rhasspy&amp;quot;; #Replace &amp;quot;Rhasspy&amp;quot; with the name of your RHASSPY-Device&lt;br /&gt;
  my $response = ReadingsVal($name,&amp;quot;voiceResponse&amp;quot;,&amp;quot;Ich kann mich leider nicht erinnern&amp;quot;);&lt;br /&gt;
  return $response;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ergänze im Attribut &#039;&#039;rhasspyIntents&#039;&#039; folgende Zeile (je Intent muss eine eigene Zeile verwendet werden):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
Respeak=Respeak()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ergänze einen neuen Intent in deinen &#039;&#039;sentence.ini&#039;&#039; an der Rhasspy base:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:Respeak]&lt;br /&gt;
was hast du gesagt&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Intents in eigenen Dateien ===&lt;br /&gt;
Beispiele: https://github.com/fhem/fhem-rhasspy/blob/main/FHEM/99_RHASSPY_Utils_Demo.pm&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: Raumwechsel ====&lt;br /&gt;
Erforderlichen Code in das Modulverzeichnis holen und laden: &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;{ Svn_GetFile(&#039;contrib/RHASSPY/99_RHASSPY_Utils_siteId2room.pm&#039;, &#039;FHEM/99_RHASSPY_Utils_siteId2room.pm&#039;,sub(){ RHASSPY_Utils_siteId2room_Initialize() }) }&amp;lt;/syntaxhighlight&amp;gt;Ergänze im Attribut &#039;&#039;rhasspyIntents&#039;&#039; folgende Zeile (je Intent muss eine eigene Zeile verwendet werden):&lt;br /&gt;
&amp;lt;syntaxhighlight  lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
siteId2room=RHASSPY::siteId2room::siteId2room(NAME,DATA)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Ergänze einen neuen Intent in deinen &#039;&#039;sentence.ini&#039;&#039; an der Rhasspy base:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:siteId2room]&lt;br /&gt;
( Ortswechsel  | begib dich ) ( ins | in den ) $de.fhem.Room{Room}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tipps &amp;amp; Tricks ==&lt;br /&gt;
===Custom Converter für reelle Zahlen===&lt;br /&gt;
{{Randnotiz|RNTyp=Fehl|RNText=Derzeit funktioniert der Konverter aufgrund eines Fehlers in Rhasspy nicht}}&lt;br /&gt;
Rhasspy kann (derzeit) keine gesprochenen reellen Nummern (z.B. 22,5) als Nummer erkennen. Stattdessen interpretiert es die Zahl als zwei Nummern und einen Punkt.&lt;br /&gt;
&lt;br /&gt;
Um reelle Nummern richtig zu verwenden, muss ein [https://rhasspy.readthedocs.io/en/latest/training/#converters Custom Converter] erstellt und in der sentences.ini verwendet werden.&lt;br /&gt;
&lt;br /&gt;
So ein Konverter kann erstellt werden, in dem unter &amp;lt;code&amp;gt;&amp;lt;profile&amp;gt;/converters&amp;lt;/code&amp;gt; ein neues File mit beliebigem Namen angelegt wird. Der Name muss aber dann auch genau so als Converter in der sentences.ini verwendet werden. Anschließend muss die Datei noch ausführbar gemacht werden.&lt;br /&gt;
&lt;br /&gt;
Z.B.:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
touch .config/rhasspy/profile/en/converters/customFloat&lt;br /&gt;
chmod +x .config/rhasspy/profile/en/converters/customFloat&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Folgender Beispiel-Code kann danach in die Datei geschrieben werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python3&lt;br /&gt;
import sys&lt;br /&gt;
import json&lt;br /&gt;
&lt;br /&gt;
# von Rhasspy als JSON übergebene/n Wert/e einlesen&lt;br /&gt;
args = json.load(sys.stdin)&lt;br /&gt;
&lt;br /&gt;
# wenn im deserialisierten JSON nur ein Wert ist, wird der als Ergebnis genommen&lt;br /&gt;
# sind mehrere Werte vorhanden (z.B. 22,.,5), werden die zu einem einzelnen String zusammen gesetzt&lt;br /&gt;
if type(args) == int:&lt;br /&gt;
    num = args&lt;br /&gt;
else:&lt;br /&gt;
    num = &amp;quot;&amp;quot;.join(str(s).strip() for s in args)&lt;br /&gt;
&lt;br /&gt;
# Ergebnis wird an Rhasspy übergeben&lt;br /&gt;
print(num)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nach einem Neustart von Rhasspy kann dieser Converter dann verwendet werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem.SetNumeric]&lt;br /&gt;
stelle die heizung auf (0..30 [komma:. 0..99]){Value!customFloat}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rhasspy speaks actual state of device after switching it===&lt;br /&gt;
JensS wrote a short script to let Rhasspy speak the actual state of a FHEM-device after switching it with a voice-command.&lt;br /&gt;
Add the following to your 99_myUtils.pm&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub ResponseOnOff($){&lt;br /&gt;
  my ($dev) = @_;&lt;br /&gt;
  my $room;&lt;br /&gt;
  my $state = lc(ReadingsVal($dev,&amp;quot;state&amp;quot;,&amp;quot;in unknown state&amp;quot;));&lt;br /&gt;
  my $name = (split(/,/,AttrVal($dev,&amp;quot;rhasspyName&amp;quot;,&amp;quot;error&amp;quot;)))[0];&lt;br /&gt;
  if (AttrVal($dev,&amp;quot;rhasspyRoom&amp;quot;,&amp;quot;&amp;quot;)){$room = &amp;quot; in &amp;quot;.(split(/,/,AttrVal($dev,&amp;quot;rhasspyRoom&amp;quot;,&amp;quot;&amp;quot;)))[0]};&lt;br /&gt;
  $state=~s/.*on/turned on/;&lt;br /&gt;
  $state=~s/.*off/turned off/;&lt;br /&gt;
  return &amp;quot;Ok - &amp;quot;.$name.$room.&amp;quot; is now &amp;quot;.$state&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
and add a response to the SetOnOff-Mapping of a device&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
SetOnOff:cmdOn=on,cmdOff=off,response={ResponseOnOff($DEVICE)}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [https://github.com/rhasspy/rhasspy Rhasspy auf Github]&lt;br /&gt;
* [https://rhasspy.readthedocs.io/en/latest/ offizielle Rhasspy Doku-Seite]&lt;br /&gt;
* [https://community.rhasspy.org/ Offizielles Rhasspy Forum]&lt;br /&gt;
* [https://github.com/fhem/fhem-rhasspy fhem-rhasspy Modul auf GitHub]&lt;br /&gt;
* [https://github.com/Romkabouter/ESP32-Rhasspy-Satellite ESP32-basierte Hardware als Satelliten]&lt;br /&gt;
* [https://github.com/razzo04/rhasspy-mobile-app App für Android-Satelliten]&lt;br /&gt;
* [https://www.youtube.com/watch?v=sWVl0ZoXZEo Video zu sentences.ini]&lt;br /&gt;
[[Kategorie:Sprachsteuerung]]&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=RHASSPY&amp;diff=36945</id>
		<title>RHASSPY</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=RHASSPY&amp;diff=36945"/>
		<updated>2022-01-04T16:24:43Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: /* Custom Converter für reelle Zahlen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
Diese Seite beschreibt die Konfiguration und Verwendung des Moduls 10_RHASSPY.pm. &lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=Anbindung von FHEM an den Rhasspy Sprachassistenten&lt;br /&gt;
|ModType=contrib&lt;br /&gt;
|ModCmdRef=RHASSPY&lt;br /&gt;
|ModForumArea=Frontends/Sprachsteuerung&lt;br /&gt;
|ModFTopic=119447&lt;br /&gt;
|ModTechName=10_RHASSPY.pm&lt;br /&gt;
|ModOwner=Beta-User ({{Link2FU|9229|Forum}}/[[Benutzer Diskussion:Beta-User|Wiki]]), drhirn ({{Link2FU|15727|Forum}}/[[Benutzer Diskussion:Drhirn|Wiki]])&lt;br /&gt;
}}&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
[https://github.com/rhasspy/rhasspy Rhasspy] ist eine Open Source Server-Lösung für Spracherkennung und Sprachsteuerung, welche auf einem RaspBerry Pi oder einem anderen Debian-basierten Serversystem lauffähig ist. Es handelt sich dabei um eine Sammlung von Programmen (=Skripten in der Python-Sprechweise), die unter einer einheitlichen und sehr  flexiblen Benutzungsoberfläche zusammengefasst sind. Die Besonderheit an Rhasspy ist, dass es nach der Installation komplett offline betrieben werden kann. Es werden also keine Daten an einen Server im Internet geschickt, und für den Betrieb nur für FHEM werden nur moderate Hardwareanforderungen gestellt - ein aktueller Raspberry Pi ab Modell 3B+ sollte in der Regel genügen.&lt;br /&gt;
&lt;br /&gt;
Die Anbindung weiterer Räume ist über sogenannte &amp;quot;Satelliten&amp;quot; möglich. Dies kann z.B. ein Pi Zero mit Mikro und Lautsprecher sein, ein ESP32 mit entsprechender Hardware oder ein Mobiltelefon mit Android und der entsprechenden App.&lt;br /&gt;
&lt;br /&gt;
Rhasspy besteht aus vielen unterschiedlichen Modulen (Hot-Word Erkennung, Text-to-Speech, Speech-to-Text, Intent Erkennung, etc.). Alle diese Module kommunizieren miteinander über das [[MQTT|MQTT]]-Protokoll.&lt;br /&gt;
&lt;br /&gt;
Das Modul [[RHASSPY]] prüft Teile des MQTT-Traffics, konvertiert diese JSON-Nachrichten in FHEM-Befehle und sendet Nachrichten zurück an Rhasspy um z.B. Antworten über Text-to-Speech auszugeben.&lt;br /&gt;
&lt;br /&gt;
RHASSPY verwendet das Modul 00_MQTT2_CLIENT.pm um Nachrichten zu empfangen und zu senden. Daher ist es notwendig, eine Instanz dieses Moduls als FHEM-Device zu erstellen, bevor RHASSPY verwendet werden kann.&lt;br /&gt;
&lt;br /&gt;
Hervorgegangen ist RHASSPY aus dem Snips-Modul, nachdem Snips an Sonos verkauft und anschließend eingestellt wurde. Danke also an Thyraz, der die grundlegenden Arbeiten erledigt hat!&lt;br /&gt;
&lt;br /&gt;
=== Konventionen ===&lt;br /&gt;
{{Hinweis| In diesem Artikel und der CommandRef werden folgende Schreibweisen verwendet:&lt;br /&gt;
* &#039;&#039;&#039;[[RHASSPY]]&#039;&#039;&#039; bezieht sich auf das FHEM-Modul&lt;br /&gt;
* &#039;&#039;&#039;rhasspy&#039;&#039;&#039; bezieht sich auf das das FHEM-Device&lt;br /&gt;
* &#039;&#039;&#039;Rhasspy&#039;&#039;&#039; bezeichnet die (zentrale) Serverinstallation}}&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|Dialoge werden in RHASSPY verwaltet wie [https://rhasspy.readthedocs.io/en/latest/reference/#dialogue-manager hier] beschrieben. Dialoge werden also nicht funktionieren, sobald für das Dialogue-Management etwas anderes als &#039;&#039;RHASSPY&#039;&#039; eingestellt ist}}&lt;br /&gt;
&lt;br /&gt;
=== Erste Schritte ===&lt;br /&gt;
Die Installation und Erstinbetriebnahme von Rhasspy wird in einer Schnellstart-Anleitung erklärt: [[RHASSPY/Schnellstart]] Diese Anleitung sollte auch befolgt werden, wenn man sich sehr gut mit FHEM auskennt. Wer dies erfolgreich absolviert hat, kann gleich zu Abschnitt [[#Set-Befehle_.28SET.29|Set-Befehle (SET)]] weiterspringen, und/oder die [[RHASSPY/Vertiefung|Vertiefung]] durcharbeiten.&lt;br /&gt;
&lt;br /&gt;
=== Details zur Verwaltung des RHASSPY Moduls ===&lt;br /&gt;
Das Modul ist derzeit nicht in der &amp;quot;offiziellen&amp;quot; FHEM Distribution enthalten und muss daher manuell installiert werden. Dafür gibt es zwei Möglichkeiten.&lt;br /&gt;
&lt;br /&gt;
*Im Subversion Repository, kurz SVN von FHEM ist die jeweils aktuelle &amp;quot;stable&amp;quot; Version des Moduls im &#039;&#039;contrib&#039;&#039;-Zweig zu finden. Diese kann mit folgendem Befehl, der im FHEM Befehls-Eingabefeld einzugeben ist, heruntergeladen werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;{ Svn_GetFile(&#039;contrib/RHASSPY/10_RHASSPY.pm&#039;, &#039;FHEM/10_RHASSPY.pm&#039;) }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Genauere Informationen zu dieser Vorgangsweise finden sich unter [[Update#Einzelne_Dateien_aus_dem_SVN_holen]]. Nach Installation des Moduls muss FHEM neu gestartet werden.&lt;br /&gt;
*FHEM Update und GitHub&lt;br /&gt;
Im GitHub-Repository des Moduls gibt es zwei Branches &#039;&#039;main&#039;&#039; und &#039;&#039;dev&#039;&#039;. In &#039;&#039;main&#039;&#039; ist die stabile Version des Moduls, in &#039;&#039;dev&#039;&#039; die jeweils aktuelle Entwicklungsversion. Aus Gründen der Stabilität ist natürlich die aus &#039;&#039;main&#039;&#039; zu bevorzugen.&lt;br /&gt;
&lt;br /&gt;
Um das Modul zu installieren bzw. zu aktualisieren, kann der &#039;&#039;update&#039;&#039;-Mechanismus von FHEM genutzt werden. Dazu muss das Repository in der Liste der vom update-Befehl verarbeiteten Repositorien aufgenommen werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;update add https://raw.githubusercontent.com/fhem/fhem-rhasspy/main/controls_fhem-rhasspy.txt&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Anschließend kann mit folgendem Befehl das Modul installiert oder aktualisiert werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;update all https://raw.githubusercontent.com/fhem/fhem-rhasspy/main/controls_fhem-rhasspy.txt&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wählt man diesen Weg, wird das Modul auch automatisch aktualisiert, wenn ein Update von FHEM durchgeführt wird. Möchte man die Entwicklungsversion verwenden, muss in den beiden Befehlen &#039;&#039;main&#039;&#039; durch &#039;&#039;dev&#039;&#039; ersetzt werden.&lt;br /&gt;
&lt;br /&gt;
Weitere Informationen zu dieser Vorgangsweise in der stehen in der [https://fhem.de/commandref.html#update CommandRef] oder im [[Update|FHEM-Wiki]].&lt;br /&gt;
&lt;br /&gt;
Nach Installation des Moduls muss FHEM neu gestartet werden.&lt;br /&gt;
&lt;br /&gt;
== Einrichtung MQTT2_CLIENT ==&lt;br /&gt;
Rhasspy kommuniziert hauptsächlich über das [[MQTT]]-Protokoll. Und zwar sowohl Rhasspy-intern, wie auch mit FHEM. Da dies auch für die übertragene Sprache und Audio-Dateien gilt und es daher zu sehr viel MQTT-Verkehr kommt, sollte der Rhasspy-interne MQTT-Server verwendet werden. Daher ist die Einrichtung eines [[MQTT2_CLIENT]]-Devices notwendig, um die für FHEM relevanten Daten zu beziehen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zuerst muss ein MQTT2_CLIENT Device erstellt werden, welches sich mit dem MQTT-Server (Mosquitto) von Rhasspy verbindet:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;define &amp;lt;deviceName&amp;gt; MQTT2_CLIENT &amp;lt;ip-oder-hostname-des-mqtt-servers&amp;gt;:&amp;lt;port&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anschließend wird die &#039;&#039;clientOrder&#039;&#039; gesetzt, um die richtige Benachrichtigungsreihenfolge einzustellen. Wird das MQTT2_CLIENT Device nur für RHASSPY verwendet, reicht hier die Angabe &amp;lt;code&amp;gt;RHASSPY&amp;lt;/code&amp;gt;. Ansonsten müssen noch alle anderen Devices (z.B. &amp;lt;code&amp;gt;MQTT_GENERIC_BRIDGE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;MQTT2_DEVICE&amp;lt;/code&amp;gt;) angegeben werden.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;attr &amp;lt;deviceName&amp;gt; clientOrder RHASSPY [device2] [device3]&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Um die Topics einzuschränken, die das Device abonniert, müssen diese angegeben werden. Wird der MQTT-Server nur für RHASSPY verwendet, reicht die Angabe &amp;lt;code&amp;gt;setByTheProgram&amp;lt;/code&amp;gt;. Ansonsten müssen alle für RHASSPY notwendigen Topics eingefügt werden.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;attr &amp;lt;deviceName&amp;gt; subscriptions setByTheProgram&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
bzw.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;attr &amp;lt;deviceName&amp;gt; subscriptions hermes/intent/+ hermes/dialogueManager/sessionStarted hermes/dialogueManager/sessionEnded hermes/nlu/intentNotRecognized hermes/hotword/+/detected&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Beispiele&lt;br /&gt;
* Rhasspy-interner MQTT-Server wird mit seinem Standard-Port verwendet. Rhasspy läuft auf der selben Maschine wie FHEM. MQTT2_CLIENT wird nur für RHASSPY verwendet.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod rhasspyMQTT2 MQTT2_CLIENT localhost:12183&lt;br /&gt;
attr rhasspyMQTT2 clientOrder RHASSPY&lt;br /&gt;
attr rhasspyMQTT2 subscriptions setByTheProgram&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*Rhasspy läuft auf einem eigenen Server und verwendet einen externen MQTT Server mit eigener Port-Einstellung. MQTT2_CLIENT wird für RHASSPY, aber auch MQTT_GENERIC_BRIDGE und MQTT2_DEVICE verwendet.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod rhasspyMQTT2 MQTT2_CLIENT 192.168.1.122:1884&lt;br /&gt;
attr rhasspyMQTT2 clientOrder RHASSPY MQTT_GENERIC_BRIDGE MQTT2_DEVICE&lt;br /&gt;
attr rhasspyMQTT2 subscriptions hermes/intent/+ hermes/dialogueManager/sessionStarted hermes/dialogueManager/sessionEnded hermes/nlu/intentNotRecognized hermes/hotword/+/detected [zusätzliche Subscriptions für andere MQTT-Module]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Definition von RHASSPY (DEF)==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;define &amp;lt;name&amp;gt; RHASSPY &amp;lt;baseUrl&amp;gt; &amp;lt;devspec&amp;gt; &amp;lt;defaultRoom&amp;gt; &amp;lt;language&amp;gt; &amp;lt;fhemId&amp;gt; &amp;lt;prefix&amp;gt; &amp;lt;useGenericAttrs&amp;gt; &amp;lt;handleHotword&amp;gt; &amp;lt;encoding&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
{{Randnotiz|RNTyp=Info|RNText=RHASSPY verwendet sehr oft &amp;lt;parseParams&amp;gt;. Nicht nur im Define, sondern z.B. auch, um Attribut-Werte auszuwerten. Es sollten also alle Parameter im Define in der Form key=value angegeben werden.).}}{{Randnotiz|RNTyp=Info|RNText=RHASSPY führt jede Menge Daten aus unterschiedlichen Quellen zusammen um seine Funktion erfüllen zu können. Die endgültige Daten-Struktur, die RHASSPY verwendet, kann mittels des [[List|list]]-Kommandos angezeigt werden. Es wird empfohlen, sich diese Daten-Struktur auf jeden Fall anzusehen. Vor allem dann, wenn etwas nicht wie gewünscht funktioniert.}}&lt;br /&gt;
Alle Parameter sind &#039;&#039;&#039;optional&#039;&#039;&#039;. Die meisten werden im Normalfall gar nicht benötigt (z.B. &amp;lt;code&amp;gt;fhemId&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;prefix&amp;lt;/code&amp;gt;). Sollten sie aber verwendet und später geändert werden, kann es zu unvorhergesehenem Verhalten kommen. Speziell beim Einstieg in das Thema RHASSPY sollten nicht mehr, als die ersten drei verwendet werden. Ausgenommen eventuell noch &amp;lt;code&amp;gt;language&amp;lt;/code&amp;gt;, möchte man eine andere Sprache als Englisch oder Deutsch verwenden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;def-baseurl&amp;quot;&amp;gt;baseUrl&amp;lt;/code&amp;gt;&lt;br /&gt;
:Die URL zum Rhasspy-Webservice. Sollten eine Base und mehrere Satelliten verwendet werden, die URL zur Base. Bitte sicherstellen, dass die Adresse richtig ist (IP und Port)! Default ist &amp;lt;code&amp;gt;baseUrl=http://127.0.0.1:12101&amp;lt;/code&amp;gt;.&lt;br /&gt;
;&amp;lt;code id=&amp;quot;def-devspec&amp;quot;&amp;gt;devspec&amp;lt;/code&amp;gt;&lt;br /&gt;
:devspec der Geräte, die mit Rhasspy gesteuert werden sollen. Wenn der &#039;&#039;genericDeviceType&#039;&#039;-Support aktiviert ist, ist der Default &amp;lt;code&amp;gt;devspec=genericDeviceType=.+&amp;lt;/code&amp;gt;, sonst wird &amp;lt;code&amp;gt;devspec=room=Rhasspy&amp;lt;/code&amp;gt; verwendet. Ohne ein passendes Match in der devspec wird kein Gerät mit dem Modul interagieren, egal, ob sonst irgendwelche RHASSPY-spezifischen Attribute beim Gerät gesetzt sind. Genauere Informationen, wie z.B. eine Liste von Geräten oder Kombinationen aus Geräten und Räumen (z.B. &amp;lt;code&amp;gt;devspec=room=livingroom,room=bathroom,bedroomlamp&amp;lt;/code&amp;gt;) verwendet werden können, finden sich in der [https://commandref.fhem.de/commandref.html#devspec CommandRef].&lt;br /&gt;
;&amp;lt;code id=&amp;quot;def-defaultroom&amp;quot;&amp;gt;defaultRoom&amp;lt;/code&amp;gt;&lt;br /&gt;
:Der Name des Standard-Raumes, der verwendet wird, wenn im Sprachkommando kein Raum enthalten ist und auch kein passender für das Device gefunden werden kann. Default ist &amp;lt;code&amp;gt;defaultRoom=default&amp;lt;/code&amp;gt;.&lt;br /&gt;
;&amp;lt;code id=&amp;quot;def-language&amp;quot;&amp;gt;language&amp;lt;/code&amp;gt;&lt;br /&gt;
:Sprache, in der mit Rhasspy gesprochen wird. Der Standard-Wert hängt vom &#039;&#039;global&#039;&#039;-Device ab. Dieser ist standardmäßig &amp;lt;code&amp;gt;language=en&amp;lt;/code&amp;gt;.&lt;br /&gt;
;&amp;lt;code id=&amp;quot;def-fhemid&amp;quot;&amp;gt;fhemId&amp;lt;/code&amp;gt;&lt;br /&gt;
:Wird verwendet um auf MQTT-Seite zwischen mehreren Installationen des RHASSPY-Moduls zu unterscheiden. Ist auch ein Teil des Topic-Trees, auf den die jeweilige RHASSPY-Instanz hört. Default ist &amp;lt;code&amp;gt;fhemId=fhem&amp;lt;/code&amp;gt;.&lt;br /&gt;
;&amp;lt;code id=&amp;quot;def-prefix&amp;quot;&amp;gt;prefix&amp;lt;/code&amp;gt;&lt;br /&gt;
:Wird verwendet um auf FHEM-Seite zwischen mehreren Installationen des RHASSPY-Moduls zu unterscheiden. Praktisch, wenn man mehrere Instanzen von RHASSPY auf einer FHEM Installation laufen hat und z.B. verschiedene Bezeichner für Gruppen und Räume haben möchte (z.B. unterschiedliche Sprachen). Default ist &amp;lt;code&amp;gt;prefix=rhasspy&amp;lt;/code&amp;gt;.&lt;br /&gt;
;&amp;lt;code id=&amp;quot;def-usegenericattrs&amp;quot;&amp;gt;&#039;&#039;&#039;useGenericAttrs&#039;&#039;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
:Üblicherweise verwendet RHASSPY - wie auch einige andere FHEM Module für Sprachassistenten - das Attribut &#039;&#039;genericDeviceType&#039;&#039; um Schaltmöglichkeiten von Geräten automatisch zu erkennen. Dieser Parameter fügt das Attribut &#039;&#039;genericDeviceType&#039;&#039; zur globalen Attributliste hinzu. Der Wert 0 verhindert dieses hinzufügen. Default ist &amp;lt;code&amp;gt;useGenericAttrs=1&amp;lt;/code&amp;gt;.&lt;br /&gt;
;&amp;lt;code id=&amp;quot;def-encoding&amp;quot;&amp;gt;encoding&amp;lt;/code&amp;gt;&lt;br /&gt;
:Sollte es Probleme mit Umlauten geben, kann das Character-Encoding geändert werden. Default ist &amp;lt;code&amp;gt;encoding=utf8&amp;lt;/code&amp;gt;.&lt;br /&gt;
;&amp;lt;code id=&amp;quot;handlehotword&amp;quot;&amp;gt;handleHotword&amp;lt;/code&amp;gt;&lt;br /&gt;
:Triggert das Reading &#039;&#039;hotword&#039;&#039;, wenn ein Hotword erkannt wurde (und erstellt das Reading, falls noch nicht vorhanden). Weitere Informationen dazu stehen beim Attribut [[#attr-rhasspyhotwords|&#039;&#039;rhasspyHotwords&#039;&#039;]]. Default ist &amp;lt;code&amp;gt;handleHotword=0&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|Nach dem Definieren eines RHASSPY-Modules sollte das IODev manuell gesetzt werden um ein automatische IO-Zuweisung zu verhindern. Z.B. &amp;lt;code&amp;gt;attr &amp;lt;deviceName&amp;gt; IODev &amp;lt;m2client&amp;gt;&amp;lt;/code&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
;Beispiele:&lt;br /&gt;
Läuft Rhasspy auf der selben Maschine wie FHEM, die Sprache ist im &#039;&#039;global&#039;&#039;-Device bereits richtig eingestellt und der Standardraum entspricht der siteID, die in Rhasspy vergeben wurde:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;define Rhasspy RHASSPY&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Läuft Rhasspy auf einem anderen System wie FHEM, der Standard-Raum enspricht nicht dem, was Rhasspy liefert, die Sprache soll auch anders sein und es sollen sowohl Geräte mit vorhandenem &#039;&#039;genericDeviceType&#039;&#039; Attribut, als auch die Geräte &#039;&#039;device_a1&#039;&#039; und &#039;&#039;device_xy&#039;&#039; gesteuert werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;define Rhasspy RHASSPY baseUrl=http://192.168.1.210:12101 defaultRoom=&amp;quot;Büro Lisa&amp;quot; language=de devspec=genericDeviceType=.+,device_a1,device_xy handleHotword=1&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Set-Befehle (SET)==&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;set-customslot&amp;quot;&amp;gt;customSlot&amp;lt;/code&amp;gt;&lt;br /&gt;
:Erstellt einen neue - oder überschreibt einen alten - Slot in Rhasspy&lt;br /&gt;
:&amp;lt;code&amp;gt;slotname&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;slotdata&amp;lt;/code&amp;gt; sind verpflichtend&lt;br /&gt;
:&amp;lt;code&amp;gt;overwrite&amp;lt;/code&amp;gt; ist optional. Default ist &amp;lt;code&amp;gt;overwrite=true&amp;lt;/code&amp;gt;. Das Setzen eines anderes Wertes verhindert das Überschreiben einen bereits bestehenden Slot mit gleichem Namen.&lt;br /&gt;
:&amp;lt;code&amp;gt;training&amp;lt;/code&amp;gt; ist optional. Default ist &amp;lt;code&amp;gt;training=true&amp;lt;/code&amp;gt;. Das Setzen eines anderen Wertes verhindert ein Training von Rhasspy nach dem Speichern des Slots.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Beispiele:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; customSlot mySlot a,b,c overwrite training&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; customSlot slotname=mySlot slotdata=a,b,c overwrite=false&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;set-fetchsiteids&amp;quot;&amp;gt;fetchSiteIds&amp;lt;/code&amp;gt;&lt;br /&gt;
:Liest alle in Rhasspy vorhandenen siteIDs aus und speichert sie im Reading &#039;&#039;siteIds&#039;&#039;. Wird z.B. verwendet, um festzustellen, auf welchem Satelliten der User über das Ende eines Timers benachrichtigt werden soll.&lt;br /&gt;
:Muss immer ausgeführt werden, wenn eine neue siteId in Rhasspy hinzugefügt wird (neuer Satellit z.B.).&lt;br /&gt;
:&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; fetchSiteIds&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;set-play&amp;quot;&amp;gt;play&amp;lt;/code&amp;gt;&lt;br /&gt;
:Sendet eine WAV Datei an Rhasspy.&lt;br /&gt;
:&amp;lt;code&amp;gt;siteId&amp;lt;/code&amp;gt; und &amp;lt;path&amp;gt; sind verpflichtend!&lt;br /&gt;
:Optional kann die Anzahl der Wiederholungen (Default: 1) und die Dauer der Pause zwischen den jeweiligen Wiederholungen (Default: 15) angeben werden.&lt;br /&gt;
:&#039;&#039;Beispiele:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; play siteId=&amp;quot;default&amp;quot; path=&amp;quot;/opt/fhem/test.wav&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; play siteId=&amp;quot;default&amp;quot; path=&amp;quot;./test.wav&amp;quot; repeats=3 wait=20&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;set-speak&amp;quot;&amp;gt;speak&amp;lt;/code&amp;gt;&lt;br /&gt;
:Sendet einen Text an das TTS-Sytem, welches ihn dann als Sprache ausgibt.&lt;br /&gt;
:Beide Argumente &amp;lt;code&amp;gt;siteId&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;text&amp;lt;/code&amp;gt; sind verpflichtend!&lt;br /&gt;
:&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; speak siteId=&amp;quot;wohnzimmer&amp;quot; text=&amp;quot;This is a test&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;set-textcommand&amp;quot;&amp;gt;textCommand&amp;lt;/code&amp;gt;&lt;br /&gt;
:Sendet ein Text-Kommando an Rhasspy.&lt;br /&gt;
:&#039;&#039;&#039;Example:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; textCommand schalte das licht ein&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;set-trainrhasspy&amp;quot;&amp;gt;trainRhasspy&amp;lt;/code&amp;gt;&lt;br /&gt;
:Startet das Training von Rhasspy.&lt;br /&gt;
:&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; trainRhasspy&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;set-update&amp;quot;&amp;gt;update&amp;lt;/code&amp;gt;&lt;br /&gt;
:;&amp;lt;code id=&amp;quot;set-update-devicemap&amp;quot;&amp;gt;devicemap&amp;lt;/code&amp;gt;&lt;br /&gt;
::Wenn an der Konfiguration von RHASSPY oder an den von ihm gesteuerten Geräten etwas geändert wurde, muss dieser Befehl ausgeführt werden, um die Datenstruktur von RHASSPY zu aktualisieren, Rhasspy von den Änderungen zu informieren (Slots z.B.), ein Training zu starten, etc.&lt;br /&gt;
::&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update devicemap&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:;&amp;lt;code id=&amp;quot;set-update-devicemaponly&amp;quot;&amp;gt;devicemap_only&amp;lt;/code&amp;gt;&lt;br /&gt;
::Aktualisiert die Datenstruktur von RHASSPY. Es werden weder Slots in Rhasspy geändert, noch das Training gestartet.&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update devicemap_only&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:;&amp;lt;code id=&amp;quot;set-update-slots&amp;quot;&amp;gt;slots&amp;lt;/code&amp;gt;&lt;br /&gt;
::Aktualisiert (bzw. erstellt) alle Slots in Rhasspy mit den aktuellen Geräten, Räumen, usw.&lt;br /&gt;
::Erstellte/Aktualisierte Slots sind z.B.:&lt;br /&gt;
::*de.fhem.AllKeywords&lt;br /&gt;
::*de.fhem.Device&lt;br /&gt;
::*de.fhem.Device-&#039;&#039;genericDeviceType&#039;&#039;&lt;br /&gt;
::*de.fhem.Device-&#039;&#039;Intent&#039;&#039;&lt;br /&gt;
::*de.fhem.Group&lt;br /&gt;
::*de.fhem.Room&lt;br /&gt;
::*de.fhem.MediaChannels&lt;br /&gt;
::*de.fhem.Color&lt;br /&gt;
::*de.fhem.NumericType&lt;br /&gt;
::(Hinweis: Die ersten beiden Teile &#039;&#039;de&#039;&#039; und &#039;&#039;fhem&#039;&#039; hängen von der DEF des RHASSPY-Devices ab)&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update slots&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:;&amp;lt;code id=&amp;quot;set-update-slotsnotraining&amp;quot;&amp;gt;slots_no_training&amp;lt;/code&amp;gt;&lt;br /&gt;
::Wie &amp;lt;code&amp;gt;slots&amp;lt;/code&amp;gt;, aber ohne Training nach dem Update.&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update slots_no_training&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:;&amp;lt;code id=&amp;quot;set-update-language&amp;quot;&amp;gt;language&amp;lt;/code&amp;gt;&lt;br /&gt;
::Liest das das Sprach-File (&#039;&#039;languageFile&#039;&#039;) neu ein.&lt;br /&gt;
::Muss immer ausgeführt werden, wenn in diesem File oder dem Attribut &#039;&#039;languageFile&#039;&#039; etwas geändert wurde!&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update language&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:;&amp;lt;code id=&amp;quot;set-udpate-intentfilter&amp;quot;&amp;gt;intent_filter&amp;lt;/code&amp;gt;&lt;br /&gt;
::Setzt die Intent Filter, die vom Rhasspy Dialogue Manger verwendet werden zurück. Details dazu bei [[#attr-rhasspytweaks-intentfilter|intentFilter]] im &#039;&#039;rhasspyTweaks&#039;&#039;-Attribut.&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update intent_filter&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:;&amp;lt;code id=&amp;quot;set-update-all&amp;quot;&amp;gt;all&amp;lt;/code&amp;gt;&lt;br /&gt;
::Aktualisiert die Devicemap und das languageFile&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update all&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;set-volume&amp;quot;&amp;gt;volume&amp;lt;/code&amp;gt;&lt;br /&gt;
::Stellt die Lautstärke der gewünschten siteId auf einen Wert zwischen 0 and 1 (float).&lt;br /&gt;
::Beide Argumente &amp;lt;code&amp;gt;siteId&amp;lt;/code&amp;gt; &amp;lt;code&amp;gt;volume&amp;lt;/code&amp;gt; sind verpflichtend.&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; siteId=&amp;quot;default&amp;quot; volume=&amp;quot;0.5&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|Bitte nicht vergessen, dass nach jeder Änderung an RHASSPY oder an einem von RHASSPY gesteuerten Gerät ein &amp;lt;code&amp;gt;update devicemap&amp;lt;/code&amp;gt; ausgeführt werden muss!}}&lt;br /&gt;
&lt;br /&gt;
==Attribute (ATTR)==&lt;br /&gt;
Um RHASSPY zum Laufen zu bringen, müssen unterschiedliche Attribute gesetzt werden. Dabei gibt es&lt;br /&gt;
*Attribute, die im RHASSPY-Device selbst gesetzt werden müssen und&lt;br /&gt;
*Attribute, die in den Devices gesetzt werden müssen, die von RHASSPY kontrolliert werden sollen.&lt;br /&gt;
&lt;br /&gt;
Letztere werden im Abschnitt [[#FHEM-Devices für die Verwendung mit Rhasspy konfigurieren|FHEM-Devices für die Verwendung mit Rhasspy konfigurieren]] behandelt.&lt;br /&gt;
&lt;br /&gt;
In diesem Abschnitt werden die Attribute behandelt, die auf das RHASSPY-Device selbst wirken.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;attr-iodev&amp;quot;&amp;gt;IODev&amp;lt;/code&amp;gt;&lt;br /&gt;
:Das MQTT2_CLIENT Device, welches die MQTT-Nachrichten für RHASSPY liefert.&lt;br /&gt;
:&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;attr &amp;lt;rhasspyDevice&amp;gt; IODev rhasspyMQTT2&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;attr-forcenext&amp;quot;&amp;gt;forceNext&amp;lt;/code&amp;gt;&lt;br /&gt;
:Wenn dieses Attribut auf 1 gesetzt ist, leitet RHASSPY eingehende MQTT-Nachrichten an andere MQTT2-IO-Client Module wie MQTT2_DEVICE weiter, auch wenn das Topic zu einem von RHASSPY abonnierten passt.&lt;br /&gt;
:Standardmäßig werden diese Nachrichten nicht weitergeleitet um eine bessere Kompatibilität mit dem &#039;&#039;autocreate&#039;&#039;-Feature des MQTT2_DEVICE sicher zu stellen.&lt;br /&gt;
:Siehe dazu das {{Link2CmdRef|Anker=MQTT2_CLIENT-attr-clientOrder|Lang=en|Label=clientOrder}}-Attribut in der CommandRef zum MQTT2_CLIENT Device.&lt;br /&gt;
:Das Setzen dieses Attributs in einer RHASSPY-Instanz kann auch andere eventuell vorhandene RHASSPY-Instanzen beinflussen.&lt;br /&gt;
:Default ist &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;attr &amp;lt;rhasspyDevice&amp;gt; forceNext 1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;attr-languagefile&amp;quot;&amp;gt;languageFile&amp;lt;/code&amp;gt;&lt;br /&gt;
:Pfad zur Sprach-Datei&lt;br /&gt;
:Ist dieses Argument nicht gesetzt, wird ein Standard-Set an englischen Sätzen für die Sprachantworten verwendet.&lt;br /&gt;
:Die Datei selbst muss ein gültiges JSON-File sein, dass sich nach der Struktur aus den englischen Standardwerten richtet.&lt;br /&gt;
:Eine deutsche Beispiel-Datei ist in [https://svn.fhem.de/trac/browser/trunk/fhem/contrib/RHASSPY/rhasspy-de.cfg SVN] und [https://github.com/fhem/fhem-rhasspy/blob/dev/FHEM/rhasspy-de.cfg GitHub] vorhanden. Man kann aber einfach ein Dump der englischen Struktur machen (replace RHASSPY by your device&#039;s name: &amp;lt;code&amp;gt;{toJSON($defs{RHASSPY}-&amp;gt;{helper}{lng})}&amp;lt;/code&amp;gt;, das Ergebnis dann bearbeiten und es als eigenes languageFile verwenden.&lt;br /&gt;
:Im Standard-Set sind auch einige Variablen enthalten. Auch die können im eigenen File verwendet werden.&lt;br /&gt;
:languageFile erlaubt auch eine Kombination aus vorhandenen und eigenen Sätzen. Dazu können die eigenen Sätzen einfach im Sub-Tree &#039;&#039;user&#039;&#039; abgelegt werden.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Beispiel:&#039;&#039;&#039; (vorausgesetzt, die Sprach-Datei ist im selben Verzeichnis wie fhem.pl):&lt;br /&gt;
:&amp;lt;code&amp;gt;attr &amp;lt;rhasspyDevice&amp;gt; languageFile ./rhasspy-de.cfg&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;attr-response&amp;quot;&amp;gt;response&amp;lt;/code&amp;gt;&lt;br /&gt;
:&#039;&#039;&#039;Hinweis:&#039;&#039;&#039;: Die Verwendung dieses Attributs ist nicht mehr empfohlen. Bessere Alternative ist die Sprach-Datei.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Mit diesem Attribut können eigene Standardantworten definiert werden.&lt;br /&gt;
Mögliche Schlüsselwörter sind &amp;lt;code&amp;gt;DefaultError&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;NoActiveMediaDevice&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;DefaultConfirmation&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;DefaultError=&lt;br /&gt;
DefaultConfirmation=Klaro, mach ich&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;attr-rhasspyhotwords&amp;quot;&amp;gt;rhasspyHotwords&amp;lt;/code&amp;gt;&lt;br /&gt;
:Kann verwendet werden, um benutzerdefinierte Aktionen auszuführen, sobald ein bestimmtes Hotword erkannt wurde. Dazu sind keine speziellen Konfigurationsschritte in anderen FHEM Devices notwendig.&lt;br /&gt;
:Wenn mittels Attribut oder DEF aktiviert, wird ein Reading &#039;&#039;hotword&#039;&#039; erstellt und mit dem erkannten Hotword und der siteId befüllt um ein Event-Handling zu ermöglichen.&lt;br /&gt;
:&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Da bei den hotword messages für alle Teilnehmer dieselbe Topic-Structur verwendet wird, kann RHASSPY nicht unterscheiden, ob eine solche für diese Instanz relevant ist. Falls entsprechende Unterscheidungen gemacht werden sollen, muss dies vom User entsprechend konfiguriert werden, z.B. indem die subscriptions (am MQTT2_CLIENT) eingeschränkt werden oder indem nur jeweils andere hotword-Einträge für jede RHASSPY-Instanz genutzt werden.&lt;br /&gt;
:Ein Hotword pro Zeile, Syntax entweder einfach oder erweitert&lt;br /&gt;
 &lt;br /&gt;
:&#039;&#039;&#039;Beispiele:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;bumblebee_linux = set amplifier2 mute on&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;porcupine_linux = livingroom=&amp;quot;set amplifier mute on&amp;quot; default={Log3($DEVICE,3,&amp;quot;device $DEVICE - room $ROOM - value $VALUE&amp;quot;)}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Im ersten Beispiel wird der Befehl immer ausgeführt, wenn das Hotword &#039;&#039;bumblebee_linux&#039;&#039; erkannt wurde.&lt;br /&gt;
:Im zweiten nur, wenn das Hotword &#039;&#039;porcupine_linux&#039;&#039; in der siteId &#039;&#039;livingroom&#039;&#039; erkannt wurde.&lt;br /&gt;
:$DEVICE wird ausgewertet als der Name des RHASSPY Devices, $ROOM als siteId und $VALUE als das verwendete Hotword.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;attr-rhasspyintents&amp;quot;&amp;gt;rhasspyIntents&amp;lt;/code&amp;gt;&lt;br /&gt;
:Definiert einen benutzerdefinierten Intent.&lt;br /&gt;
:Ein Intent pro Zeile.&lt;br /&gt;
:&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;attr &amp;lt;rhasspyDevice&amp;gt; rhasspyIntents SetCustomIntentsTest=SetCustomIntentsTest(siteId,Type)&amp;lt;/code&amp;gt;&lt;br /&gt;
:in Kombination mit folgendem myUtils-Code&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub SetCustomIntentsTest {&lt;br /&gt;
my $room = shift;&lt;br /&gt;
my $type = shift;&lt;br /&gt;
Log3(&#039;rhasspy&#039;,3 , &amp;quot;RHASSPY: Room $room, Type $type&amp;quot;);&lt;br /&gt;
return &amp;quot;RHASSPY: Room $room, Type $type&amp;quot;;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
:schreibt einen Log-Eintrag nach jedem Aufruf dieses Intents.&lt;br /&gt;
:Die folgenden Argumente können dabei übergeben werden:&lt;br /&gt;
:*NAME =&amp;gt; Name des RHASSPY-Devices&lt;br /&gt;
:*DATA =&amp;gt; komplette JSON-$data (wie intern geparsed), in JSON kodiert&lt;br /&gt;
:*siteId, Device etc. =&amp;gt; jedes Element, das in JSON-$data existiert&lt;br /&gt;
:Wird von der Funktion ein einfacher Text zurück geliefert, wird dieser als &#039;&#039;response&#039;&#039; angesehen. Wenn der Rückgabewert nicht definiert ist, wird die Standard-&#039;&#039;response&#039;&#039; verwendet.&lt;br /&gt;
:Es kann aber auch ein HASH oder ARRAY übergeben werden.&lt;br /&gt;
:Im Falle eines ARRAYs wird das erste Element als &#039;&#039;response&#039;&#039; interpretiert und kann ein reiner Text sein, womit der Dialog beendet wird. Ist das erste Element ein HASH wird die Dialog-Session fortgesetzt. Eine offene Dialog-Session wird per Default nach 20 Sekunden beendet. Diese Zeitspanne kann aber auch geändert werden, in dem im ARRAY als zweiter Wert eine Zahl übergeben wird. Das zweite Element kann aber auch eine komma-getrennte Liste an Geräten sein, die geändert (geschalten) wurden. Das dient dazu, damit die Geräte auch Events liefern, was ansonsten nicht der Fall wäre. Siehe dazu den &amp;quot;d&amp;quot;-Parameter beim Attribut [[#attr-rhasspyshortcuts|rhasspyShortcuts]].&lt;br /&gt;
:Wird eine HASH-Datenstruktur (ggf. in $response innerhalb einer ARRAY-Struktur), um einen laufenden Dialog fortzusetzen, muss sichergestellt werden, dass alle erforderlichen Datenelemente enthalten sind, insbesondere &#039;&#039;intentFilter&#039;&#039;, falls die für den weiteren Dialog relevanten Intents eingeschränkt (oder erweitert) werden sollen. Dabei sollte möglichst der Intent &#039;&#039;CancelAction&#039;&#039; aktiv gehalten werden, damit der User die Option hat, den Dialog jederzeit aktiv zu beenden.&lt;br /&gt;
:Siehe dazu auch den Abschnitt [[#Eigene Intents erstellen]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;attr-rhasspyshortcuts&amp;quot;&amp;gt;rhasspyShortcuts&amp;lt;/code&amp;gt;&lt;br /&gt;
:Hiermit können benutzerdefinierte Sätze erstellt werden ohne die sentences.ini in Rhasspy bearbeiten zu müssen.&lt;br /&gt;
:Diese Shortcuts werden zu Rhasspy hochgeladen, sobald das &amp;lt;code&amp;gt;updateSlots&amp;lt;/code&amp;gt; [[#set-update|Set]]-Kommando ausgeführt wird.&lt;br /&gt;
:Ein Shortcut pro Zeile, Syntax ist entweder einfach oder erweitert.&lt;br /&gt;
:&#039;&#039;&#039;Beispiele:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;mute on=set amplifier2 mute on&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;lamp off={fhem(&amp;quot;set lampe1 off&amp;quot;)}&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;i=&amp;quot;du bist cool&amp;quot; f=&amp;quot;set $NAME speak siteId=&#039;livingroom&#039; text=&#039;danke dir! du bist noch viel cooler!&#039;&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;i=&amp;quot;schalte den ton aus&amp;quot; p={fhem (&amp;quot;set $NAME mute off&amp;quot;)} n=amplifier2 c=&amp;quot;soll ich den ton wirklich ausschalten?&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;i=&amp;quot;ich hab hunger&amp;quot; f=&amp;quot;set Herd on&amp;quot; d=&amp;quot;Herd&amp;quot; c=&amp;quot;möchtest du schweinsbraten?&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
:Erklärung zu den Abkürzungen:&lt;br /&gt;
:*&amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt; =&amp;gt; intent&lt;br /&gt;
::Zeilen, die mit &amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt; beginnen, werden als erweiterte Syntax interpretiert. Soll die erweiterte Syntax verwendet werden, ist das &amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt; also Pflicht!&lt;br /&gt;
:*&amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; =&amp;gt; FHEM Befehl&lt;br /&gt;
::Syntax wie von der FHEM Kommandozeile gewohnt&lt;br /&gt;
:*&amp;lt;code&amp;gt;p&amp;lt;/code&amp;gt; =&amp;gt; Perl Befehl&lt;br /&gt;
::Syntax wie von der FHEM Kommandozeile gewohnt, eingerahmt in geschwungenen Klammern (&amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt;). &amp;lt;code&amp;gt;p&amp;lt;/code&amp;gt; hat Vorrang vor &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt;&lt;br /&gt;
:*&amp;lt;code&amp;gt;d&amp;lt;/code&amp;gt; =&amp;gt; Device Name(en, Komma getrennt)&lt;br /&gt;
::Device Name(n), die an fhem.pl als upgedated übergeben werden sollen. Das wird benötigt um weitere Aktionen in FHEM und das Longpolling zu triggern.&lt;br /&gt;
::Hinweis: Wenn Perl-Funktionen aufgerufen werden, wird der Rückgabewert dieser Funktion verwendet, sofern kein explizites Device angegeben ist.&lt;br /&gt;
:*&amp;lt;code&amp;gt;r&amp;lt;/code&amp;gt; =&amp;gt; Response&lt;br /&gt;
::Sprachanwort, die ausgegeben wird. Ist &amp;lt;code&amp;gt;r&amp;lt;/code&amp;gt; nicht gesetzt, wird der Rückgabewert der aufgerufenen Funktion verwendet.&lt;br /&gt;
::In den Antwortsätze werden &#039;&#039;set magic&#039;&#039;-ähnliche Ersetzungen verarbeitet. Es ist also auch eine Zeile wie &amp;lt;code&amp;gt;i=&amp;quot;what&#039;s the time for sunrise&amp;quot; r=&amp;quot;at [Astro:SunRise] o&#039;clock&amp;quot;&amp;lt;/code&amp;gt; gültig.&lt;br /&gt;
::Mit den folgenden Abkürzungen kann auch nach einer Bestätigung für den Befehl gefragt werden:&lt;br /&gt;
::*&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt; =&amp;gt; Entweder Zahl oder Text. Wenn Zahl, wird sie als Timeout für den Abbruch des Dialogs behandelt. Wenn Text wird dieser als Sprachausgabe zur Bestätigung verwendet.&lt;br /&gt;
::*&amp;lt;code&amp;gt;ct&amp;lt;/code&amp;gt; =&amp;gt; Numerischer Wert für das Timeout des Dialogs in Sekunden. Default ist &amp;lt;code&amp;gt;15&amp;lt;/code&amp;gt;.&lt;br /&gt;
::Siehe [[#attr-rhasspytweaks-confirmintents|hier]] für weitere Informationen zu Bestätigungen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;attr-rhasspytweaks&amp;quot;&amp;gt;rhasspyTweaks&amp;lt;/code&amp;gt;&lt;br /&gt;
Mit diesen Einstellungen können benutzerdefinierte Optimierungen an RHASSPY vorgenommen werden.&lt;br /&gt;
&lt;br /&gt;
:*&amp;lt;code id=&amp;quot;attr-rhasspytweaks-timerlimits&amp;quot;&amp;gt;timerLimits&amp;lt;/code&amp;gt;&lt;br /&gt;
::Wird verwendet um den Timer anzuweisen mit z.B. &amp;quot;gestellt auf 30 Minuten&amp;quot; oder &amp;quot;gestellt auf 10:30&amp;quot; zu antworten&lt;br /&gt;
::&amp;lt;code&amp;gt;timerLimits=90,300,3000,2*HOURSECONDS,50&amp;lt;/code&amp;gt;&lt;br /&gt;
::Hierbei müssen fünf Werte gesetzt werden, die den Zeitgrenzen für Stufen in der Antwortstruktur &#039;&#039;timerSet&#039;&#039; entsprechen.&lt;br /&gt;
::Obiges Beispiel also würde dazu führen, unter einer eingestellten Zeit von 90 Sekunden mit der Sekundenangabe geantwortet wird. In Minuten und Sekunden solange der Timer kürzer als 300 Sekunden ist. Usw. Der letzte Wert ist das Limit in Sekunden, wenn der Timer im &amp;quot;Uhrzeit&amp;quot;-Format gestellt ist.&lt;br /&gt;
&lt;br /&gt;
:*&amp;lt;code id=&amp;quot;attr-rhasspytweaks-timersounds&amp;quot;&amp;gt;timerSounds&amp;lt;/code&amp;gt;&lt;br /&gt;
::Standardmäßig antwortet der Timer mit einer Sprachnachricht, wenn er abgelaufen ist. Soll lieber eine WAV-Datei verwendet werden, kann das hier eingestellt werden.&lt;br /&gt;
::&amp;lt;code&amp;gt;timerSounds= default=./yourfile1.wav eier=3:20:./yourfile2.wav kartoffeln=5:./yourfile3.wav&amp;lt;/code&amp;gt;&lt;br /&gt;
::Die Keys in dieser Code-Zeile sind Beispiele und deren Name - bis auf &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; frei wählbar. Der Name muss aber zu den &#039;&#039;Label&#039;&#039;-Tags für die Timer in den Rhasspy-Sentences passen.&lt;br /&gt;
::&amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; ist optional. Wenn gesetzt, wird dieses WAV-File für alle benannten Timer verwendet, für die kein Keyword in der Konfiguration ist.&lt;br /&gt;
::Die beiden Nummern sind optional. Die erste legt fest, wie oft die WAV-Datei wiederholt werden soll (Default: 5). Die zweite definiert die Pause in Sekunden zwischen den Wiederholungen (Default: 15). Ist nur eine Zahl gesetzt, wird diese als gewünschte Anzahl an Wiederholungen interpretiert.&lt;br /&gt;
&lt;br /&gt;
:*&amp;lt;code id=&amp;quot;attr-rhasspytweaks-updateslots&amp;quot;&amp;gt;updateSlots&amp;lt;/code&amp;gt;&lt;br /&gt;
::Ändert diverse Aspekte des Erstellens und Updatens von Slots&lt;br /&gt;
::*&amp;lt;code&amp;gt;noEmptySlots=1&amp;lt;/code&amp;gt;&lt;br /&gt;
:::Per Default generiert RHASSPY einen zusätzlichen Slot für jeden &#039;&#039;genericDeviceType&#039;&#039;, der erkannt wird. Unabhängig davon, ob er bei einem Gerät gesetzt ist. Das kann zu leeren Slots führen.&lt;br /&gt;
:::Ist der Wert &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;, werden keine leeren Slots erstellt.&lt;br /&gt;
::*&amp;lt;code&amp;gt;overwrite_all=false&amp;lt;/code&amp;gt;&lt;br /&gt;
:::RHASSPY überschreibt alle vorhandenen Slots wenn ein &amp;lt;code&amp;gt;updateSlots&amp;lt;/code&amp;gt; ausgeführt wird. Ist das nicht gewünscht, muss dieser Wert auf &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; gesetzt werden.&lt;br /&gt;
::*&amp;lt;code&amp;gt;timeouts&amp;lt;/code&amp;gt;&lt;br /&gt;
:::Die Keywörter &amp;lt;code&amp;gt;confirm&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; können verwendet werden, um das Standard-Timeouts (15s/20s) für Dialoge zu ändern.&lt;br /&gt;
:::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:::&amp;lt;code&amp;gt;timeouts: confirm=25 default=30&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:*&amp;lt;code id=&amp;quot;attr-rhasspytweaks-confirmintents&amp;quot;&amp;gt;confirmIntents&amp;lt;/code&amp;gt;&lt;br /&gt;
::Hiermit kann eingestellt werden, dass für bestimmte Intents immer ein Bestätigung erfragt wird. Unterstützt werden derzeit alle &amp;quot;set-&amp;quot;-Intents.&lt;br /&gt;
::Dazu werden &amp;lt;code&amp;gt;Intent&amp;lt;/code&amp;gt;=&amp;lt;code&amp;gt;regex&amp;lt;/code&amp;gt;-Paare verwendet.&lt;br /&gt;
:::&amp;lt;code&amp;gt;Intent&amp;lt;/code&amp;gt; ist der Name des gewünschten Intents&lt;br /&gt;
:::&amp;lt;code&amp;gt;regex&amp;lt;/code&amp;gt; ist eine Regex, die eine bestimmte Gruppe (für Gruppen-Intents) oder einen bestimmten Device-Namen beschreiben muss.&lt;br /&gt;
:::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:::&amp;lt;code&amp;gt;confirmIntents=SetOnOffGroup=light|blinds SetOnOff=blind.*&amp;lt;/code&amp;gt;&lt;br /&gt;
::Befehle werden nur nach einer positiven Bestätigung ausgeführt. Das bedeutet, es muss unbedingt ein &amp;lt;code&amp;gt;Mode:OK&amp;lt;/code&amp;gt;-Wert vom &#039;&#039;ConfirmAction&#039;&#039;-Intent gesendet werden. Jede andere Wert für &amp;lt;code&amp;gt;Mode&amp;lt;/code&amp;gt; wird als Abbruch gewertet. Es kann aber auch der eigene Intent &#039;&#039;CancelAction&#039;&#039; für den Abbruch verwendet werden.&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:ConfirmAction]&lt;br /&gt;
( yes, please do it | go on | that&#039;s ok | yes, please ){Mode:OK}&lt;br /&gt;
( don&#039;t do it after all ){Mode}&lt;br /&gt;
&lt;br /&gt;
[de.fhem:CancelAction]&lt;br /&gt;
( let it be | oh no | cancel | cancellation ){Mode:Cancel}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:*&amp;lt;code id=&amp;quot;attr-rhasspytweaks-confirmintentresponses&amp;quot;&amp;gt;confirmIntentResponses&amp;lt;/code&amp;gt;&lt;br /&gt;
::Üblicherweise ist die Bestätigungs-Frage ein &amp;quot;Echo&amp;quot; des ursprünglich gesprochenen Befehls. Dies kann für jeden Intent geändert werden,&lt;br /&gt;
::Dies kann für jeden Intent individuell angepaßt werden, wobei die Variablen $target, ($rawInput) und $Value verwendet werden können.&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;confirmIntentResponses=SetOnOffGroup=&amp;quot;wirklich die Gruppe $target $Value schalten&amp;quot; SetOnOff=&amp;quot;bestätige dass $target $Value geschaltet werden soll&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
::&amp;lt;code&amp;gt;$Value&amp;lt;/code&amp;gt; wird dabei mit den defaults aus dem &#039;&#039;words&#039;&#039; key in der languageFile übersetz (falls vorhanden). Weitere Optionen für Ersetzungen von &amp;lt;code&amp;gt;$Value&amp;lt;/code&amp;gt; sind für einzelne Devices über den [[#attr-rhasspyspecials-confirmvaluemap|confirmValueMap]] key im Attribut &#039;&#039;rhasspySpecials&#039;&#039; verfügbar.&lt;br /&gt;
&lt;br /&gt;
:*&amp;lt;code id=&amp;quot;attr-rhasspytweaks-intentfilter&amp;quot;&amp;gt;intentFilter&amp;lt;/code&amp;gt;&lt;br /&gt;
::Rhasspy aktiviert bei jedem Neustart alle ihm bekannten Intents. Da manche der von FHEM genutzten Intents nur in bestimmten Situationen (v.a. innerhalb offener Dialoge) benötigt werden, deaktiviert RHASSPY diese (derzeit: ConfirmAction, CancelAction, ChoiceRoom und ChoiceDevice beim Start, sowie jedes Mal, wenn erkannt wird, dass das Standardfiltering nicht wie erwartet funktioniert (was v.a. bei einem zwischenzeitlichen Rhasspy-Neustart der Fall sein kann). Über diesen Tweak können weitere Intents mit in diese automatisierte (De-) Aktivierung mit einbezogen werden. Entweder ist dabei einfach der Name (ohne die Zusätze aus &#039;&#039;language&#039;&#039; und &#039;&#039;fhemId&#039;&#039; anzugeben, oder eine explizite Anweisung zum ein- und Ausschalten (in der Form &amp;lt;code&amp;gt;intentname=true&amp;lt;/code&amp;gt;). Die 4 vorgenannten Standard-Intents können nicht über diesen Weg aktiviert werden. Details zur intern genutzten Rhasspy-Funktionalität sind in der [https://rhasspy.readthedocs.io/en/latest/reference/#dialogue-manager Rhasspy-Dokumentation] zu finden.&lt;br /&gt;
&lt;br /&gt;
:*&amp;lt;code id=&amp;quot;attr-rhasspytweaks-ignorekeywords&amp;quot;&amp;gt;ignoreKeywords&amp;lt;/code&amp;gt;&lt;br /&gt;
::Da in manchen der von RHASSPY automatisch ausgewerteten Attribute häufig auch eher technisch motivierte Angaben zu finden sind, kann über diesen Schlüssel verhindert werden, dass derartige Angaben bei der slot-Erstellung übergangen werden. Dies betrifft z.B. häufig anzutreffende &#039;&#039;room&#039;&#039;-Werte wie &#039;&#039;MQTT&#039;&#039;, &#039;&#039;alexa&#039;&#039;, &#039;&#039;homebridge&#039;&#039; oder &#039;&#039;googleassistant&#039;&#039;. Die hier angegebenen key-value-Paare werden als Negativ-Filter für die angegebenen Werte verwendet (derzeit nur für &#039;&#039;rooms&#039;&#039; und &#039;&#039;group&#039;&#039;). &#039;&#039;value&#039;&#039; wird dabei als (case-insensitive) regex behandelt, verglichen wird auf exakten match (es müssen also ggf. vorne bzw. hinten &#039;&#039;.*&#039;&#039; angefügt werden).&lt;br /&gt;
::Dieses &#039;&#039;&#039;Beispiel&#039;&#039;&#039; filtert daher die o.g. Räume aus und dazu noch die strukturierten Unterräume unterhalb &#039;&#039;Steuerung&#039;&#039;:&lt;br /&gt;
::&amp;lt;code&amp;gt;ignoreKeywords=rooms=mqtt.*|alexa|homebridge|googleassistant|steuerung-.&amp;lt;/code&amp;gt;&lt;br /&gt;
:* &amp;lt;code id=&amp;quot;attr-rhasspytweaks-ignorekeywords&amp;quot;&amp;gt;gdt2groups&amp;lt;/code&amp;gt;  Dieser Eintrag ermöglicht es, alle Geräte eines generichDeviceType innerhalb der automatischen Erfassung automatisch einer oder mehreren Gruppen zuzuordnen. Die Vorgaben in diesem Eintrag werden nicht übernommen, wenn am jeweiligen Einzelgerät  das Attribut &#039;&#039;rhasspyGroup&#039;&#039; gesetzt ist.  Hier eine deutschsprachige Vorbelegung als &#039;&#039;&#039;Beispiel&#039;&#039;&#039;: &amp;lt;code&amp;gt;gdt2groups= blind=rollläden,rollladen thermostat=heizkörper light=lichter,leuchten&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Readings / Events==&lt;br /&gt;
;&amp;lt;code&amp;gt;IODev&amp;lt;/code&amp;gt;&lt;br /&gt;
:Das eingestellte IO-Device&lt;br /&gt;
;&amp;lt;code&amp;gt;intents&amp;lt;/code&amp;gt;&lt;br /&gt;
:Eine Liste der in Rhasspy vorhandenen Intents&lt;br /&gt;
;&amp;lt;code&amp;gt;lastIntentPayload&amp;lt;/code&amp;gt;&lt;br /&gt;
:Inhalt des letzten Intents der von FHEM empfangen wurde&lt;br /&gt;
;&amp;lt;code&amp;gt;lastIntentTopic&amp;lt;/code&amp;gt;&lt;br /&gt;
:Das MQTT-Topic des letzten Intents&lt;br /&gt;
;&amp;lt;code&amp;gt;listening_roomname&amp;lt;/code&amp;gt;&lt;br /&gt;
:Ein Reading für jeden Raum bzw. jede siteId&lt;br /&gt;
:Wechselt auf 1 sobald ein Hotword erkannt wurde und zurück auf 0, sobald die Dialog-Session beendet ist.&lt;br /&gt;
:Kann z.B. verwendet werden, um den Ton eines TVs auszuschalten, während Rhasspy auf ein Kommando hört.&lt;br /&gt;
;&amp;lt;code&amp;gt;mute_roomname&amp;lt;/code&amp;gt;&lt;br /&gt;
:Zeigt an, ob ein Raum / eine siteId vom Intent &#039;&#039;SetMute&#039;&#039; stumm geschalten wurde und somit keine Befehle ausführt.&lt;br /&gt;
:Jeweils ein Reading für jede siteId.&lt;br /&gt;
:Default ist 0.&lt;br /&gt;
;&amp;lt;code&amp;gt;responseType&amp;lt;/code&amp;gt;&lt;br /&gt;
:Der Typ der letzten Antwort (text/voice).&lt;br /&gt;
:voiceResponse and textResponse&lt;br /&gt;
:Antwort auf das letzte Sprach-/Text-Kommando.&lt;br /&gt;
;&amp;lt;code&amp;gt;siteIds&amp;lt;/code&amp;gt;&lt;br /&gt;
:Listet alle siteIds auf.&lt;br /&gt;
:Kann mit [[#set-fetchsiteids|fetchSiteIds]] aktualisiert werden.&lt;br /&gt;
;&amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;&lt;br /&gt;
:Zeigt an ob RHASSPY mit Rhasspy verbunden ist&lt;br /&gt;
;&amp;lt;code&amp;gt;training&amp;lt;/code&amp;gt;&lt;br /&gt;
:Letzte zurückgelieferte Antwort auf einen [[#set-trainrhasspy|trainRhasspy]]-Befehl.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
;&amp;lt;code&amp;gt;updateSentences&amp;lt;/code&amp;gt;&lt;br /&gt;
:Letzte zurückgelieferte Antwort nach einem [[#set-update-slots|updateSlots]]-Befehl.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
;&amp;lt;code&amp;gt;updateSlots&amp;lt;/code&amp;gt;&lt;br /&gt;
:Letzte zurückgelieferte Antwort nach einem [[#set-update-slots|updateSlots]]-Befehl.&lt;br /&gt;
;&amp;lt;code&amp;gt;hotword&amp;lt;/code&amp;gt;&lt;br /&gt;
:Wenn aktiviert, beinhaltet dieses Reading das letzte verwendete Hotword und von welcher siteId es aufgerufen wurde.&lt;br /&gt;
;&amp;lt;code&amp;gt;voiceResponse&amp;lt;/code&amp;gt;&lt;br /&gt;
:Letze Sprach-Antwort auf einen Sprach-Befehl&lt;br /&gt;
&lt;br /&gt;
=== Benutzerdefinierte Readings ===&lt;br /&gt;
&lt;br /&gt;
There are some readings you may find useful to tweak some aspects of RHASSPY&#039;s logics:&lt;br /&gt;
*&amp;lt;code&amp;gt;siteId2room_&amp;lt;/code&amp;gt; Falls keine explizite Raum-Information in den an RHASSPY weitergegebenen Daten enthalten ist, ermittelt das Modul den Raum in der Regel aus dem Namen der &#039;&#039;siteId&#039;&#039;. So werden z.B. alle raumlosen Anweisungen von einem Satelliten names &#039;&#039;schlafzimmer&#039;&#039;, im Raum &#039;&#039;schlafzimmer&#039;&#039; ausgeführt werden (wenn möglich). Die Gruppenfunktion von Rhasspy wird unterstützt, so wird z.B. &#039;&#039;wohnzimmer.vorne&#039;&#039; ebenfalls automatisch dem Raum &#039;&#039;wohnzimmer&#039;&#039; zugeordnet. Über passende Angaben in &#039;&#039;siteId2room-Readings&#039;&#039; kann dieses Verhalten modifiziert werden:  &amp;lt;code&amp;gt;setreading siteId2room_mobile_phone1 wohnzimmer&amp;lt;/code&amp;gt; wird RHASSPY veranlassen, den Satelliten  &#039;&#039;mobile_phone1&#039;&#039; dem Raum &#039;&#039;wohnzimmer&#039;&#039; zuzuweisen. Hierzu ist in &#039;&#039;contrib&#039;&#039; auch eine Hilfsfunktion zu finden, mit der mobilen Satelliten per Sprachbefehl einem neuen Raum zugewiesen werden können.&lt;br /&gt;
*&amp;lt;code&amp;gt;siteId2doubleSpeak_&amp;lt;/code&amp;gt; RHASSPY antwortet immer über den Satelliten, von dem die jeweilige Sprachanweisung kam. Manchmal kann es erwünscht sein, zusätzliche Sprachrückmeldungen an einen weiteren Satelliten zu geben - z.B. weil der betreffende Lautsprecher (zeitweise) ausgeschaltet ist. Ist ein entsprechendes Reading gesetzt, erfolgen (zusätzliche!) Sprachausgaben an den dort als Readingwert angegebenen zweiten Satelliten; das Namensschema der Readings entspricht dem für site2room.&lt;br /&gt;
&lt;br /&gt;
== FHEM-Devices für die Verwendung mit Rhasspy konfigurieren ==&lt;br /&gt;
Um ein Gerät mit Rhasspy steuern zu können, muss Rhasspy einige Details über das Gerät kennen. Diese werden bekannt gemacht, in dem bei den Geräten Attribute gesetzt werden, die anschließend vom RHASSPY-Modul ausgewertet und an Rhasspy gesendet werden.&lt;br /&gt;
&lt;br /&gt;
Der einfachste - und empfohlene - Weg, dies zu erreichen, ist durch Setzen des Attributs &#039;&#039;&#039;&#039;&#039;genericDeviceType&#039;&#039;&#039;&#039;&#039;. Das Modul erkennt dann die möglichen Schalt - und Abfragemöglichkeiten des Gerätes automatisch.&lt;br /&gt;
&lt;br /&gt;
Sollte &#039;&#039;genericDeviceType&#039;&#039; (gDT) nicht ausreichen, gibt es noch weitere Attribute, die stattdessen oder ergänzend dazu verwendet werden können (z.b. rhasspyName, rhasspyRoom, ...). Die Namen dieser Attribute beginnen alle mit dem &#039;&#039;prefix&#039;&#039;, das in der DEF des RHASSPY-Moduls gesetzt wurde. Diese Dokumentation verwendet das Prefix &amp;lt;code&amp;gt;rhasspy&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Sind sowohl &#039;&#039;genericDeviceType&#039;&#039; als auch Spezial-Attribute vorhanden, werden die von gDT gesammelten Möglichkeiten durch die der Spezial-Attribute überschrieben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Wichtig:&#039;&#039;&#039;&lt;br /&gt;
*Nach JEDER Änderung an den folgenden Attributen muss ein &amp;lt;code&amp;gt;[[#set-update-devicemap|update devicemap]]&amp;lt;/code&amp;gt; ausgeführt werden. Sonst erfahren weder RHASSPY, noch Rhasspy von der Änderung.&lt;br /&gt;
*RHASSPY sammelt alle Informationen aus diesen Attributen in seinem eigenen Device-HASH. Dieser wird durch das &amp;lt;code&amp;gt;update devicemap&amp;lt;/code&amp;gt;-Kommando aktualisiert und kann mittels &amp;lt;code&amp;gt;[[List|list]]&amp;lt;/code&amp;gt;-Befehl angezeigt werden. Für diesen HASH werden alle Namen und sonstige &amp;quot;Labels&amp;quot; in Kleinbuchstaben umgewandelt. Sollte man Slots händisch befüllen, muss also darauf geachtet werden, dass Rhasspy ebenfalls Werte in Kleinbuchstaben liefert.&lt;br /&gt;
*Die Mindestvoraussetzungen für ein FHEM Device um mit RHASSPY zusammenzuarbeiten sind:&lt;br /&gt;
**Das Device muss von der devspec im Define des RHASSPY-Devices abgedeckt werden&lt;br /&gt;
**Es muss mindestens eines der folgenden Attribute (im Normalfall &#039;&#039;genericDeviceType&#039;&#039;) im Device gesetzt sein.&lt;br /&gt;
*Die Mapping-Logik (für Namen, mögliche Schaltzustände, etc.) ist wie folgt:&lt;br /&gt;
**Sind RHASSPY-spezifische Attribute gesetzt, werden ausschließlich diese verwendet. Natürlich nur für den Zweck des gesetzten Attributs. Ein gesetzter &#039;&#039;rhasspyName&#039;&#039; z.B. wird also nicht verhindern, dass die durch &#039;&#039;genericDeviceType&#039;&#039; ermittelten möglichen Schaltzustände ebenfalls gespeichert werden.&lt;br /&gt;
**Je spezifischer ein Attribut ist, desto eher wird überschreiben, was weniger speziell ist. Ein gesetzter &#039;&#039;alias&#039;&#039; wird also verhindern, dass der (technische) Device-Name verwendet wird. Aber ein gesetztes Attribut &#039;&#039;alexaName&#039;&#039;, &#039;&#039;gassistantName&#039;&#039; oder &#039;&#039;siriName&#039;&#039; wird (auch) den &#039;&#039;alias&#039;&#039; überschreiben. Sind zwei &amp;quot;gleichwertige&amp;quot; Attribute vorhanden (z.B. &#039;&#039;siriName&#039;&#039; und &#039;&#039;alexaName&#039;&#039;), werden beide verwendet.&lt;br /&gt;
*Attribut-Werte werden typischerweise &amp;quot;Zeile für Zeile&amp;quot; gelesen. Wobei gilt, eine Zeile pro Wert/Befehl/Funktionalität. Zeilenumbrüche &#039;&#039;&#039;müssen&#039;&#039;&#039; also an den richtigen Stellen gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;code&amp;gt;genericDeviceType&amp;lt;/code&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
Ist dieses Attribut gesetzt &#039;&#039;&#039;und&#039;&#039;&#039; entspricht der Devicename der devspec, wird RHASSPY das Mapping (und andere eventuell schon vorhandene Werte) automatisch ermitteln.&lt;br /&gt;
&lt;br /&gt;
Derzeit werden folgende Werte für das Attribut genericDeviceType unterstützt:&lt;br /&gt;
*switch&lt;br /&gt;
*light&lt;br /&gt;
*thermostat&lt;br /&gt;
*thermometer&lt;br /&gt;
*HumiditySensor&lt;br /&gt;
*blind/blinds/shutter&lt;br /&gt;
*media&lt;br /&gt;
*motion/contact/ContactSensor/lock/presence&lt;br /&gt;
&lt;br /&gt;
Wird &#039;&#039;genericDeviceType&#039;&#039; verwendet, werden unter anderem folgende Informationen gesammelt:&lt;br /&gt;
* der Name (&amp;lt;code&amp;gt;NAME&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;alias&amp;lt;/code&amp;gt;) des Devices&lt;br /&gt;
* der (FHEM-)Raum, in dem sich das Device befindet.&lt;br /&gt;
* die Gruppe, zu der das Device gehört (ggf. unter Beachtung des Schlüssels  &amp;lt;code id=&amp;quot;attr-rhasspytweaks-ignorekeywords&amp;quot;&amp;gt;gdt2groups&amp;lt;/code&amp;gt; aus &#039;&#039;rhasspyTweaks&#039;&#039;)&lt;br /&gt;
* wie Informationen vom Gerät abgefragt werden können&lt;br /&gt;
* wie Werte/Status am Gerät gesetzt werden können&lt;br /&gt;
&lt;br /&gt;
Die Verwendung von &#039;&#039;genericDeviceType&#039;&#039; ist der einfachste Weg, wie man FHEM-Devices dazu bringen kann, mit RHASSPY zusammenzuarbeiten. Manchmal liefert genericDeviceType aber nicht ausreichende oder nicht passende Informationen. In so einem Fall können die folgenden Attribute (zusätzlich) verwendet werden.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;code&amp;gt;rhasspyName&amp;lt;/code&amp;gt;===&lt;br /&gt;
Mit diesem Attribut kann der Name des Geräts eingestellt werden, mit dem es in einem Sprachbefehl angesprochen werden soll. Es können auch mehrere Namen - getrennt durch ein Komma - angegeben werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039; &amp;lt;code&amp;gt;attr &amp;lt;device&amp;gt; rhasspyName Lampe,Stehlampe,Wunderlicht&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es ist durchaus möglich, mehrere FHEM-Geräte mit dem selben Namen zu haben. Sie müssen dann nur in unterschiedlichen Räumen sein.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;code&amp;gt;rhasspyRoom&amp;lt;/code&amp;gt;===&lt;br /&gt;
Dieses Attribut kann verwendet werden, um Rhasspy mitzuteilen, in welchem physischem (oder logischen) Raum sich das Gerät befindet.&lt;br /&gt;
&lt;br /&gt;
Ist es nicht vorhanden, wird &amp;lt;code&amp;gt;alexaRoom&amp;lt;/code&amp;gt; oder das FHEM-Attribut &amp;lt;room&amp;gt; verwendet. Sind auch diese nicht vergeben, gehört das Gerät zum &amp;quot;Standard-Raum&amp;quot;, der im Define des RHASSPY-Devices angegeben wurde.&lt;br /&gt;
&lt;br /&gt;
Das Attribut ist nützlich, wenn man Sprachbefehle ohne explizite Raumangabe verwenden will. Gibt es z.B. ein Gerät mit dem Namen &#039;&#039;Lampe&#039;&#039; und dessen rhasspyRoom-Attribut ist gleich, wie die &#039;&#039;siteId&#039;&#039; von der aus der Sprachbefehl abgesetzt wird, reicht es zu sagen &amp;quot;Lampe ein&amp;quot;. Der Raum muss also nicht extra dazu gesagt werden.&lt;br /&gt;
&lt;br /&gt;
Es ist auch möglich, mehrere Raum-Namen zu vergeben sofern diese durch ein Komma voneinander getrennt werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039; &amp;lt;code&amp;gt;attr &amp;lt;device&amp;gt; rhasspyRoom livingroom&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hinweis: Wenn die &#039;&#039;siteId&#039;&#039; den Konventionen von Rhasspy zur Gruppierung von siteIds folgt (&#039;&#039;roomname.satellite&#039;&#039;), wird nur &amp;lt;code&amp;gt;roomname&amp;lt;/code&amp;gt; als Raum-Name angenommen. Beachte: Die automatisierte Zuweisung zu einem Raum kann durch &#039;&#039;siteId2room_.*&#039;&#039;-Readings modifiziert werden (s.o.). &lt;br /&gt;
===&amp;lt;code&amp;gt;rhasspyGroup&amp;lt;/code&amp;gt;===&lt;br /&gt;
Kommagetrennte Liste an Gruppen, zu denen das Gerät zugehörig ist&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039; &amp;lt;code&amp;gt;attr &amp;lt;device&amp;gt; rhasspyGroup Lampen,Beleuchtung Arbeitsfläche,Küchen Beleuchtung&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;code&amp;gt;rhasspyMapping&amp;lt;/code&amp;gt;===&lt;br /&gt;
Wenn die automatische Erkennung des richtigen Intents für ein Gerät nicht funktioniert oder nicht das gewünschte Ergebnis liefert, kann mit diesem Attribut angegeben werden, mit welchem Intent das Gerät gesteuert werden kann.&lt;br /&gt;
&lt;br /&gt;
Es ist möglich, mehrere verschiedene Intents pro Gerät zu verwenden. Es muss nur einfach eine neue Zeile für ein weiteres Mapping verwendet werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr &amp;lt;device&amp;gt; rhasspyMapping SetOnOff:cmdOn=on,cmdOff=off,response=&amp;quot;Alles klar&amp;quot;&lt;br /&gt;
GetOnOff:currentVal=state,valueOff=off&lt;br /&gt;
GetNumeric:currentVal=pct,type=brightness&lt;br /&gt;
SetNumeric:currentVal=brightness,cmd=brightness,minVal=0,maxVal=255,map=percent,step=1,type=brightness&lt;br /&gt;
Status:response=Die Helligkeit in der Küche ist bei [&amp;lt;device&amp;gt;:pct]&lt;br /&gt;
MediaControls:cmdPlay=play,cmdPause=pause,cmdStop=stop,cmdBack=previous,cmdFwd=next&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Formatierung von Befehlen und Readings innerhalb eines rhasspyMappings====&lt;br /&gt;
Manche Intents können FHEM-Kommandos oder -Readings verwenden, um Werte auszulesen oder zu setzen.&lt;br /&gt;
&lt;br /&gt;
Dabei gibt es drei Möglichkeiten, wie diese geschrieben werden können:&lt;br /&gt;
*Direktes Verwenden von SET-Kommando oder Reading des aktuellen Device:&lt;br /&gt;
:&amp;lt;code&amp;gt;cmd=on or currentReading=temperature&amp;lt;/code&amp;gt;&lt;br /&gt;
*Umleiten eines Kommando auf ein anderes Device oder Verwenden eines Readings aus einem anderen Gerät:&lt;br /&gt;
:&amp;lt;code&amp;gt;cmd=Otherdevice:on or currentReading=Otherdevice:temperature&amp;lt;/code&amp;gt;&lt;br /&gt;
*Perl-Code um einen Befehl auszuführen oder einen Wert zu setzen:&lt;br /&gt;
:Das ermöglicht sehr komplexe Anfragen.&lt;br /&gt;
:Der Code muss in geschwungenen Klammern sein.&lt;br /&gt;
:&amp;lt;code&amp;gt;{currentVal={ReadingsVal($DEVICE,&amp;quot;state&amp;quot;,0)}&amp;lt;/code&amp;gt;&lt;br /&gt;
:oder&lt;br /&gt;
:&amp;lt;code&amp;gt; cmd={fhem(&amp;quot;set $DEVICE dim $VALUE&amp;quot;)}&amp;lt;/code&amp;gt;&lt;br /&gt;
:$DEVICE ist das aktuelle FHEM-device. Der SetNumeric-Intent kann $VALUE für den Wert verwenden, der gesetzt werden soll.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;code&amp;gt;rhasspySpecials&amp;lt;/code&amp;gt;===&lt;br /&gt;
Dieses Attribut wirkt ähnlich wie [[#rhasspyTweaks| rhasspyTweaks]], verändert allerdings nur jeweils das Verhalten des Geräts, bei dem es gesetzt ist. Auch dieses Attribut wird zeilenweise eingelesen, es können ein oder mehrere der folgenden Optionen gesetzt werden:&lt;br /&gt;
&lt;br /&gt;
==== group ====&lt;br /&gt;
::Wird dieser Schlüssel gesetzt, wird das Gerät bei Gruppenaktionen nicht direkt adressiert, sondern die hier angegebene Gruppe. Details hierzu sind in [[RHASSPY/Vertiefung#Timing-Aspekte| Vertiefung - Timing-Aspekte]] zu finden.&lt;br /&gt;
&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;attr lamp1 rhasspySpecials group:async_delay=100 prio=1 group=lights&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== numericValueMap ====&lt;br /&gt;
::Ermöglicht es, statt der allgemeinen Methode zum Umgang mit numerischen Werten einzelnen Werten spezielle Kommandos zuzuweisen. Dies kann z.B. hilfreich sein, um spezielle Positionen für Rollladengeräte anzusteuern.&lt;br /&gt;
::&#039;&#039;&#039;Beispiel&#039;&#039;&#039;:&lt;br /&gt;
::&amp;lt;code&amp;gt;attr blind1 rhasspySpecials numericValueMap:10=&#039;Event Slit&#039; 50=&#039;myPosition&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
::führt dazu, dass ein numerischer Wert von 10 (im {Value}-key) das Kommando &amp;lt;code&amp;gt;set blind1 Event Slit&amp;lt;/code&amp;gt; ausführt.&lt;br /&gt;
&lt;br /&gt;
==== venetianBlind ====&lt;br /&gt;
Siehe [[RHASSPY/Vertiefung#Jalousien|Vertiefung - Jalousien]]&lt;br /&gt;
&lt;br /&gt;
==== colorCommandMap ====&lt;br /&gt;
Sowie **colorTempMap** und **colorForceHue2rgb**&lt;br /&gt;
Siehe [[RHASSPY/Vertiefung#Farben|Vertiefung - Farben]]&lt;br /&gt;
&lt;br /&gt;
==== priority ====&lt;br /&gt;
Ermöglicht es, Rückfragen zu vermeiden, wenn mehrere Geräte für bestimmte Aktionen in Frage kommen. Siehe [[RHASSPY/Vertiefung#Einer_statt_alle|Einer statt alle]]&lt;br /&gt;
&lt;br /&gt;
==== confirm ====&lt;br /&gt;
Ist eine Möglichkeit, Geräte nur nach Rückfrage und Bestätigung zu schalten (ähnlich wie &#039;&#039;confirmIntents&#039;&#039; in &#039;&#039;rhasspyTweaks&#039;&#039;). Es können entweder einfach nur Intent-Namen angegeben werden, oder Paare von **Intent** und zugehöriger **response**:&lt;br /&gt;
 SetOnOff=&amp;quot;Soll $target wirklich $Value geschaltet werden&amp;quot; SetScene&lt;br /&gt;
&lt;br /&gt;
==== confirmValueMap ====&lt;br /&gt;
Kann spezielle Übersetzungen für $Value enthalten, z.B. für Rollladen-Geräte:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;confirm: SetOnOff=&amp;quot;wirklich $Value $target&amp;quot;&lt;br /&gt;
confirmValueMap: on=öffnen off=schließen&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== scenes ====&lt;br /&gt;
Wird bei der automatisierten Erfassung erkannt, dass ein Gerät das Setzen von Szenen unterstützt, werden die erkannten Szenen-Namen an Rhasspy übergeben. Da diese häufig technischer Natur sind, eignen sie sich nicht für eine Spracherkennung. Über diesen Schlüssel können daher sprechbare Namen für jede Szene vergeben werden, und/oder einzelne bzw. alle Szenen von der Erkennung ausgenommen werden. Der Kenner &#039;&#039;none&#039;&#039; löscht die Szene von der Liste der übermittelten Szenen, wird die Kombination &#039;&#039;all=none&#039;&#039; angegeben, wird dieses Gerät insgesamt von der Vorbereitung für den Intent &#039;&#039;SetScene&#039;&#039; ausgeschlossen.&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;attr lamp1 rhasspySpecials scenes:scene2=&amp;quot;Kino zu zweit&amp;quot; scene3=Musik scene1=none scene4=none&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Siehe auch [[RHASSPY/Vertiefung#echte_Szenen|Vertiefung - echte Szenen]]. &lt;br /&gt;
&lt;br /&gt;
=== Veraltete Attribute ===&lt;br /&gt;
In der Regel sollte es ausreichen, die zu steuernden Devices über die oben genannten Attribute zu konfigurieren. Es gibt jedoch noch zwei ältere Methoden. Um diese zu verwenden, muss zuerst jeweils ein entsprechendes User-Attribut im FHEM-Device, das damit gesteuert werden soll, angelegt werden.&lt;br /&gt;
&lt;br /&gt;
====&amp;lt;code&amp;gt;rhasspyChannels&amp;lt;/code&amp;gt;====&lt;br /&gt;
Das Attribut wird vom Intent &#039;&#039;MediaControls&#039;&#039; verwendet. Es informiert den Intent darüber, welche (Medien-)Kanäle vorhanden sind und welcher FHEM-Befehl oder Perl-Code auszuführen ist, wenn auf diesen Kanal geschaltet werden soll.&lt;br /&gt;
&lt;br /&gt;
In diesem Attribut muss eine Zeile pro (Medien-)Kanal verwendet werden.&lt;br /&gt;
&lt;br /&gt;
Um rhasspyChannels zu verwenden, muss zuerst ein neues User-Attribut im FHEM-Device, das damit gesteuert werden soll, angelegt werden. Dafür kann z.B. dieses Beispiel verwendet werden: &amp;lt;code&amp;gt;attr &amp;lt;deviceName&amp;gt; userattr rhasspyChannels:textField-long&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr &amp;lt;device&amp;gt; rhasspyChannels orf eins=channel 201&lt;br /&gt;
orf zwei=channel 202&lt;br /&gt;
orf drei=channel 203&lt;br /&gt;
netflix=launchApp Netflix&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&amp;lt;code&amp;gt;rhasspyColors&amp;lt;/code&amp;gt;====&lt;br /&gt;
Ältere Methode, die verwendet werden kann, um Lichtfarben zu wechseln. Es wird nachdrücklich empfohlen, die neueren Methoden über die (nummerisch zu übergebenden) allgemeinen Farbwerte und/oder ein &#039;&#039;colorCommandMap&#039;&#039; oder &#039;&#039;colorTempMap&#039;&#039; (siehe &#039;&#039;rhasspySpecials&#039;&#039;) zu konfigurieren!&lt;br /&gt;
&lt;br /&gt;
Um das Mapping zu verwenden, muss zuerst ein User-Attribut am zu steuernden Gerät angelegt werden. Z.B. &amp;lt;code&amp;gt;attr &amp;lt;deviceName&amp;gt; userattr rhasspyChannels:textField-long&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Eine Zeile pro Farbe&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr lamp1 rhasspyColors rot=rgb FF0000&lt;br /&gt;
grün=rgb 008000&lt;br /&gt;
blau=rgb 0000FF&lt;br /&gt;
gelb=rgb FFFF00&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Intents ==&lt;br /&gt;
Intents werden verwendet um FHEM zu sagen, was es nach einem erhaltenen Sprach-/Textkommand unternehmen soll. Dieses Modul stellt einige Intents bereit.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Wichtig&lt;br /&gt;
:*Bei Tags (&amp;lt;code&amp;gt;Value&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;, etc.) ist die Schreibweise sehr wichtig! Die sind case-sensitive. Bitte daher genau so schreiben, wie sie in dieser Dokumentation vorkommen.&lt;br /&gt;
:*RHASSPY erstellt bei einem &amp;lt;code&amp;gt;update slots&amp;lt;/code&amp;gt; auch Slots je nach Möglichkeiten der Geräte oder Gruppen. Unterstützt ein Gerät zum Beispiel den Intent &#039;&#039;GetNumeric&#039;&#039;, wird auch ein Slot &amp;lt;code&amp;gt;de.fhem.Device-GetNumeric&amp;lt;/code&amp;gt; erstellt. Ein Gerät, dass ein- und ausgeschalten werden kann, wird im Slot &amp;lt;code&amp;gt;de.fhem.Device-SetOnOff&amp;lt;/code&amp;gt; untergebracht. Ein einzelnes Gerät kann sich auch in mehreren Slots befinden. Um eine möglichst genaue Spracherkennung zu gewährleisten, ist &#039;&#039;&#039;empfohlen&#039;&#039;&#039;, diese &#039;&#039;&#039;spezifischen Slots&#039;&#039;&#039; - statt einfach nur &amp;lt;code&amp;gt;de.fhem.Device&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;de.fhem.Group&amp;lt;/code&amp;gt; - &#039;&#039;&#039;zu verwenden&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetOnOff ===&lt;br /&gt;
Intent um Geräte zwischen zwei Zuständen (ein/aus, auf/zu, start/stop) zu schalten.&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
SetOnOff:cmdOn=on,cmdOff=off&lt;br /&gt;
SetOnOff:cmdOn=on,cmdOff=off,response=&amp;quot;Sir yes Sir&amp;quot;&lt;br /&gt;
SetOnOff:cmdOn=on,cmdOff=off,response=&amp;quot;$DEVICE now [$DEVICE:state]&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Argumente:&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdOn&amp;lt;/code&amp;gt; Befehl um das Gerät einzuschalten. Siehe [[#Formatierung von Befehlen und Readings innerhalb eines rhasspyMappings|Formatierung von Befehlen und Readings innerhalb eines rhasspyMappings]].&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdOff&amp;lt;/code&amp;gt; Befehl um das Gerät auszuschalten. Siehe [[#Formatierung von Befehlen und Readings innerhalb eines rhasspyMappings|Formatierung von Befehlen und Readings innerhalb eines rhasspyMappings]].&lt;br /&gt;
&lt;br /&gt;
Optionale Argumente:&lt;br /&gt;
*&amp;lt;code&amp;gt;response&amp;lt;/code&amp;gt; Eine benutzerdefinierte Antwort auf den Befehl&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
schalten das licht ein&lt;br /&gt;
schließe den rollladen im schlafzimmer&lt;br /&gt;
starte die kaffeemaschine&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetOnOff]&lt;br /&gt;
(schalte|schalt|mache|mach|stelle|stell|starte) [den|die|das] $de.fhem.Device-SetOnOff{Device} [[(im|in dem|auf dem|in der|auf der)] $de.fhem.Room{Room}] (an|ein){Value:on}&lt;br /&gt;
(schalte|schalt|mache|mach|stelle|stell) [den|die|das] $de.fhem.Device-SetOnOff{Device} [[(im|in dem|auf dem|in der|auf der)] $de.fhem.Room{Room}] aus{Value:off}&lt;br /&gt;
(fahre|fahr) [den|die|das] $de.fhem.Device-blind{Device} [[(im|in dem|auf dem|in der|auf der)] $de.fhem.Room{Room}] ((hoch|auf){Value:on}|(zu|runter){Value:off})&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verpflichtende Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Value:on&amp;lt;/code&amp;gt; und/oder &amp;lt;code&amp;gt;Value:off&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetOnOffGroup ===&lt;br /&gt;
Intent um Gruppen von Geräte zwischen zwei Zuständen zu schalten.&lt;br /&gt;
&lt;br /&gt;
Dafür ist ein SetOnOff-Mapping benötigt und alle gewünschten Geräte müssen dasselbe Attribut &amp;lt;code&amp;gt;group&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;rhasspyGroup&amp;lt;/code&amp;gt; haben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
schalte alle lampen in der küche aus&lt;br /&gt;
schließe alle rollläden im schlafzimmer&lt;br /&gt;
schalte alle lampen aus&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetOnOffGroup]&lt;br /&gt;
\[(schalt|mach)] (alle | sämtliche ) $de.fhem.Group-SetOnOff{Group} [[in|im|in der|auf der] [( überall:global | $de.fhem.Room ){Room}] ein{Value:on}&lt;br /&gt;
\[(schalt|mach)] (alle | sämtliche ) $de.fhem.Group-SetOnOff{Group} [[in|im|in der|auf der] [( überall:global | $de.fhem.Room ){Room}] aus{Value:off}&lt;br /&gt;
(öffne{Value:on}|schließe{Value:off}) (alle | sämtliche ) $de.fhem.Group-blind{Group} [[in|im|in der|auf der] [( überall:global{Room:global} | $de.fhem.Room{Room} )] &lt;br /&gt;
(fahr|fahre|mach|mache) [den|die|das] $de.fhem.Group-blind{Group} [[(im|in dem|in der)] ( überall:global{Room:global} | $de.fhem.Room{Room} )] ( auf{Value:on} | hoch{Value:on} | zu{Value:off} | runter{Value:off} )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verpflichtende Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Value:on&amp;lt;/code&amp;gt; und/oder &amp;lt;code&amp;gt;Value:off&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Group&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetTimedOnOff ===&lt;br /&gt;
Intent um Geräte für eine bestimmte Zeitspanne in einen bestimmten Zustand zu versetzten.&lt;br /&gt;
&lt;br /&gt;
Device muss ein SetOnOff-Mapping haben und die {{Link2CmdRef|Anker=setExtensions|Lang=de|Label=SetExtentions}} unterstützen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
schalte das licht für eine minute und dreißig sekunden aus&lt;br /&gt;
schalte die musik im bad bis zwei uhr ein&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetTimedOnOff]&lt;br /&gt;
schalte $de.fhem.Device-SetOnOff{Device} [$de.fhem.Room{Room}] für ([(1..60){Hour!int} (stunde|stunden)] [und] [(1..60){Min!int} (minute|minuten)] [und] [(1..60){Sec!int} (sekunde|sekunden)]) (ein{Value:on}|aus{Value:off})&lt;br /&gt;
schalte $de.fhem.Device-SetOnOff{Device} [$de.fhem.Room{Room}] bis (0..24){Hourabs!int} [(1..60){Min!int}] (ein{Value:on}|aus{Value:off})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verpflichtende Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Value&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Hour&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Min&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Sec&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Hourabs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetTimedOnOffGroup ===&lt;br /&gt;
Intent um eine Gruppe von Geräten für eine bestimmte Zeit zu schalten.&lt;br /&gt;
&lt;br /&gt;
Devices müssen ein SetOnOff-Mapping haben, in einer Gruppe sein und die {{Link2CmdRef|Anker=setExtensions|Lang=de|Label=SetExtentions}} unterstützen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
schalte alle lichter in der küche für fünfzig sekunden ein&lt;br /&gt;
schalte alle licher bis zwei uhr ein&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetTimedOnOffGroup]&lt;br /&gt;
schalte $de.fhem.Group-SetOnOff{Group} [$de.fhem.Room{Room}] für ([(1..60){Hour!int} (stunde|stunden)] [und] [(1..60){Min!int} (minute|minuten)] [und] [(1..60){Sec!int} (sekunde|sekunden)]) (ein{Value:on}|aus{Value:off})&lt;br /&gt;
schalte $de.fhem.Group-SetOnOff{Group} [$de.fhem.Room{Room}] bis (0..24){Hourabs!int} [(1..60){Min!int}] (ein{Value:on}|aus{Value:off})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verpflichtende Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Value&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Group&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Hour&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Min&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Sec&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Hourabs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GetOnOff ===&lt;br /&gt;
Intent um den aktuellen Zustand eines Gerätes zu erfragen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
GetOnOff:currentVal=state,valueOff=closed&lt;br /&gt;
GetOnOff:currentVal=state,valueOn=on&lt;br /&gt;
GetOnOff:currentVal=pct,valueOff=0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Argumente:&lt;br /&gt;
Hinweis: nur &amp;lt;code&amp;gt;valueOn&amp;lt;/code&amp;gt; ODER &amp;lt;code&amp;gt;valueOff&amp;lt;/code&amp;gt; müssen gesetzt werden. Der jeweils andere Wert bekommt den anderen Status.&lt;br /&gt;
*&amp;lt;code&amp;gt;currentVal&amp;lt;/code&amp;gt; Reading aus dem der aktuelle Status hervorgeht&lt;br /&gt;
*&amp;lt;code&amp;gt;valueOff&amp;lt;/code&amp;gt; Wert, der den Zustand &#039;&#039;aus&#039;&#039; beschreibt&lt;br /&gt;
*&amp;lt;code&amp;gt;valueOn&amp;lt;/code&amp;gt; Wert, der den Zustand &#039;&#039;an&#039;&#039; beschreibt&lt;br /&gt;
&lt;br /&gt;
Optionale Argumente:&lt;br /&gt;
*&amp;lt;code&amp;gt;response&amp;lt;/code&amp;gt; Eine benutzerdefinierte Antwort auf den Befehl&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
ist das licht im bad ein&lt;br /&gt;
ist das fenster im wohnzimmer geöffnet&lt;br /&gt;
läuft die waschmaschine&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[en.fhem:GetOnOff]&lt;br /&gt;
ist $de.fhem.Device-GetOnOff{Device} [$de.fhem.Room{Room}] (ein|geöffnet){State:on}&lt;br /&gt;
ist $de.fhem.Device-GetOnOff{Device} [$de.fhem.Room{Room}] (aus|geschlossen){State:off}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zustände &#039;&#039;ein&#039;&#039; und &#039;&#039;aus&#039;&#039; sollten in unterschiedlichen Sentences sein und müssen &amp;lt;code&amp;gt;{State:on}&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;{State:off}&amp;lt;/code&amp;gt; beinhalten.&lt;br /&gt;
&lt;br /&gt;
Verpflichtende Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;State:on&amp;lt;/code&amp;gt; und/oder &amp;lt;code&amp;gt;State:off&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetNumeric ===&lt;br /&gt;
Intent, um Lampen zu dimmen, Rollladengeräte zu positionieren, Lautstärken oder Solltemperaturen zu ändern, usw.. &lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
SetNumeric:currentVal=pct,cmd=dim,minVal=0,maxVal=99,step=25,type=brightness&lt;br /&gt;
SetNumeric:currentVal=volume,cmd=volume,minVal=0,maxVal=99,step=10,type=volume&lt;br /&gt;
SetNumeric:currentVal=brightness,cmd=brightness,minVal=0,maxVal=255,map=percent,step=1,type=brightness&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Argumente:&lt;br /&gt;
*&amp;lt;code&amp;gt;currentVal&amp;lt;/code&amp;gt; Reading, in dem der aktuelle Wert zu finden ist (wird zwingend benötigt).&lt;br /&gt;
*&amp;lt;code&amp;gt;part&amp;lt;/code&amp;gt; Kann genutzt werden, um den Wert aus **currentVal** in mehrere Teile zu zerlegen (getrennt wird am Leerzeichen). Z.B. wenn currentVal 23 C ist, wird **part=0** **23** ergeben. Optionaler Parameter.&lt;br /&gt;
*&amp;lt;code&amp;gt;cmd&amp;lt;/code&amp;gt; Das **Set**-Kommando des Geräts, das in Folge des Sprachkommandos ausgeführt werden soll. (Notwendiger Parameter).&lt;br /&gt;
*&amp;lt;code&amp;gt;minVal&amp;lt;/code&amp;gt; Niedrigster zugelassener Wert, optional.&lt;br /&gt;
*&amp;lt;code&amp;gt;maxVal&amp;lt;/code&amp;gt; Höchster zugelassener Wert, optional.&lt;br /&gt;
*&amp;lt;code&amp;gt;step&amp;lt;/code&amp;gt; Schrittweite für relative Änderungen wie &amp;lt;code&amp;gt;mach lauter&amp;lt;/code&amp;gt;. Optional. Default: 10.&lt;br /&gt;
*&amp;lt;code&amp;gt;map&amp;lt;/code&amp;gt; Derzeit wird ausschließlich die Angabe **percent** ausgewertet. Optionaler Parameter, der bewirkt, dass alle Angaben als Prozentwert (zwischen minVal und maxVal) interpretiert werden und entsprechend gerechnet wird. So wird z.B. eine Leuchte mit **minVal=0** und **maxVal=255** beim Befehl &amp;quot;stelle das Licht auf 50&amp;quot; dies so verstehen, als wäre die Anweisung &amp;quot;stelle das Licht auf 50 Prozent&amp;quot; gewesen. Das Licht wird daher auf 127 gestellt, und nicht auf (absolut) 50.&lt;br /&gt;
*&amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; Zur Unterscheidung, falls mehrere SetNumeric-Intents für das Gerät möglich sind. Empfohlener Parameter.&lt;br /&gt;
&lt;br /&gt;
Gut zu wissen:&lt;br /&gt;
Um Kommandos wie **lauter** oder **leiser** ohne Angabe eines Gerätes ausführen zu können, muss RHASSPY zunächst ermitteln, welches Gerät gerade überhaupt etwas wiedergibt ist. Daher nutzt es die GetOnOff-Mappings, um festzustellen, welches Gerät vom **type=volume** überhaupt angeschaltet ist. Dabei wird wie üblich zunächst im aktuellen rhasspyRoom gesucht, bevor die Suche außerhalb fortgesetzt wird.&lt;br /&gt;
Setzt man also Mappings manuell, ist es ratsam, auch ein **GetOnOff**-Mapping zu setzen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zulässige Typen sind:&lt;br /&gt;
*&amp;lt;code&amp;gt;brightness&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;setTarget&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;temperature&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;volume&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
Stelle das Licht auf 30 Prozent&lt;br /&gt;
Mach das Radio leiser&lt;br /&gt;
Stell die Temperatur im Wohnzimmer 2 Grad wärmer&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
(Beachte: Wenn wie hier im Beispiel reele Zahlen (mit Komma) ermöglicht werden sollen (&amp;quot;acht Komma fünf&amp;quot;), wird ein [[#Custom Converter für reelle Zahlen| Custom Converter für reelle Zahlen]] benötigt)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetNumeric]&lt;br /&gt;
den=(den|die|das)&lt;br /&gt;
cmdmulti=(schalte|schalt|mache|mach|stelle|stell)&lt;br /&gt;
rooms=([(im|in dem|auf dem|in der|auf der)] $de.fhem.Room{Room})&lt;br /&gt;
&amp;lt;cmdmulti&amp;gt; [&amp;lt;den&amp;gt;] $de.fhem.Device-SetNumeric{Device} auf (0..100){Value!int} [Prozent{Unit:percent}]&lt;br /&gt;
\[&amp;lt;cmdmulti&amp;gt;] [die Lautstärke [an|am]] [dem|&amp;lt;den&amp;gt;] $de.fhem.Device-media{Device} [&amp;lt;rooms&amp;gt;] [um] [(0..10){Value!float}] [dezibel{Unit:decibel}|Prozent{Unit:percent}] ( lauter:volUp | leiser:volDown ){Change}&lt;br /&gt;
&amp;lt;cmdmulti&amp;gt; [die Lautstärke [an|am]] [dem|&amp;lt;den&amp;gt;] [$de.fhem.Device-media{Device}] [&amp;lt;rooms&amp;gt;] [um] [(0..10){Value!float}] [dezibel{Unit:decibel}|Prozent{Unit:percent}] ( lauter:volUp | leiser:volDown ){Change}&lt;br /&gt;
&amp;lt;cmdmulti&amp;gt; [&amp;lt;den&amp;gt;] $de.fhem.Device-thermostat{Device} [&amp;lt;rooms&amp;gt;] [um] [(0..10){Value!int}] [Grad{Unit.degree}] ( wärmer:tempUp | kälter:tempDown ){Change}&lt;br /&gt;
&amp;lt;cmdmulti&amp;gt; [&amp;lt;den&amp;gt;] $de.fhem.Device-light{Device} [&amp;lt;rooms&amp;gt;] [um] [(0..30 [Komma:. 1..9]){Value!customFloat}] [Prozent{Unit:percent}] ( heller:lightUp | dunkler:lightDown){Change}&lt;br /&gt;
&amp;lt;cmdmulti&amp;gt; [&amp;lt;den&amp;gt;] ( $de.fhem.Device-light | $de.fhem.Device-media |$de.fhem.Device-blind){Device}  [&amp;lt;rooms&amp;gt;] auf [(0..30 [Komma:. 1..9]){Value!customFloat}]&lt;br /&gt;
( mehr{Change:lightUp} | weniger{Change:lightDown} ) $de.fhem.Device-light{Device} [&amp;lt;de.fhem:SetOnOff.rooms&amp;gt;]&lt;br /&gt;
( halte | stoppe | stop ) [&amp;lt;den&amp;gt;] $de.fhem.Device-blind{Device} [&amp;lt;de.fhem:SetOnOff.rooms&amp;gt;] [an] {Change:cmdStop}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Derzeit werden folgende Typen für das Feld &amp;lt;code&amp;gt;{Change}&amp;lt;/code&amp;gt; ausgewertet:&lt;br /&gt;
*&amp;lt;code&amp;gt;tempUp&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;tempDown&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;volUp&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;volDown&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;lightUp&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;lightDown&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;setUp&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;setDown&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notwendig sind:&lt;br /&gt;
*&amp;lt;code&amp;gt;Change&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Type&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Value&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Change&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Unit&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== SetNumericGroup ===&lt;br /&gt;
Intent, um Lampen zu dimmen, Rollladengeräte zu positionieren, Lautstärken oder Solltemperaturen zu ändern, usw.. Die Funktionsweise entspricht dabei dem des Intents &#039;&#039;SetNumeric&#039;&#039;, wobei eben statt eines einzelnen Devices eben ein oder mehrere Geräte über ihren Gruppennamen angesprochen werden. Statt des optionalen Tags &amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt; ist daher der Tag &amp;lt;code&amp;gt;Group&amp;lt;/code&amp;gt; zu übergeben.&lt;br /&gt;
Aus der Adressierung mehrerer Geräte ergeben sich einige Besonderheiten, die in der [[RHASSPY/Vertiefung]], dort speziell auch im Punkt [[RHASSPY/Vertiefung#Beispiel_SetOnOffGroup|Beispiel SetOnOffGroup]] näher erläutert sind. Wesentliche zu beachtende Aspekte sind:&lt;br /&gt;
* Vermeidung von Funk-Überschneidungen (&#039;&#039;Specials&#039;&#039; &#039;&#039;partOf&#039;&#039; und &#039;&#039;async_delay&#039;&#039;)&lt;br /&gt;
* Begrenzung der Gruppenzugehörigkeit durch die Raumzugehörigkeit (und die Aufhebung dieser Beschränkung durch die Übergabe des speziellen Raums &#039;&#039;global&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
=== GetNumeric ===&lt;br /&gt;
Intent, mit dem man Werte erfragen kann, wie z.B. die aktuelle Temperatur, Helligkeit, Lautstärke, ...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
GetNumeric:currentVal=temperature,part=1,type=temperature&lt;br /&gt;
GetNumeric:currentVal=pct,map=percent,minVal=0,maxVal=100,type=brightness&lt;br /&gt;
GetNumeric:currentVal=volume,type=volume&lt;br /&gt;
GetNumeric:currentVal=humidity,part=0,type=airHumidity&lt;br /&gt;
GetNumeric:currentVal=batteryPercent,type=battery&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Argumente:&lt;br /&gt;
*&amp;lt;code&amp;gt;currentVal&amp;lt;/code&amp;gt; Das Reading, das den abzufragenden Wert enthält&lt;br /&gt;
*&amp;lt;code&amp;gt;part&amp;lt;/code&amp;gt; Teile aus currentVal ableiten, indem am Leerzeichen getrennt wird. Ist &#039;&#039;currentVal&#039;&#039; beispielsweise &#039;&#039;23 C&#039;&#039;, entspricht &#039;&#039;part=1&#039;&#039; dem Wert &#039;&#039;23&#039;&#039;&lt;br /&gt;
*&amp;lt;code&amp;gt;map&amp;lt;/code&amp;gt; Die Funktionswiese entspricht dem &#039;&#039;SetNumeric&#039;&#039; Intent. Wandelt den vorhandenen Wert in eine Prozent-Angabe um.&lt;br /&gt;
*&amp;lt;code&amp;gt;minVal&amp;lt;/code&amp;gt; Niedrigster zulässiger Wert (nur benötigt, wenn &#039;&#039;map&#039;&#039; angegeben ist).&lt;br /&gt;
*&amp;lt;code&amp;gt;maxVal&amp;lt;/code&amp;gt; Höchster zulässiger Wert  (nur benötigt, wenn &#039;&#039;map&#039;&#039; angegeben ist).&lt;br /&gt;
*&amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; Dient der Unterscheidung zwischen mehreren GetNumeric-Anfragemöglichkeiten für dasselbe Gerät (auch relevant für SetNumeric-Anweisungen).&lt;br /&gt;
&lt;br /&gt;
Mögliche Abfragetypen:&lt;br /&gt;
*&amp;lt;code&amp;gt;airHumidity&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;battery&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;brightness&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;desired-temp&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;setTarget&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;soilMoisture&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;temperature&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;volume&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;waterLevel&amp;lt;/code&amp;gt;&lt;br /&gt;
Aus dem Abfragetypen ergibt sich die von RHASSPY ausgewählte Antwort.&lt;br /&gt;
&lt;br /&gt;
Beispiel Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
what is the temperature in the living room&lt;br /&gt;
how bright is the floor lamp&lt;br /&gt;
what is the volume of the tv&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
[en.fhem:GetNumeric]&lt;br /&gt;
#actual temperature&lt;br /&gt;
(what is|how high is) the temperature{Type:temperature} [$de.fhem.Device-GetNumeric{Device}] [$de.fhem.Room{Room}]&lt;br /&gt;
&lt;br /&gt;
#desired-temperature&lt;br /&gt;
\[what is the|how high is the] (desired temperature){Type:desired-temp} [$de.fhem.Device-GetNumeric{Device}] [$de.fhem.Room{Room}]&lt;br /&gt;
&lt;br /&gt;
#volume&lt;br /&gt;
(what is the|how high is the) volume{Type:volume} $de.fhem.Device-GetNumeric{Device} [$de.fhem.Room{Room}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Type&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional tags&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GetState ===&lt;br /&gt;
Intent to get specific information of a device. The respone can be defined.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
GetState:response=&amp;quot;Temperature is [$DEVICE:temp] degree at [Thermo:hum] percent humidity&amp;quot;&lt;br /&gt;
GetState:response={my $value=ReadingsVal(&amp;quot;$DEVICE&amp;quot;,&amp;quot;brightness&amp;quot;,&amp;quot;&amp;quot;); return &amp;quot;Brightness is $value&amp;quot;;}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Options:&lt;br /&gt;
*&amp;lt;code&amp;gt;response&amp;lt;/code&amp;gt; Text for the response Rhassyp will give.&lt;br /&gt;
:To use values from FHEM use format [Device:Reading].&lt;br /&gt;
:A comma within the response has to be escaped (\, instead of ,).&lt;br /&gt;
:Or you can use Perl-code enclosed in curley brackets to define the response.&lt;br /&gt;
:Mixing text and Perl-code is not supported.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
How is the state of the thermostat in the kitchen&lt;br /&gt;
state light in livingroom&lt;br /&gt;
state washer&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:GetState]&lt;br /&gt;
\[how is the] (state) $de.fhem.Device{Device} [$de.fhem.Room{Room}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== MediaControls ===&lt;br /&gt;
Intent to control media devices&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mapping:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
MediaControls:cmdPlay=play,cmdPause=pause,cmdStop=stop,cmdBack=previous,cmdFwd=next&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Options:&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdPlay&amp;lt;/code&amp;gt; Play command of the device. See chapter Formatting Commands and Readings inside a rhasspyMapping.&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdPause&amp;lt;/code&amp;gt; Command to pause the device.&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdStop&amp;lt;/code&amp;gt; Command to stop the device.&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdFwd&amp;lt;/code&amp;gt; Command to skip to the next track/channel/etc.&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdBack&amp;lt;/code&amp;gt; Command to skip to the previous track/channel/etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note on issuing a voice-command without a room-name:&lt;br /&gt;
As described in the SetNumeric-Intent, it is recommended to define a GetOnOff-Mapping to use the MediaControls-Intent without a room name.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
skip to next track on the radio&lt;br /&gt;
pause&lt;br /&gt;
skip video on the dvd player&lt;br /&gt;
stop playback&lt;br /&gt;
next&lt;br /&gt;
previous&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:MediaControls]&lt;br /&gt;
(start){Command:cmdPlay} the playback [$de.fhem.Device-MediaControls{Device}]&lt;br /&gt;
(stop){Command:cmdStop} the playback [$de.fhem.Device-MediaControls{Device}]&lt;br /&gt;
(pause){Command:cmdPause} the playback [$de.fhem.Device-MediaControls{Device}]&lt;br /&gt;
(next){Command:Fwd} (song|title) [$de.fhem.Device-MediaControls{Device}]&lt;br /&gt;
(previous){Command:Back} (song|title) [$de.fhem.Device-MediaControls{Device}] [$de.fhem.Room{Room}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Command&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== MediaChannels ===&lt;br /&gt;
Intent to change radio-/tv channels, favorites, playlists, lightscenes, ...&lt;br /&gt;
&lt;br /&gt;
Instead of using the attribute rhasspyMapping, this intent is configured with an own attribute [[#rhasspyChannels]] in the respective device. Reason is the multiple-line-configuration.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
SWR3=favorite s_w_r_3&lt;br /&gt;
SWR1=favorite s_w_r_1&lt;br /&gt;
ARD=channel 204&lt;br /&gt;
Netflix=launchApp Netflix&lt;br /&gt;
Leselicht=set lightSceneWz scene Leselicht&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Notice on using the commands without a device name:&lt;br /&gt;
To start playback on a device without specifying the device name in the voice command, the module needs to know, which device should be used. Therefor it searches the attribute rhasspyChannels for suitable one. Devices in the actual or spoken room are preferred.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
play CNN on the radio in my office&lt;br /&gt;
switch to HBO&lt;br /&gt;
change channel on radio to BBC news&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[en.fhem:MediaChannels]&lt;br /&gt;
\[(play|switch to|change to)] ($de.fhem.MediaChannels){Channel} [($de.fhem.Device){Device}] [($de.fhem.Room){Room}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Channel&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetColor ===&lt;br /&gt;
Intent to change light colors&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Because of the multi-line settings, instead of configuring this intent with the attribute rhasspyMapping, a separate user-attribute [[#rhasspyColors]] is used.&lt;br /&gt;
&lt;br /&gt;
The content of the rhasspyColors uses the following format:&lt;br /&gt;
&amp;lt;code&amp;gt;Colorname=cmd&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Settings:&lt;br /&gt;
*&amp;lt;code&amp;gt;Colorname&amp;lt;/code&amp;gt; The name of the color you want to use in a voice-command&lt;br /&gt;
*&amp;lt;code&amp;gt;cmd&amp;lt;/code&amp;gt; The FHEM-command&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
red=rgb FF0000&lt;br /&gt;
green=rgb 00FF00&lt;br /&gt;
blue=rgb 0000FF&lt;br /&gt;
white=ct 3000&lt;br /&gt;
warm white=ct 2700&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
change light to green&lt;br /&gt;
lightstrip blue&lt;br /&gt;
color the light in the sleeping room white&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[en.fhem:SetColor]&lt;br /&gt;
\[change|color] $de.fhem.Device{Device} [$de.fhem.Room{Room}] $de.fhem.Color{Color}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Color&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional tags&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetColorGroup ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetScene ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GetTime ===&lt;br /&gt;
Intent um die Uhrzeit zu erfragen.&lt;br /&gt;
&lt;br /&gt;
Es werden keine Konfigurationen in FHEM benötigt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
wie spät ist es?&lt;br /&gt;
sag mir die uhrzeit&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:GetTime]&lt;br /&gt;
wie spät [ist es]&lt;br /&gt;
sag mir die uhrzeit&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GetDate ===&lt;br /&gt;
Intent um das aktuelle Datum zu erfragen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Keine FHEM Einstellungen nötig.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Satz:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
welcher tag ist heute&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:GetDate]&lt;br /&gt;
welcher tag ist heute&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetTimer ===&lt;br /&gt;
Intent to create a timer/countdown/alarm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This intent creates an AT-command in FHEM with the given time and - currently - speaks the sentences &amp;quot;timer expired&amp;quot; when it has expired.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
No FHEM-settings needed&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
Set timer in bedroom to five minutes&lt;br /&gt;
Set countdown in the kitchen to two hours&lt;br /&gt;
set timer to five and a half hours&lt;br /&gt;
set alarm to 5 o&#039; clock&lt;br /&gt;
set timer to 3 hours and 20 minutes&lt;br /&gt;
set timer to 1 hour, 30 minutes and 15 seconds&lt;br /&gt;
stop the timer in bedroom&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentence:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetTimer]&lt;br /&gt;
labels=(alarm|teetimer|countdown|timer)&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in) [((1..60){Hour!int} (hour|hours))] [and] [((1..60){Min!int} (minute|minutes))] [and] [((1..60){Sec!int} (second|seconds))]&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in) (1..60){Hour!int} and (a quarter{Min:15}|a half{Min:30}|three quarters{Min:45}) (hour|hours)&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in) (1..60){Min!int} and (a quarter{Sec:15}|a half{Sec:30}|three quarters{Sec:45}) (minute|minutes)&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in) ((the fourth){Min:15}|(half a){Min:30}|(three fourth){Min:45}) (hour)&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in) ((the fourth){Min:15}|(half a){Min:30}|(three fourth){Min:45}) (minute)&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in|at) (1..24){Hourabs!int} [(1..60){Min!int}] o clock&lt;br /&gt;
&lt;br /&gt;
(cancel|remove|stop|delete){CancelTimer} [&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags to set a timer:&lt;br /&gt;
*&amp;lt;code&amp;gt;Label&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Hour&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Hourabs&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Min&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Sec&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags to cancel a timer:&lt;br /&gt;
*&amp;lt;code&amp;gt;Label&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
rhasspyTweaks for Timer:&lt;br /&gt;
*&amp;lt;code&amp;gt;[[#attr-rhasspytweaks-timerlimits|timerLimits]]&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;[[#attr-rhasspytweaks-timersounds|timerSounds]]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetMute ===&lt;br /&gt;
Intent to disable/enable the processing of intents on a specific siteId. Rhasspy will still listen to the wakeword but will not process any intents.&lt;br /&gt;
&lt;br /&gt;
This intents creates a Reading &amp;lt;code&amp;gt;mute_siteId&amp;lt;/code&amp;gt; for every siteId it get&#039;s a voice-command from.&lt;br /&gt;
&lt;br /&gt;
No FHEM-settings needed&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
good night&lt;br /&gt;
be quiet&lt;br /&gt;
good morning&lt;br /&gt;
make noise&lt;br /&gt;
start listening&lt;br /&gt;
stop listening&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetMute]&lt;br /&gt;
(good night|be quiet){Value:on}&lt;br /&gt;
(good morning|make noise){Value:off}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hinweis: Die Felder &amp;lt;code&amp;gt;{Value:on}&amp;lt;/code&amp;gt; bzw. &amp;lt;code&amp;gt;{Value:off}&amp;lt;/code&amp;gt; sind verpflichtend und &#039;&#039;case sensitive&#039;&#039;, der Wert &#039;&#039;on&#039;&#039; bzw. &#039;&#039;off&#039;&#039; ist in Englisch anzugeben!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ConfirmAction ===&lt;br /&gt;
Dies ist - wie die drei folgenden Intents &#039;&#039;CancelAction&#039;&#039;, &#039;&#039;ChoiceRoom&#039;&#039; und &#039;&#039;ChoiceDevice&#039;&#039; auch - ein Intent, der im Rahmen von Dialogen benötigt wird. Siehe dazu auch [[RHASSPY/Vertiefung#Dialoge|Vertiefung - Dialoge]].&lt;br /&gt;
Rückgabe ist zwingend &amp;lt;code&amp;gt;{Mode}&amp;lt;/code&amp;gt; mit dem Wert &#039;&#039;OK&#039;&#039;, alles andere wird so behandelt, als wäre der Intent &#039;&#039;CancelAction&#039;&#039; ausgewählt worden.&lt;br /&gt;
&lt;br /&gt;
=== CancelAction ===&lt;br /&gt;
Siehe &#039;&#039;ConfirmAction&#039;&#039;. Dieser Intent muss nicht zwingend existieren, es kann auch ein unpassender Rückgabewert in &#039;&#039;ConfirmAction&#039;&#039; angegeben werden, um die Abbruch-Routinen für Dialoge zu starten.&lt;br /&gt;
&lt;br /&gt;
=== ChoiceRoom ===&lt;br /&gt;
Siehe &#039;&#039;ConfirmAction&#039;&#039;. Dient im Rahmen von Dialogen der Auswahl eines Raums.&lt;br /&gt;
&lt;br /&gt;
=== ChoiceDevice ===&lt;br /&gt;
Siehe &#039;&#039;ConfirmAction&#039;&#039;. Dient im Rahmen von Dialogen der Auswahl eines Gerätes.&lt;br /&gt;
&lt;br /&gt;
=== ReSpeak ===&lt;br /&gt;
Wiederholt den letzten Satz, den Rhasspy gesprochen hat. Um genauer zu sein: Spricht den Inhalt des FHEM Readings &amp;lt;code&amp;gt;voiceResponse&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Keine Einstellungen in FHEM benötigt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
was hast du gesagt&lt;br /&gt;
kannst du das wiederholen&lt;br /&gt;
ich habe dich nicht verstanden&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:ReSpeak]&lt;br /&gt;
was hast du gesagt&lt;br /&gt;
kannst du das [bitte] wiederholen&lt;br /&gt;
ich habe dich nicht verstanden&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Eigene Intents erstellen ==&lt;br /&gt;
Es ist auch möglich, eigene Intents zu erstellen, sollten die hier vorgestellten nicht reichen. Dafür gibt es zwei Wege: Für kleinere Intents können die Möglichkeiten von FHEMs [[99_myUtils_anlegen|99_myUtils.pm]] genutzt werden. Aufwendigere Intents können in jeweils eigenen Dateien abgelegt werden, die dann von RHASSPY ausgelesen werden.&lt;br /&gt;
=== Intents in 99_myUtils.pm ===&lt;br /&gt;
&lt;br /&gt;
Hier ein (veraltetes, siehe oben) Beispiel, mit dem die letzte &#039;&#039;voice response&#039;&#039; wiederholt werden kann.&lt;br /&gt;
&lt;br /&gt;
Ergänze deine 99_myUtils.pm mit folgender Funktion:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub Respeak(){&lt;br /&gt;
  #Credits to JensS&lt;br /&gt;
  my $name = &amp;quot;Rhasspy&amp;quot;; #Replace &amp;quot;Rhasspy&amp;quot; with the name of your RHASSPY-Device&lt;br /&gt;
  my $response = ReadingsVal($name,&amp;quot;voiceResponse&amp;quot;,&amp;quot;Ich kann mich leider nicht erinnern&amp;quot;);&lt;br /&gt;
  return $response;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ergänze im Attribut &#039;&#039;rhasspyIntents&#039;&#039; folgende Zeile (je Intent muss eine eigene Zeile verwendet werden):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
Respeak=Respeak()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ergänze einen neuen Intent in deinen &#039;&#039;sentence.ini&#039;&#039; an der Rhasspy base:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:Respeak]&lt;br /&gt;
was hast du gesagt&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Intents in eigenen Dateien ===&lt;br /&gt;
Beispiele: https://github.com/fhem/fhem-rhasspy/blob/main/FHEM/99_RHASSPY_Utils_Demo.pm&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: Raumwechsel ====&lt;br /&gt;
Erforderlichen Code in das Modulverzeichnis holen und laden: &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;{ Svn_GetFile(&#039;contrib/RHASSPY/99_RHASSPY_Utils_siteId2room.pm&#039;, &#039;FHEM/99_RHASSPY_Utils_siteId2room.pm&#039;,sub(){ RHASSPY_Utils_siteId2room_Initialize() }) }&amp;lt;/syntaxhighlight&amp;gt;Ergänze im Attribut &#039;&#039;rhasspyIntents&#039;&#039; folgende Zeile (je Intent muss eine eigene Zeile verwendet werden):&lt;br /&gt;
&amp;lt;syntaxhighlight  lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
siteId2room=RHASSPY::siteId2room::siteId2room(NAME,DATA)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Ergänze einen neuen Intent in deinen &#039;&#039;sentence.ini&#039;&#039; an der Rhasspy base:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:siteId2room]&lt;br /&gt;
( Ortswechsel  | begib dich ) ( ins | in den ) $de.fhem.Room{Room}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tipps &amp;amp; Tricks ==&lt;br /&gt;
===Custom Converter für reelle Zahlen===&lt;br /&gt;
{{Randnotiz|RNTyp=Fehl|RNText=Derzeit funktioniert der Konverter aufgrund eines Fehlers in Rhasspy nicht}}&lt;br /&gt;
Rhasspy kann (derzeit) keine gesprochenen reellen Nummern (z.B. 22,5) als Nummer erkennen. Stattdessen interpretiert es die Zahl als zwei Nummern und einen Punkt.&lt;br /&gt;
&lt;br /&gt;
Um reelle Nummern richtig zu verwenden, muss ein [https://rhasspy.readthedocs.io/en/latest/training/#converters Custom Converter] erstellt und in der sentences.ini verwendet werden.&lt;br /&gt;
&lt;br /&gt;
So ein Konverter kann erstellt werden, in dem unter &amp;lt;code&amp;gt;&amp;lt;profile&amp;gt;/converters&amp;lt;/code&amp;gt; ein neues File mit beliebigem Namen angelegt wird. Der Name muss aber dann auch genau so als Converter in der sentences.ini verwendet werden. Anschließend muss die Datei noch ausführbar gemacht werden.&lt;br /&gt;
&lt;br /&gt;
Z.B.:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
touch .config/rhasspy/profile/en/converters/customFloat&lt;br /&gt;
chmod +x .config/rhasspy/profile/en/converters/customFloat&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Folgender Beispiel-Code kann danach in die Datei geschrieben werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python3&lt;br /&gt;
import sys&lt;br /&gt;
import json&lt;br /&gt;
&lt;br /&gt;
# von Rhasspy als JSON übergebene/n Wert/e einlesen&lt;br /&gt;
args = json.load(sys.stdin)&lt;br /&gt;
&lt;br /&gt;
# wenn im deserialisierten JSON nur ein Wert ist, wird der als Ergebnis genommen&lt;br /&gt;
# sind mehrere Werte vorhanden (z.B. 22,.,5), werden die zu einem einzelnen String zusammen gesetzt&lt;br /&gt;
if type(args) == int:&lt;br /&gt;
    num = args&lt;br /&gt;
else:&lt;br /&gt;
    num = &amp;quot;&amp;quot;.join(str(s).strip() for s in args)&lt;br /&gt;
&lt;br /&gt;
# Ergebnis wird an Rhasspy übergeben&lt;br /&gt;
print(num)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nach einem Neustart von Rhasspy kann dieser Converter dann verwendet werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem.SetNumeric]&lt;br /&gt;
stelle die heizung auf (0..30 [komma:. 0..99]){Value!customFloat}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rhasspy speaks actual state of device after switching it===&lt;br /&gt;
JensS wrote a short script to let Rhasspy speak the actual state of a FHEM-device after switching it with a voice-command.&lt;br /&gt;
Add the following to your 99_myUtils.pm&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub ResponseOnOff($){&lt;br /&gt;
  my ($dev) = @_;&lt;br /&gt;
  my $room;&lt;br /&gt;
  my $state = lc(ReadingsVal($dev,&amp;quot;state&amp;quot;,&amp;quot;in unknown state&amp;quot;));&lt;br /&gt;
  my $name = (split(/,/,AttrVal($dev,&amp;quot;rhasspyName&amp;quot;,&amp;quot;error&amp;quot;)))[0];&lt;br /&gt;
  if (AttrVal($dev,&amp;quot;rhasspyRoom&amp;quot;,&amp;quot;&amp;quot;)){$room = &amp;quot; in &amp;quot;.(split(/,/,AttrVal($dev,&amp;quot;rhasspyRoom&amp;quot;,&amp;quot;&amp;quot;)))[0]};&lt;br /&gt;
  $state=~s/.*on/turned on/;&lt;br /&gt;
  $state=~s/.*off/turned off/;&lt;br /&gt;
  return &amp;quot;Ok - &amp;quot;.$name.$room.&amp;quot; is now &amp;quot;.$state&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
and add a response to the SetOnOff-Mapping of a device&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
SetOnOff:cmdOn=on,cmdOff=off,response={ResponseOnOff($DEVICE)}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [https://github.com/rhasspy/rhasspy Rhasspy auf Github]&lt;br /&gt;
* [https://rhasspy.readthedocs.io/en/latest/ offizielle Rhasspy Doku-Seite]&lt;br /&gt;
* [https://community.rhasspy.org/ Offizielles Rhasspy Forum]&lt;br /&gt;
* [https://github.com/fhem/fhem-rhasspy fhem-rhasspy Modul auf GitHub]&lt;br /&gt;
* [https://github.com/Romkabouter/ESP32-Rhasspy-Satellite ESP32-basierte Hardware als Satelliten]&lt;br /&gt;
* [https://github.com/razzo04/rhasspy-mobile-app App für Android-Satelliten]&lt;br /&gt;
* [https://www.youtube.com/watch?v=sWVl0ZoXZEo Video zu sentences.ini]&lt;br /&gt;
[[Kategorie:Sprachsteuerung]]&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=RHASSPY&amp;diff=36937</id>
		<title>RHASSPY</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=RHASSPY&amp;diff=36937"/>
		<updated>2022-01-04T13:08:48Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: /* Custom Converter für reelle Zahlen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Baustelle}}&lt;br /&gt;
Diese Seite beschreibt die Konfiguration und Verwendung des Moduls 10_RHASSPY.pm. &lt;br /&gt;
{{Infobox Modul&lt;br /&gt;
|ModPurpose=Anbindung von FHEM an den Rhasspy Sprachassistenten&lt;br /&gt;
|ModType=contrib&lt;br /&gt;
|ModCmdRef=RHASSPY&lt;br /&gt;
|ModForumArea=Frontends/Sprachsteuerung&lt;br /&gt;
|ModFTopic=119447&lt;br /&gt;
|ModTechName=10_RHASSPY.pm&lt;br /&gt;
|ModOwner=Beta-User ({{Link2FU|9229|Forum}}/[[Benutzer Diskussion:Beta-User|Wiki]]), drhirn ({{Link2FU|15727|Forum}}/[[Benutzer Diskussion:Drhirn|Wiki]])&lt;br /&gt;
}}&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
[https://github.com/rhasspy/rhasspy Rhasspy] ist eine Open Source Server-Lösung für Spracherkennung und Sprachsteuerung, welche auf einem RaspBerry Pi oder einem anderen Debian-basierten Serversystem lauffähig ist. Es handelt sich dabei um eine Sammlung von Programmen (=Skripten in der Python-Sprechweise), die unter einer einheitlichen und sehr  flexiblen Benutzungsoberfläche zusammengefasst sind. Die Besonderheit an Rhasspy ist, dass es nach der Installation komplett offline betrieben werden kann. Es werden also keine Daten an einen Server im Internet geschickt, und für den Betrieb nur für FHEM werden nur moderate Hardwareanforderungen gestellt - ein aktueller Raspberry Pi ab Modell 3B+ sollte in der Regel genügen.&lt;br /&gt;
&lt;br /&gt;
Die Anbindung weiterer Räume ist über sogenannte &amp;quot;Satelliten&amp;quot; möglich. Dies kann z.B. ein Pi Zero mit Mikro und Lautsprecher sein, ein ESP32 mit entsprechender Hardware oder ein Mobiltelefon mit Android und der entsprechenden App.&lt;br /&gt;
&lt;br /&gt;
Rhasspy besteht aus vielen unterschiedlichen Modulen (Hot-Word Erkennung, Text-to-Speech, Speech-to-Text, Intent Erkennung, etc.). Alle diese Module kommunizieren miteinander über das [[MQTT|MQTT]]-Protokoll.&lt;br /&gt;
&lt;br /&gt;
Das Modul [[RHASSPY]] prüft Teile des MQTT-Traffics, konvertiert diese JSON-Nachrichten in FHEM-Befehle und sendet Nachrichten zurück an Rhasspy um z.B. Antworten über Text-to-Speech auszugeben.&lt;br /&gt;
&lt;br /&gt;
RHASSPY verwendet das Modul 00_MQTT2_CLIENT.pm um Nachrichten zu empfangen und zu senden. Daher ist es notwendig, eine Instanz dieses Moduls als FHEM-Device zu erstellen, bevor RHASSPY verwendet werden kann.&lt;br /&gt;
&lt;br /&gt;
Hervorgegangen ist RHASSPY aus dem Snips-Modul, nachdem Snips an Sonos verkauft und anschließend eingestellt wurde. Danke also an Thyraz, der die grundlegenden Arbeiten erledigt hat!&lt;br /&gt;
&lt;br /&gt;
=== Konventionen ===&lt;br /&gt;
{{Hinweis| In diesem Artikel und der CommandRef werden folgende Schreibweisen verwendet:&lt;br /&gt;
* &#039;&#039;&#039;[[RHASSPY]]&#039;&#039;&#039; bezieht sich auf das FHEM-Modul&lt;br /&gt;
* &#039;&#039;&#039;rhasspy&#039;&#039;&#039; bezieht sich auf das das FHEM-Device&lt;br /&gt;
* &#039;&#039;&#039;Rhasspy&#039;&#039;&#039; bezeichnet die (zentrale) Serverinstallation}}&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|Dialoge werden in RHASSPY verwaltet wie [https://rhasspy.readthedocs.io/en/latest/reference/#dialogue-manager hier] beschrieben. Dialoge werden also nicht funktionieren, sobald für das Dialogue-Management etwas anderes als &#039;&#039;RHASSPY&#039;&#039; eingestellt ist}}&lt;br /&gt;
&lt;br /&gt;
=== Erste Schritte ===&lt;br /&gt;
Die Installation und Erstinbetriebnahme von Rhasspy wird in einer Schnellstart-Anleitung erklärt: [[RHASSPY/Schnellstart]] Diese Anleitung sollte auch befolgt werden, wenn man sich sehr gut mit FHEM auskennt. Wer dies erfolgreich absolviert hat, kann gleich zu Abschnitt [[#Set-Befehle_.28SET.29|Set-Befehle (SET)]] weiterspringen, und/oder die [[RHASSPY/Vertiefung|Vertiefung]] durcharbeiten.&lt;br /&gt;
&lt;br /&gt;
=== Details zur Verwaltung des RHASSPY Moduls ===&lt;br /&gt;
Das Modul ist derzeit nicht in der &amp;quot;offiziellen&amp;quot; FHEM Distribution enthalten und muss daher manuell installiert werden. Dafür gibt es zwei Möglichkeiten.&lt;br /&gt;
&lt;br /&gt;
*Im Subversion Repository, kurz SVN von FHEM ist die jeweils aktuelle &amp;quot;stable&amp;quot; Version des Moduls im &#039;&#039;contrib&#039;&#039;-Zweig zu finden. Diese kann mit folgendem Befehl, der im FHEM Befehls-Eingabefeld einzugeben ist, heruntergeladen werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;{ Svn_GetFile(&#039;contrib/RHASSPY/10_RHASSPY.pm&#039;, &#039;FHEM/10_RHASSPY.pm&#039;) }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Genauere Informationen zu dieser Vorgangsweise finden sich unter [[Update#Einzelne_Dateien_aus_dem_SVN_holen]]. Nach Installation des Moduls muss FHEM neu gestartet werden.&lt;br /&gt;
*FHEM Update und GitHub&lt;br /&gt;
Im GitHub-Repository des Moduls gibt es zwei Branches &#039;&#039;main&#039;&#039; und &#039;&#039;dev&#039;&#039;. In &#039;&#039;main&#039;&#039; ist die stabile Version des Moduls, in &#039;&#039;dev&#039;&#039; die jeweils aktuelle Entwicklungsversion. Aus Gründen der Stabilität ist natürlich die aus &#039;&#039;main&#039;&#039; zu bevorzugen.&lt;br /&gt;
&lt;br /&gt;
Um das Modul zu installieren bzw. zu aktualisieren, kann der &#039;&#039;update&#039;&#039;-Mechanismus von FHEM genutzt werden. Dazu muss das Repository in der Liste der vom update-Befehl verarbeiteten Repositorien aufgenommen werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;update add https://raw.githubusercontent.com/fhem/fhem-rhasspy/main/controls_fhem-rhasspy.txt&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Anschließend kann mit folgendem Befehl das Modul installiert oder aktualisiert werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;update all https://raw.githubusercontent.com/fhem/fhem-rhasspy/main/controls_fhem-rhasspy.txt&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wählt man diesen Weg, wird das Modul auch automatisch aktualisiert, wenn ein Update von FHEM durchgeführt wird. Möchte man die Entwicklungsversion verwenden, muss in den beiden Befehlen &#039;&#039;main&#039;&#039; durch &#039;&#039;dev&#039;&#039; ersetzt werden.&lt;br /&gt;
&lt;br /&gt;
Weitere Informationen zu dieser Vorgangsweise in der stehen in der [https://fhem.de/commandref.html#update CommandRef] oder im [[Update|FHEM-Wiki]].&lt;br /&gt;
&lt;br /&gt;
Nach Installation des Moduls muss FHEM neu gestartet werden.&lt;br /&gt;
&lt;br /&gt;
== Einrichtung MQTT2_CLIENT ==&lt;br /&gt;
Rhasspy kommuniziert hauptsächlich über das [[MQTT]]-Protokoll. Und zwar sowohl Rhasspy-intern, wie auch mit FHEM. Da dies auch für die übertragene Sprache und Audio-Dateien gilt und es daher zu sehr viel MQTT-Verkehr kommt, sollte der Rhasspy-interne MQTT-Server verwendet werden. Daher ist die Einrichtung eines [[MQTT2_CLIENT]]-Devices notwendig, um die für FHEM relevanten Daten zu beziehen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zuerst muss ein MQTT2_CLIENT Device erstellt werden, welches sich mit dem MQTT-Server (Mosquitto) von Rhasspy verbindet:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;define &amp;lt;deviceName&amp;gt; MQTT2_CLIENT &amp;lt;ip-oder-hostname-des-mqtt-servers&amp;gt;:&amp;lt;port&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Anschließend wird die &#039;&#039;clientOrder&#039;&#039; gesetzt, um die richtige Benachrichtigungsreihenfolge einzustellen. Wird das MQTT2_CLIENT Device nur für RHASSPY verwendet, reicht hier die Angabe &amp;lt;code&amp;gt;RHASSPY&amp;lt;/code&amp;gt;. Ansonsten müssen noch alle anderen Devices (z.B. &amp;lt;code&amp;gt;MQTT_GENERIC_BRIDGE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;MQTT2_DEVICE&amp;lt;/code&amp;gt;) angegeben werden.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;attr &amp;lt;deviceName&amp;gt; clientOrder RHASSPY [device2] [device3]&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Um die Topics einzuschränken, die das Device abonniert, müssen diese angegeben werden. Wird der MQTT-Server nur für RHASSPY verwendet, reicht die Angabe &amp;lt;code&amp;gt;setByTheProgram&amp;lt;/code&amp;gt;. Ansonsten müssen alle für RHASSPY notwendigen Topics eingefügt werden.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;attr &amp;lt;deviceName&amp;gt; subscriptions setByTheProgram&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
bzw.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;attr &amp;lt;deviceName&amp;gt; subscriptions hermes/intent/+ hermes/dialogueManager/sessionStarted hermes/dialogueManager/sessionEnded hermes/nlu/intentNotRecognized hermes/hotword/+/detected&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Beispiele&lt;br /&gt;
* Rhasspy-interner MQTT-Server wird mit seinem Standard-Port verwendet. Rhasspy läuft auf der selben Maschine wie FHEM. MQTT2_CLIENT wird nur für RHASSPY verwendet.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod rhasspyMQTT2 MQTT2_CLIENT localhost:12183&lt;br /&gt;
attr rhasspyMQTT2 clientOrder RHASSPY&lt;br /&gt;
attr rhasspyMQTT2 subscriptions setByTheProgram&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*Rhasspy läuft auf einem eigenen Server und verwendet einen externen MQTT Server mit eigener Port-Einstellung. MQTT2_CLIENT wird für RHASSPY, aber auch MQTT_GENERIC_BRIDGE und MQTT2_DEVICE verwendet.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
defmod rhasspyMQTT2 MQTT2_CLIENT 192.168.1.122:1884&lt;br /&gt;
attr rhasspyMQTT2 clientOrder RHASSPY MQTT_GENERIC_BRIDGE MQTT2_DEVICE&lt;br /&gt;
attr rhasspyMQTT2 subscriptions hermes/intent/+ hermes/dialogueManager/sessionStarted hermes/dialogueManager/sessionEnded hermes/nlu/intentNotRecognized hermes/hotword/+/detected [zusätzliche Subscriptions für andere MQTT-Module]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Definition von RHASSPY (DEF)==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;define &amp;lt;name&amp;gt; RHASSPY &amp;lt;baseUrl&amp;gt; &amp;lt;devspec&amp;gt; &amp;lt;defaultRoom&amp;gt; &amp;lt;language&amp;gt; &amp;lt;fhemId&amp;gt; &amp;lt;prefix&amp;gt; &amp;lt;useGenericAttrs&amp;gt; &amp;lt;handleHotword&amp;gt; &amp;lt;encoding&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
{{Randnotiz|RNTyp=Info|RNText=RHASSPY verwendet sehr oft &amp;lt;parseParams&amp;gt;. Nicht nur im Define, sondern z.B. auch, um Attribut-Werte auszuwerten. Es sollten also alle Parameter im Define in der Form key=value angegeben werden.).}}{{Randnotiz|RNTyp=Info|RNText=RHASSPY führt jede Menge Daten aus unterschiedlichen Quellen zusammen um seine Funktion erfüllen zu können. Die endgültige Daten-Struktur, die RHASSPY verwendet, kann mittels des [[List|list]]-Kommandos angezeigt werden. Es wird empfohlen, sich diese Daten-Struktur auf jeden Fall anzusehen. Vor allem dann, wenn etwas nicht wie gewünscht funktioniert.}}&lt;br /&gt;
Alle Parameter sind &#039;&#039;&#039;optional&#039;&#039;&#039;. Die meisten werden im Normalfall gar nicht benötigt (z.B. &amp;lt;code&amp;gt;fhemId&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;prefix&amp;lt;/code&amp;gt;). Sollten sie aber verwendet und später geändert werden, kann es zu unvorhergesehenem Verhalten kommen. Speziell beim Einstieg in das Thema RHASSPY sollten nicht mehr, als die ersten drei verwendet werden. Ausgenommen eventuell noch &amp;lt;code&amp;gt;language&amp;lt;/code&amp;gt;, möchte man eine andere Sprache als Englisch oder Deutsch verwenden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;def-baseurl&amp;quot;&amp;gt;baseUrl&amp;lt;/code&amp;gt;&lt;br /&gt;
:Die URL zum Rhasspy-Webservice. Sollten eine Base und mehrere Satelliten verwendet werden, die URL zur Base. Bitte sicherstellen, dass die Adresse richtig ist (IP und Port)! Default ist &amp;lt;code&amp;gt;baseUrl=http://127.0.0.1:12101&amp;lt;/code&amp;gt;.&lt;br /&gt;
;&amp;lt;code id=&amp;quot;def-devspec&amp;quot;&amp;gt;devspec&amp;lt;/code&amp;gt;&lt;br /&gt;
:devspec der Geräte, die mit Rhasspy gesteuert werden sollen. Wenn der &#039;&#039;genericDeviceType&#039;&#039;-Support aktiviert ist, ist der Default &amp;lt;code&amp;gt;devspec=genericDeviceType=.+&amp;lt;/code&amp;gt;, sonst wird &amp;lt;code&amp;gt;devspec=room=Rhasspy&amp;lt;/code&amp;gt; verwendet. Ohne ein passendes Match in der devspec wird kein Gerät mit dem Modul interagieren, egal, ob sonst irgendwelche RHASSPY-spezifischen Attribute beim Gerät gesetzt sind. Genauere Informationen, wie z.B. eine Liste von Geräten oder Kombinationen aus Geräten und Räumen (z.B. &amp;lt;code&amp;gt;devspec=room=livingroom,room=bathroom,bedroomlamp&amp;lt;/code&amp;gt;) verwendet werden können, finden sich in der [https://commandref.fhem.de/commandref.html#devspec CommandRef].&lt;br /&gt;
;&amp;lt;code id=&amp;quot;def-defaultroom&amp;quot;&amp;gt;defaultRoom&amp;lt;/code&amp;gt;&lt;br /&gt;
:Der Name des Standard-Raumes, der verwendet wird, wenn im Sprachkommando kein Raum enthalten ist und auch kein passender für das Device gefunden werden kann. Default ist &amp;lt;code&amp;gt;defaultRoom=default&amp;lt;/code&amp;gt;.&lt;br /&gt;
;&amp;lt;code id=&amp;quot;def-language&amp;quot;&amp;gt;language&amp;lt;/code&amp;gt;&lt;br /&gt;
:Sprache, in der mit Rhasspy gesprochen wird. Der Standard-Wert hängt vom &#039;&#039;global&#039;&#039;-Device ab. Dieser ist standardmäßig &amp;lt;code&amp;gt;language=en&amp;lt;/code&amp;gt;.&lt;br /&gt;
;&amp;lt;code id=&amp;quot;def-fhemid&amp;quot;&amp;gt;fhemId&amp;lt;/code&amp;gt;&lt;br /&gt;
:Wird verwendet um auf MQTT-Seite zwischen mehreren Installationen des RHASSPY-Moduls zu unterscheiden. Ist auch ein Teil des Topic-Trees, auf den die jeweilige RHASSPY-Instanz hört. Default ist &amp;lt;code&amp;gt;fhemId=fhem&amp;lt;/code&amp;gt;.&lt;br /&gt;
;&amp;lt;code id=&amp;quot;def-prefix&amp;quot;&amp;gt;prefix&amp;lt;/code&amp;gt;&lt;br /&gt;
:Wird verwendet um auf FHEM-Seite zwischen mehreren Installationen des RHASSPY-Moduls zu unterscheiden. Praktisch, wenn man mehrere Instanzen von RHASSPY auf einer FHEM Installation laufen hat und z.B. verschiedene Bezeichner für Gruppen und Räume haben möchte (z.B. unterschiedliche Sprachen). Default ist &amp;lt;code&amp;gt;prefix=rhasspy&amp;lt;/code&amp;gt;.&lt;br /&gt;
;&amp;lt;code id=&amp;quot;def-usegenericattrs&amp;quot;&amp;gt;&#039;&#039;&#039;useGenericAttrs&#039;&#039;&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
:Üblicherweise verwendet RHASSPY - wie auch einige andere FHEM Module für Sprachassistenten - das Attribut &#039;&#039;genericDeviceType&#039;&#039; um Schaltmöglichkeiten von Geräten automatisch zu erkennen. Dieser Parameter fügt das Attribut &#039;&#039;genericDeviceType&#039;&#039; zur globalen Attributliste hinzu. Der Wert 0 verhindert dieses hinzufügen. Default ist &amp;lt;code&amp;gt;useGenericAttrs=1&amp;lt;/code&amp;gt;.&lt;br /&gt;
;&amp;lt;code id=&amp;quot;def-encoding&amp;quot;&amp;gt;encoding&amp;lt;/code&amp;gt;&lt;br /&gt;
:Sollte es Probleme mit Umlauten geben, kann das Character-Encoding geändert werden. Default ist &amp;lt;code&amp;gt;encoding=utf8&amp;lt;/code&amp;gt;.&lt;br /&gt;
;&amp;lt;code id=&amp;quot;handlehotword&amp;quot;&amp;gt;handleHotword&amp;lt;/code&amp;gt;&lt;br /&gt;
:Triggert das Reading &#039;&#039;hotword&#039;&#039;, wenn ein Hotword erkannt wurde (und erstellt das Reading, falls noch nicht vorhanden). Weitere Informationen dazu stehen beim Attribut [[#attr-rhasspyhotwords|&#039;&#039;rhasspyHotwords&#039;&#039;]]. Default ist &amp;lt;code&amp;gt;handleHotword=0&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|Nach dem Definieren eines RHASSPY-Modules sollte das IODev manuell gesetzt werden um ein automatische IO-Zuweisung zu verhindern. Z.B. &amp;lt;code&amp;gt;attr &amp;lt;deviceName&amp;gt; IODev &amp;lt;m2client&amp;gt;&amp;lt;/code&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
;Beispiele:&lt;br /&gt;
Läuft Rhasspy auf der selben Maschine wie FHEM, die Sprache ist im &#039;&#039;global&#039;&#039;-Device bereits richtig eingestellt und der Standardraum entspricht der siteID, die in Rhasspy vergeben wurde:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;define Rhasspy RHASSPY&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Läuft Rhasspy auf einem anderen System wie FHEM, der Standard-Raum enspricht nicht dem, was Rhasspy liefert, die Sprache soll auch anders sein und es sollen sowohl Geräte mit vorhandenem &#039;&#039;genericDeviceType&#039;&#039; Attribut, als auch die Geräte &#039;&#039;device_a1&#039;&#039; und &#039;&#039;device_xy&#039;&#039; gesteuert werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;define Rhasspy RHASSPY baseUrl=http://192.168.1.210:12101 defaultRoom=&amp;quot;Büro Lisa&amp;quot; language=de devspec=genericDeviceType=.+,device_a1,device_xy handleHotword=1&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Set-Befehle (SET)==&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;set-customslot&amp;quot;&amp;gt;customSlot&amp;lt;/code&amp;gt;&lt;br /&gt;
:Erstellt einen neue - oder überschreibt einen alten - Slot in Rhasspy&lt;br /&gt;
:&amp;lt;code&amp;gt;slotname&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;slotdata&amp;lt;/code&amp;gt; sind verpflichtend&lt;br /&gt;
:&amp;lt;code&amp;gt;overwrite&amp;lt;/code&amp;gt; ist optional. Default ist &amp;lt;code&amp;gt;overwrite=true&amp;lt;/code&amp;gt;. Das Setzen eines anderes Wertes verhindert das Überschreiben einen bereits bestehenden Slot mit gleichem Namen.&lt;br /&gt;
:&amp;lt;code&amp;gt;training&amp;lt;/code&amp;gt; ist optional. Default ist &amp;lt;code&amp;gt;training=true&amp;lt;/code&amp;gt;. Das Setzen eines anderen Wertes verhindert ein Training von Rhasspy nach dem Speichern des Slots.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Beispiele:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; customSlot mySlot a,b,c overwrite training&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; customSlot slotname=mySlot slotdata=a,b,c overwrite=false&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;set-fetchsiteids&amp;quot;&amp;gt;fetchSiteIds&amp;lt;/code&amp;gt;&lt;br /&gt;
:Liest alle in Rhasspy vorhandenen siteIDs aus und speichert sie im Reading &#039;&#039;siteIds&#039;&#039;. Wird z.B. verwendet, um festzustellen, auf welchem Satelliten der User über das Ende eines Timers benachrichtigt werden soll.&lt;br /&gt;
:Muss immer ausgeführt werden, wenn eine neue siteId in Rhasspy hinzugefügt wird (neuer Satellit z.B.).&lt;br /&gt;
:&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; fetchSiteIds&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;set-play&amp;quot;&amp;gt;play&amp;lt;/code&amp;gt;&lt;br /&gt;
:Sendet eine WAV Datei an Rhasspy.&lt;br /&gt;
:&amp;lt;code&amp;gt;siteId&amp;lt;/code&amp;gt; und &amp;lt;path&amp;gt; sind verpflichtend!&lt;br /&gt;
:Optional kann die Anzahl der Wiederholungen (Default: 1) und die Dauer der Pause zwischen den jeweiligen Wiederholungen (Default: 15) angeben werden.&lt;br /&gt;
:&#039;&#039;Beispiele:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; play siteId=&amp;quot;default&amp;quot; path=&amp;quot;/opt/fhem/test.wav&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; play siteId=&amp;quot;default&amp;quot; path=&amp;quot;./test.wav&amp;quot; repeats=3 wait=20&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;set-speak&amp;quot;&amp;gt;speak&amp;lt;/code&amp;gt;&lt;br /&gt;
:Sendet einen Text an das TTS-Sytem, welches ihn dann als Sprache ausgibt.&lt;br /&gt;
:Beide Argumente &amp;lt;code&amp;gt;siteId&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;text&amp;lt;/code&amp;gt; sind verpflichtend!&lt;br /&gt;
:&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; speak siteId=&amp;quot;wohnzimmer&amp;quot; text=&amp;quot;This is a test&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;set-textcommand&amp;quot;&amp;gt;textCommand&amp;lt;/code&amp;gt;&lt;br /&gt;
:Sendet ein Text-Kommando an Rhasspy.&lt;br /&gt;
:&#039;&#039;&#039;Example:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; textCommand schalte das licht ein&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;set-trainrhasspy&amp;quot;&amp;gt;trainRhasspy&amp;lt;/code&amp;gt;&lt;br /&gt;
:Startet das Training von Rhasspy.&lt;br /&gt;
:&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; trainRhasspy&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;set-update&amp;quot;&amp;gt;update&amp;lt;/code&amp;gt;&lt;br /&gt;
:;&amp;lt;code id=&amp;quot;set-update-devicemap&amp;quot;&amp;gt;devicemap&amp;lt;/code&amp;gt;&lt;br /&gt;
::Wenn an der Konfiguration von RHASSPY oder an den von ihm gesteuerten Geräten etwas geändert wurde, muss dieser Befehl ausgeführt werden, um die Datenstruktur von RHASSPY zu aktualisieren, Rhasspy von den Änderungen zu informieren (Slots z.B.), ein Training zu starten, etc.&lt;br /&gt;
::&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update devicemap&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:;&amp;lt;code id=&amp;quot;set-update-devicemaponly&amp;quot;&amp;gt;devicemap_only&amp;lt;/code&amp;gt;&lt;br /&gt;
::Aktualisiert die Datenstruktur von RHASSPY. Es werden weder Slots in Rhasspy geändert, noch das Training gestartet.&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update devicemap_only&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:;&amp;lt;code id=&amp;quot;set-update-slots&amp;quot;&amp;gt;slots&amp;lt;/code&amp;gt;&lt;br /&gt;
::Aktualisiert (bzw. erstellt) alle Slots in Rhasspy mit den aktuellen Geräten, Räumen, usw.&lt;br /&gt;
::Erstellte/Aktualisierte Slots sind z.B.:&lt;br /&gt;
::*de.fhem.AllKeywords&lt;br /&gt;
::*de.fhem.Device&lt;br /&gt;
::*de.fhem.Device-&#039;&#039;genericDeviceType&#039;&#039;&lt;br /&gt;
::*de.fhem.Device-&#039;&#039;Intent&#039;&#039;&lt;br /&gt;
::*de.fhem.Group&lt;br /&gt;
::*de.fhem.Room&lt;br /&gt;
::*de.fhem.MediaChannels&lt;br /&gt;
::*de.fhem.Color&lt;br /&gt;
::*de.fhem.NumericType&lt;br /&gt;
::(Hinweis: Die ersten beiden Teile &#039;&#039;de&#039;&#039; und &#039;&#039;fhem&#039;&#039; hängen von der DEF des RHASSPY-Devices ab)&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update slots&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:;&amp;lt;code id=&amp;quot;set-update-slotsnotraining&amp;quot;&amp;gt;slots_no_training&amp;lt;/code&amp;gt;&lt;br /&gt;
::Wie &amp;lt;code&amp;gt;slots&amp;lt;/code&amp;gt;, aber ohne Training nach dem Update.&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update slots_no_training&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:;&amp;lt;code id=&amp;quot;set-update-language&amp;quot;&amp;gt;language&amp;lt;/code&amp;gt;&lt;br /&gt;
::Liest das das Sprach-File (&#039;&#039;languageFile&#039;&#039;) neu ein.&lt;br /&gt;
::Muss immer ausgeführt werden, wenn in diesem File oder dem Attribut &#039;&#039;languageFile&#039;&#039; etwas geändert wurde!&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update language&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:;&amp;lt;code id=&amp;quot;set-udpate-intentfilter&amp;quot;&amp;gt;intent_filter&amp;lt;/code&amp;gt;&lt;br /&gt;
::Setzt die Intent Filter, die vom Rhasspy Dialogue Manger verwendet werden zurück. Details dazu bei [[#attr-rhasspytweaks-intentfilter|intentFilter]] im &#039;&#039;rhasspyTweaks&#039;&#039;-Attribut.&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update intent_filter&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:;&amp;lt;code id=&amp;quot;set-update-all&amp;quot;&amp;gt;all&amp;lt;/code&amp;gt;&lt;br /&gt;
::Aktualisiert die Devicemap und das languageFile&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; update all&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;set-volume&amp;quot;&amp;gt;volume&amp;lt;/code&amp;gt;&lt;br /&gt;
::Stellt die Lautstärke der gewünschten siteId auf einen Wert zwischen 0 and 1 (float).&lt;br /&gt;
::Beide Argumente &amp;lt;code&amp;gt;siteId&amp;lt;/code&amp;gt; &amp;lt;code&amp;gt;volume&amp;lt;/code&amp;gt; sind verpflichtend.&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;set &amp;lt;rhasspyDevice&amp;gt; siteId=&amp;quot;default&amp;quot; volume=&amp;quot;0.5&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Hinweis|Bitte nicht vergessen, dass nach jeder Änderung an RHASSPY oder an einem von RHASSPY gesteuerten Gerät ein &amp;lt;code&amp;gt;update devicemap&amp;lt;/code&amp;gt; ausgeführt werden muss!}}&lt;br /&gt;
&lt;br /&gt;
==Attribute (ATTR)==&lt;br /&gt;
Um RHASSPY zum Laufen zu bringen, müssen unterschiedliche Attribute gesetzt werden. Dabei gibt es&lt;br /&gt;
*Attribute, die im RHASSPY-Device selbst gesetzt werden müssen und&lt;br /&gt;
*Attribute, die in den Devices gesetzt werden müssen, die von RHASSPY kontrolliert werden sollen.&lt;br /&gt;
&lt;br /&gt;
Letztere werden im Abschnitt [[#FHEM-Devices für die Verwendung mit Rhasspy konfigurieren|FHEM-Devices für die Verwendung mit Rhasspy konfigurieren]] behandelt.&lt;br /&gt;
&lt;br /&gt;
In diesem Abschnitt werden die Attribute behandelt, die auf das RHASSPY-Device selbst wirken.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;attr-iodev&amp;quot;&amp;gt;IODev&amp;lt;/code&amp;gt;&lt;br /&gt;
:Das MQTT2_CLIENT Device, welches die MQTT-Nachrichten für RHASSPY liefert.&lt;br /&gt;
:&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;attr &amp;lt;rhasspyDevice&amp;gt; IODev rhasspyMQTT2&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;attr-forcenext&amp;quot;&amp;gt;forceNext&amp;lt;/code&amp;gt;&lt;br /&gt;
:Wenn dieses Attribut auf 1 gesetzt ist, leitet RHASSPY eingehende MQTT-Nachrichten an andere MQTT2-IO-Client Module wie MQTT2_DEVICE weiter, auch wenn das Topic zu einem von RHASSPY abonnierten passt.&lt;br /&gt;
:Standardmäßig werden diese Nachrichten nicht weitergeleitet um eine bessere Kompatibilität mit dem &#039;&#039;autocreate&#039;&#039;-Feature des MQTT2_DEVICE sicher zu stellen.&lt;br /&gt;
:Siehe dazu das {{Link2CmdRef|Anker=MQTT2_CLIENT-attr-clientOrder|Lang=en|Label=clientOrder}}-Attribut in der CommandRef zum MQTT2_CLIENT Device.&lt;br /&gt;
:Das Setzen dieses Attributs in einer RHASSPY-Instanz kann auch andere eventuell vorhandene RHASSPY-Instanzen beinflussen.&lt;br /&gt;
:Default ist &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;attr &amp;lt;rhasspyDevice&amp;gt; forceNext 1&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;attr-languagefile&amp;quot;&amp;gt;languageFile&amp;lt;/code&amp;gt;&lt;br /&gt;
:Pfad zur Sprach-Datei&lt;br /&gt;
:Ist dieses Argument nicht gesetzt, wird ein Standard-Set an englischen Sätzen für die Sprachantworten verwendet.&lt;br /&gt;
:Die Datei selbst muss ein gültiges JSON-File sein, dass sich nach der Struktur aus den englischen Standardwerten richtet.&lt;br /&gt;
:Eine deutsche Beispiel-Datei ist in [https://svn.fhem.de/trac/browser/trunk/fhem/contrib/RHASSPY/rhasspy-de.cfg SVN] und [https://github.com/fhem/fhem-rhasspy/blob/dev/FHEM/rhasspy-de.cfg GitHub] vorhanden. Man kann aber einfach ein Dump der englischen Struktur machen (replace RHASSPY by your device&#039;s name: &amp;lt;code&amp;gt;{toJSON($defs{RHASSPY}-&amp;gt;{helper}{lng})}&amp;lt;/code&amp;gt;, das Ergebnis dann bearbeiten und es als eigenes languageFile verwenden.&lt;br /&gt;
:Im Standard-Set sind auch einige Variablen enthalten. Auch die können im eigenen File verwendet werden.&lt;br /&gt;
:languageFile erlaubt auch eine Kombination aus vorhandenen und eigenen Sätzen. Dazu können die eigenen Sätzen einfach im Sub-Tree &#039;&#039;user&#039;&#039; abgelegt werden.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Beispiel:&#039;&#039;&#039; (vorausgesetzt, die Sprach-Datei ist im selben Verzeichnis wie fhem.pl):&lt;br /&gt;
:&amp;lt;code&amp;gt;attr &amp;lt;rhasspyDevice&amp;gt; languageFile ./rhasspy-de.cfg&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;attr-response&amp;quot;&amp;gt;response&amp;lt;/code&amp;gt;&lt;br /&gt;
:&#039;&#039;&#039;Hinweis:&#039;&#039;&#039;: Die Verwendung dieses Attributs ist nicht mehr empfohlen. Bessere Alternative ist die Sprach-Datei.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Mit diesem Attribut können eigene Standardantworten definiert werden.&lt;br /&gt;
Mögliche Schlüsselwörter sind &amp;lt;code&amp;gt;DefaultError&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;NoActiveMediaDevice&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;DefaultConfirmation&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;DefaultError=&lt;br /&gt;
DefaultConfirmation=Klaro, mach ich&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;attr-rhasspyhotwords&amp;quot;&amp;gt;rhasspyHotwords&amp;lt;/code&amp;gt;&lt;br /&gt;
:Kann verwendet werden, um benutzerdefinierte Aktionen auszuführen, sobald ein bestimmtes Hotword erkannt wurde. Dazu sind keine speziellen Konfigurationsschritte in anderen FHEM Devices notwendig.&lt;br /&gt;
:Wenn mittels Attribut oder DEF aktiviert, wird ein Reading &#039;&#039;hotword&#039;&#039; erstellt und mit dem erkannten Hotword und der siteId befüllt um ein Event-Handling zu ermöglichen.&lt;br /&gt;
:&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Da bei den hotword messages für alle Teilnehmer dieselbe Topic-Structur verwendet wird, kann RHASSPY nicht unterscheiden, ob eine solche für diese Instanz relevant ist. Falls entsprechende Unterscheidungen gemacht werden sollen, muss dies vom User entsprechend konfiguriert werden, z.B. indem die subscriptions (am MQTT2_CLIENT) eingeschränkt werden oder indem nur jeweils andere hotword-Einträge für jede RHASSPY-Instanz genutzt werden.&lt;br /&gt;
:Ein Hotword pro Zeile, Syntax entweder einfach oder erweitert&lt;br /&gt;
 &lt;br /&gt;
:&#039;&#039;&#039;Beispiele:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;bumblebee_linux = set amplifier2 mute on&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;porcupine_linux = livingroom=&amp;quot;set amplifier mute on&amp;quot; default={Log3($DEVICE,3,&amp;quot;device $DEVICE - room $ROOM - value $VALUE&amp;quot;)}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Im ersten Beispiel wird der Befehl immer ausgeführt, wenn das Hotword &#039;&#039;bumblebee_linux&#039;&#039; erkannt wurde.&lt;br /&gt;
:Im zweiten nur, wenn das Hotword &#039;&#039;porcupine_linux&#039;&#039; in der siteId &#039;&#039;livingroom&#039;&#039; erkannt wurde.&lt;br /&gt;
:$DEVICE wird ausgewertet als der Name des RHASSPY Devices, $ROOM als siteId und $VALUE als das verwendete Hotword.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;attr-rhasspyintents&amp;quot;&amp;gt;rhasspyIntents&amp;lt;/code&amp;gt;&lt;br /&gt;
:Definiert einen benutzerdefinierten Intent.&lt;br /&gt;
:Ein Intent pro Zeile.&lt;br /&gt;
:&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;attr &amp;lt;rhasspyDevice&amp;gt; rhasspyIntents SetCustomIntentsTest=SetCustomIntentsTest(siteId,Type)&amp;lt;/code&amp;gt;&lt;br /&gt;
:in Kombination mit folgendem myUtils-Code&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub SetCustomIntentsTest {&lt;br /&gt;
my $room = shift;&lt;br /&gt;
my $type = shift;&lt;br /&gt;
Log3(&#039;rhasspy&#039;,3 , &amp;quot;RHASSPY: Room $room, Type $type&amp;quot;);&lt;br /&gt;
return &amp;quot;RHASSPY: Room $room, Type $type&amp;quot;;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
:schreibt einen Log-Eintrag nach jedem Aufruf dieses Intents.&lt;br /&gt;
:Die folgenden Argumente können dabei übergeben werden:&lt;br /&gt;
:*NAME =&amp;gt; Name des RHASSPY-Devices&lt;br /&gt;
:*DATA =&amp;gt; komplette JSON-$data (wie intern geparsed), in JSON kodiert&lt;br /&gt;
:*siteId, Device etc. =&amp;gt; jedes Element, das in JSON-$data existiert&lt;br /&gt;
:Wird von der Funktion ein einfacher Text zurück geliefert, wird dieser als &#039;&#039;response&#039;&#039; angesehen. Wenn der Rückgabewert nicht definiert ist, wird die Standard-&#039;&#039;response&#039;&#039; verwendet.&lt;br /&gt;
:Es kann aber auch ein HASH oder ARRAY übergeben werden.&lt;br /&gt;
:Im Falle eines ARRAYs wird das erste Element als &#039;&#039;response&#039;&#039; interpretiert und kann ein reiner Text sein, womit der Dialog beendet wird. Ist das erste Element ein HASH wird die Dialog-Session fortgesetzt. Eine offene Dialog-Session wird per Default nach 20 Sekunden beendet. Diese Zeitspanne kann aber auch geändert werden, in dem im ARRAY als zweiter Wert eine Zahl übergeben wird. Das zweite Element kann aber auch eine komma-getrennte Liste an Geräten sein, die geändert (geschalten) wurden. Das dient dazu, damit die Geräte auch Events liefern, was ansonsten nicht der Fall wäre. Siehe dazu den &amp;quot;d&amp;quot;-Parameter beim Attribut [[#attr-rhasspyshortcuts|rhasspyShortcuts]].&lt;br /&gt;
:Wird eine HASH-Datenstruktur (ggf. in $response innerhalb einer ARRAY-Struktur), um einen laufenden Dialog fortzusetzen, muss sichergestellt werden, dass alle erforderlichen Datenelemente enthalten sind, insbesondere &#039;&#039;intentFilter&#039;&#039;, falls die für den weiteren Dialog relevanten Intents eingeschränkt (oder erweitert) werden sollen. Dabei sollte möglichst der Intent &#039;&#039;CancelAction&#039;&#039; aktiv gehalten werden, damit der User die Option hat, den Dialog jederzeit aktiv zu beenden.&lt;br /&gt;
:Siehe dazu auch den Abschnitt [[#Eigene Intents erstellen]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;attr-rhasspyshortcuts&amp;quot;&amp;gt;rhasspyShortcuts&amp;lt;/code&amp;gt;&lt;br /&gt;
:Hiermit können benutzerdefinierte Sätze erstellt werden ohne die sentences.ini in Rhasspy bearbeiten zu müssen.&lt;br /&gt;
:Diese Shortcuts werden zu Rhasspy hochgeladen, sobald das &amp;lt;code&amp;gt;updateSlots&amp;lt;/code&amp;gt; [[#set-update|Set]]-Kommando ausgeführt wird.&lt;br /&gt;
:Ein Shortcut pro Zeile, Syntax ist entweder einfach oder erweitert.&lt;br /&gt;
:&#039;&#039;&#039;Beispiele:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;code&amp;gt;mute on=set amplifier2 mute on&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;lamp off={fhem(&amp;quot;set lampe1 off&amp;quot;)}&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;i=&amp;quot;du bist cool&amp;quot; f=&amp;quot;set $NAME speak siteId=&#039;livingroom&#039; text=&#039;danke dir! du bist noch viel cooler!&#039;&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;i=&amp;quot;schalte den ton aus&amp;quot; p={fhem (&amp;quot;set $NAME mute off&amp;quot;)} n=amplifier2 c=&amp;quot;soll ich den ton wirklich ausschalten?&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
:&amp;lt;code&amp;gt;i=&amp;quot;ich hab hunger&amp;quot; f=&amp;quot;set Herd on&amp;quot; d=&amp;quot;Herd&amp;quot; c=&amp;quot;möchtest du schweinsbraten?&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
:Erklärung zu den Abkürzungen:&lt;br /&gt;
:*&amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt; =&amp;gt; intent&lt;br /&gt;
::Zeilen, die mit &amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt; beginnen, werden als erweiterte Syntax interpretiert. Soll die erweiterte Syntax verwendet werden, ist das &amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt; also Pflicht!&lt;br /&gt;
:*&amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt; =&amp;gt; FHEM Befehl&lt;br /&gt;
::Syntax wie von der FHEM Kommandozeile gewohnt&lt;br /&gt;
:*&amp;lt;code&amp;gt;p&amp;lt;/code&amp;gt; =&amp;gt; Perl Befehl&lt;br /&gt;
::Syntax wie von der FHEM Kommandozeile gewohnt, eingerahmt in geschwungenen Klammern (&amp;lt;code&amp;gt;{}&amp;lt;/code&amp;gt;). &amp;lt;code&amp;gt;p&amp;lt;/code&amp;gt; hat Vorrang vor &amp;lt;code&amp;gt;f&amp;lt;/code&amp;gt;&lt;br /&gt;
:*&amp;lt;code&amp;gt;d&amp;lt;/code&amp;gt; =&amp;gt; Device Name(en, Komma getrennt)&lt;br /&gt;
::Device Name(n), die an fhem.pl als upgedated übergeben werden sollen. Das wird benötigt um weitere Aktionen in FHEM und das Longpolling zu triggern.&lt;br /&gt;
::Hinweis: Wenn Perl-Funktionen aufgerufen werden, wird der Rückgabewert dieser Funktion verwendet, sofern kein explizites Device angegeben ist.&lt;br /&gt;
:*&amp;lt;code&amp;gt;r&amp;lt;/code&amp;gt; =&amp;gt; Response&lt;br /&gt;
::Sprachanwort, die ausgegeben wird. Ist &amp;lt;code&amp;gt;r&amp;lt;/code&amp;gt; nicht gesetzt, wird der Rückgabewert der aufgerufenen Funktion verwendet.&lt;br /&gt;
::In den Antwortsätze werden &#039;&#039;set magic&#039;&#039;-ähnliche Ersetzungen verarbeitet. Es ist also auch eine Zeile wie &amp;lt;code&amp;gt;i=&amp;quot;what&#039;s the time for sunrise&amp;quot; r=&amp;quot;at [Astro:SunRise] o&#039;clock&amp;quot;&amp;lt;/code&amp;gt; gültig.&lt;br /&gt;
::Mit den folgenden Abkürzungen kann auch nach einer Bestätigung für den Befehl gefragt werden:&lt;br /&gt;
::*&amp;lt;code&amp;gt;c&amp;lt;/code&amp;gt; =&amp;gt; Entweder Zahl oder Text. Wenn Zahl, wird sie als Timeout für den Abbruch des Dialogs behandelt. Wenn Text wird dieser als Sprachausgabe zur Bestätigung verwendet.&lt;br /&gt;
::*&amp;lt;code&amp;gt;ct&amp;lt;/code&amp;gt; =&amp;gt; Numerischer Wert für das Timeout des Dialogs in Sekunden. Default ist &amp;lt;code&amp;gt;15&amp;lt;/code&amp;gt;.&lt;br /&gt;
::Siehe [[#attr-rhasspytweaks-confirmintents|hier]] für weitere Informationen zu Bestätigungen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;code id=&amp;quot;attr-rhasspytweaks&amp;quot;&amp;gt;rhasspyTweaks&amp;lt;/code&amp;gt;&lt;br /&gt;
Mit diesen Einstellungen können benutzerdefinierte Optimierungen an RHASSPY vorgenommen werden.&lt;br /&gt;
&lt;br /&gt;
:*&amp;lt;code id=&amp;quot;attr-rhasspytweaks-timerlimits&amp;quot;&amp;gt;timerLimits&amp;lt;/code&amp;gt;&lt;br /&gt;
::Wird verwendet um den Timer anzuweisen mit z.B. &amp;quot;gestellt auf 30 Minuten&amp;quot; oder &amp;quot;gestellt auf 10:30&amp;quot; zu antworten&lt;br /&gt;
::&amp;lt;code&amp;gt;timerLimits=90,300,3000,2*HOURSECONDS,50&amp;lt;/code&amp;gt;&lt;br /&gt;
::Hierbei müssen fünf Werte gesetzt werden, die den Zeitgrenzen für Stufen in der Antwortstruktur &#039;&#039;timerSet&#039;&#039; entsprechen.&lt;br /&gt;
::Obiges Beispiel also würde dazu führen, unter einer eingestellten Zeit von 90 Sekunden mit der Sekundenangabe geantwortet wird. In Minuten und Sekunden solange der Timer kürzer als 300 Sekunden ist. Usw. Der letzte Wert ist das Limit in Sekunden, wenn der Timer im &amp;quot;Uhrzeit&amp;quot;-Format gestellt ist.&lt;br /&gt;
&lt;br /&gt;
:*&amp;lt;code id=&amp;quot;attr-rhasspytweaks-timersounds&amp;quot;&amp;gt;timerSounds&amp;lt;/code&amp;gt;&lt;br /&gt;
::Standardmäßig antwortet der Timer mit einer Sprachnachricht, wenn er abgelaufen ist. Soll lieber eine WAV-Datei verwendet werden, kann das hier eingestellt werden.&lt;br /&gt;
::&amp;lt;code&amp;gt;timerSounds= default=./yourfile1.wav eier=3:20:./yourfile2.wav kartoffeln=5:./yourfile3.wav&amp;lt;/code&amp;gt;&lt;br /&gt;
::Die Keys in dieser Code-Zeile sind Beispiele und deren Name - bis auf &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; frei wählbar. Der Name muss aber zu den &#039;&#039;Label&#039;&#039;-Tags für die Timer in den Rhasspy-Sentences passen.&lt;br /&gt;
::&amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; ist optional. Wenn gesetzt, wird dieses WAV-File für alle benannten Timer verwendet, für die kein Keyword in der Konfiguration ist.&lt;br /&gt;
::Die beiden Nummern sind optional. Die erste legt fest, wie oft die WAV-Datei wiederholt werden soll (Default: 5). Die zweite definiert die Pause in Sekunden zwischen den Wiederholungen (Default: 15). Ist nur eine Zahl gesetzt, wird diese als gewünschte Anzahl an Wiederholungen interpretiert.&lt;br /&gt;
&lt;br /&gt;
:*&amp;lt;code id=&amp;quot;attr-rhasspytweaks-updateslots&amp;quot;&amp;gt;updateSlots&amp;lt;/code&amp;gt;&lt;br /&gt;
::Ändert diverse Aspekte des Erstellens und Updatens von Slots&lt;br /&gt;
::*&amp;lt;code&amp;gt;noEmptySlots=1&amp;lt;/code&amp;gt;&lt;br /&gt;
:::Per Default generiert RHASSPY einen zusätzlichen Slot für jeden &#039;&#039;genericDeviceType&#039;&#039;, der erkannt wird. Unabhängig davon, ob er bei einem Gerät gesetzt ist. Das kann zu leeren Slots führen.&lt;br /&gt;
:::Ist der Wert &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;, werden keine leeren Slots erstellt.&lt;br /&gt;
::*&amp;lt;code&amp;gt;overwrite_all=false&amp;lt;/code&amp;gt;&lt;br /&gt;
:::RHASSPY überschreibt alle vorhandenen Slots wenn ein &amp;lt;code&amp;gt;updateSlots&amp;lt;/code&amp;gt; ausgeführt wird. Ist das nicht gewünscht, muss dieser Wert auf &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; gesetzt werden.&lt;br /&gt;
::*&amp;lt;code&amp;gt;timeouts&amp;lt;/code&amp;gt;&lt;br /&gt;
:::Die Keywörter &amp;lt;code&amp;gt;confirm&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; können verwendet werden, um das Standard-Timeouts (15s/20s) für Dialoge zu ändern.&lt;br /&gt;
:::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:::&amp;lt;code&amp;gt;timeouts: confirm=25 default=30&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:*&amp;lt;code id=&amp;quot;attr-rhasspytweaks-confirmintents&amp;quot;&amp;gt;confirmIntents&amp;lt;/code&amp;gt;&lt;br /&gt;
::Hiermit kann eingestellt werden, dass für bestimmte Intents immer ein Bestätigung erfragt wird. Unterstützt werden derzeit alle &amp;quot;set-&amp;quot;-Intents.&lt;br /&gt;
::Dazu werden &amp;lt;code&amp;gt;Intent&amp;lt;/code&amp;gt;=&amp;lt;code&amp;gt;regex&amp;lt;/code&amp;gt;-Paare verwendet.&lt;br /&gt;
:::&amp;lt;code&amp;gt;Intent&amp;lt;/code&amp;gt; ist der Name des gewünschten Intents&lt;br /&gt;
:::&amp;lt;code&amp;gt;regex&amp;lt;/code&amp;gt; ist eine Regex, die eine bestimmte Gruppe (für Gruppen-Intents) oder einen bestimmten Device-Namen beschreiben muss.&lt;br /&gt;
:::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
:::&amp;lt;code&amp;gt;confirmIntents=SetOnOffGroup=light|blinds SetOnOff=blind.*&amp;lt;/code&amp;gt;&lt;br /&gt;
::Befehle werden nur nach einer positiven Bestätigung ausgeführt. Das bedeutet, es muss unbedingt ein &amp;lt;code&amp;gt;Mode:OK&amp;lt;/code&amp;gt;-Wert vom &#039;&#039;ConfirmAction&#039;&#039;-Intent gesendet werden. Jede andere Wert für &amp;lt;code&amp;gt;Mode&amp;lt;/code&amp;gt; wird als Abbruch gewertet. Es kann aber auch der eigene Intent &#039;&#039;CancelAction&#039;&#039; für den Abbruch verwendet werden.&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:ConfirmAction]&lt;br /&gt;
( yes, please do it | go on | that&#039;s ok | yes, please ){Mode:OK}&lt;br /&gt;
( don&#039;t do it after all ){Mode}&lt;br /&gt;
&lt;br /&gt;
[de.fhem:CancelAction]&lt;br /&gt;
( let it be | oh no | cancel | cancellation ){Mode:Cancel}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:*&amp;lt;code id=&amp;quot;attr-rhasspytweaks-confirmintentresponses&amp;quot;&amp;gt;confirmIntentResponses&amp;lt;/code&amp;gt;&lt;br /&gt;
::Üblicherweise ist die Bestätigungs-Frage ein &amp;quot;Echo&amp;quot; des ursprünglich gesprochenen Befehls. Dies kann für jeden Intent geändert werden,&lt;br /&gt;
::Dies kann für jeden Intent individuell angepaßt werden, wobei die Variablen $target, ($rawInput) und $Value verwendet werden können.&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;confirmIntentResponses=SetOnOffGroup=&amp;quot;wirklich die Gruppe $target $Value schalten&amp;quot; SetOnOff=&amp;quot;bestätige dass $target $Value geschaltet werden soll&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
::&amp;lt;code&amp;gt;$Value&amp;lt;/code&amp;gt; wird dabei mit den defaults aus dem &#039;&#039;words&#039;&#039; key in der languageFile übersetz (falls vorhanden). Weitere Optionen für Ersetzungen von &amp;lt;code&amp;gt;$Value&amp;lt;/code&amp;gt; sind für einzelne Devices über den [[#attr-rhasspyspecials-confirmvaluemap|confirmValueMap]] key im Attribut &#039;&#039;rhasspySpecials&#039;&#039; verfügbar.&lt;br /&gt;
&lt;br /&gt;
:*&amp;lt;code id=&amp;quot;attr-rhasspytweaks-intentfilter&amp;quot;&amp;gt;intentFilter&amp;lt;/code&amp;gt;&lt;br /&gt;
::Rhasspy aktiviert bei jedem Neustart alle ihm bekannten Intents. Da manche der von FHEM genutzten Intents nur in bestimmten Situationen (v.a. innerhalb offener Dialoge) benötigt werden, deaktiviert RHASSPY diese (derzeit: ConfirmAction, CancelAction, ChoiceRoom und ChoiceDevice beim Start, sowie jedes Mal, wenn erkannt wird, dass das Standardfiltering nicht wie erwartet funktioniert (was v.a. bei einem zwischenzeitlichen Rhasspy-Neustart der Fall sein kann). Über diesen Tweak können weitere Intents mit in diese automatisierte (De-) Aktivierung mit einbezogen werden. Entweder ist dabei einfach der Name (ohne die Zusätze aus &#039;&#039;language&#039;&#039; und &#039;&#039;fhemId&#039;&#039; anzugeben, oder eine explizite Anweisung zum ein- und Ausschalten (in der Form &amp;lt;code&amp;gt;intentname=true&amp;lt;/code&amp;gt;). Die 4 vorgenannten Standard-Intents können nicht über diesen Weg aktiviert werden. Details zur intern genutzten Rhasspy-Funktionalität sind in der [https://rhasspy.readthedocs.io/en/latest/reference/#dialogue-manager Rhasspy-Dokumentation] zu finden.&lt;br /&gt;
&lt;br /&gt;
:*&amp;lt;code id=&amp;quot;attr-rhasspytweaks-ignorekeywords&amp;quot;&amp;gt;ignoreKeywords&amp;lt;/code&amp;gt;&lt;br /&gt;
::Da in manchen der von RHASSPY automatisch ausgewerteten Attribute häufig auch eher technisch motivierte Angaben zu finden sind, kann über diesen Schlüssel verhindert werden, dass derartige Angaben bei der slot-Erstellung übergangen werden. Dies betrifft z.B. häufig anzutreffende &#039;&#039;room&#039;&#039;-Werte wie &#039;&#039;MQTT&#039;&#039;, &#039;&#039;alexa&#039;&#039;, &#039;&#039;homebridge&#039;&#039; oder &#039;&#039;googleassistant&#039;&#039;. Die hier angegebenen key-value-Paare werden als Negativ-Filter für die angegebenen Werte verwendet (derzeit nur für &#039;&#039;rooms&#039;&#039; und &#039;&#039;group&#039;&#039;). &#039;&#039;value&#039;&#039; wird dabei als (case-insensitive) regex behandelt, verglichen wird auf exakten match (es müssen also ggf. vorne bzw. hinten &#039;&#039;.*&#039;&#039; angefügt werden).&lt;br /&gt;
::Dieses &#039;&#039;&#039;Beispiel&#039;&#039;&#039; filtert daher die o.g. Räume aus und dazu noch die strukturierten Unterräume unterhalb &#039;&#039;Steuerung&#039;&#039;:&lt;br /&gt;
::&amp;lt;code&amp;gt;ignoreKeywords=rooms=mqtt.*|alexa|homebridge|googleassistant|steuerung-.&amp;lt;/code&amp;gt;&lt;br /&gt;
:* &amp;lt;code id=&amp;quot;attr-rhasspytweaks-ignorekeywords&amp;quot;&amp;gt;gdt2groups&amp;lt;/code&amp;gt;  Dieser Eintrag ermöglicht es, alle Geräte eines generichDeviceType innerhalb der automatischen Erfassung automatisch einer oder mehreren Gruppen zuzuordnen. Die Vorgaben in diesem Eintrag werden nicht übernommen, wenn am jeweiligen Einzelgerät  das Attribut &#039;&#039;rhasspyGroup&#039;&#039; gesetzt ist.  Hier eine deutschsprachige Vorbelegung als &#039;&#039;&#039;Beispiel&#039;&#039;&#039;: &amp;lt;code&amp;gt;gdt2groups= blind=rollläden,rollladen thermostat=heizkörper light=lichter,leuchten&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Readings / Events==&lt;br /&gt;
;&amp;lt;code&amp;gt;IODev&amp;lt;/code&amp;gt;&lt;br /&gt;
:Das eingestellte IO-Device&lt;br /&gt;
;&amp;lt;code&amp;gt;intents&amp;lt;/code&amp;gt;&lt;br /&gt;
:Eine Liste der in Rhasspy vorhandenen Intents&lt;br /&gt;
;&amp;lt;code&amp;gt;lastIntentPayload&amp;lt;/code&amp;gt;&lt;br /&gt;
:Inhalt des letzten Intents der von FHEM empfangen wurde&lt;br /&gt;
;&amp;lt;code&amp;gt;lastIntentTopic&amp;lt;/code&amp;gt;&lt;br /&gt;
:Das MQTT-Topic des letzten Intents&lt;br /&gt;
;&amp;lt;code&amp;gt;listening_roomname&amp;lt;/code&amp;gt;&lt;br /&gt;
:Ein Reading für jeden Raum bzw. jede siteId&lt;br /&gt;
:Wechselt auf 1 sobald ein Hotword erkannt wurde und zurück auf 0, sobald die Dialog-Session beendet ist.&lt;br /&gt;
:Kann z.B. verwendet werden, um den Ton eines TVs auszuschalten, während Rhasspy auf ein Kommando hört.&lt;br /&gt;
;&amp;lt;code&amp;gt;mute_roomname&amp;lt;/code&amp;gt;&lt;br /&gt;
:Zeigt an, ob ein Raum / eine siteId vom Intent &#039;&#039;SetMute&#039;&#039; stumm geschalten wurde und somit keine Befehle ausführt.&lt;br /&gt;
:Jeweils ein Reading für jede siteId.&lt;br /&gt;
:Default ist 0.&lt;br /&gt;
;&amp;lt;code&amp;gt;responseType&amp;lt;/code&amp;gt;&lt;br /&gt;
:Der Typ der letzten Antwort (text/voice).&lt;br /&gt;
:voiceResponse and textResponse&lt;br /&gt;
:Antwort auf das letzte Sprach-/Text-Kommando.&lt;br /&gt;
;&amp;lt;code&amp;gt;siteIds&amp;lt;/code&amp;gt;&lt;br /&gt;
:Listet alle siteIds auf.&lt;br /&gt;
:Kann mit [[#set-fetchsiteids|fetchSiteIds]] aktualisiert werden.&lt;br /&gt;
;&amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt;&lt;br /&gt;
:Zeigt an ob RHASSPY mit Rhasspy verbunden ist&lt;br /&gt;
;&amp;lt;code&amp;gt;training&amp;lt;/code&amp;gt;&lt;br /&gt;
:Letzte zurückgelieferte Antwort auf einen [[#set-trainrhasspy|trainRhasspy]]-Befehl.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
;&amp;lt;code&amp;gt;updateSentences&amp;lt;/code&amp;gt;&lt;br /&gt;
:Letzte zurückgelieferte Antwort nach einem [[#set-update-slots|updateSlots]]-Befehl.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
;&amp;lt;code&amp;gt;updateSlots&amp;lt;/code&amp;gt;&lt;br /&gt;
:Letzte zurückgelieferte Antwort nach einem [[#set-update-slots|updateSlots]]-Befehl.&lt;br /&gt;
;&amp;lt;code&amp;gt;hotword&amp;lt;/code&amp;gt;&lt;br /&gt;
:Wenn aktiviert, beinhaltet dieses Reading das letzte verwendete Hotword und von welcher siteId es aufgerufen wurde.&lt;br /&gt;
;&amp;lt;code&amp;gt;voiceResponse&amp;lt;/code&amp;gt;&lt;br /&gt;
:Letze Sprach-Antwort auf einen Sprach-Befehl&lt;br /&gt;
&lt;br /&gt;
=== Benutzerdefinierte Readings ===&lt;br /&gt;
&lt;br /&gt;
There are some readings you may find useful to tweak some aspects of RHASSPY&#039;s logics:&lt;br /&gt;
*&amp;lt;code&amp;gt;siteId2room_&amp;lt;/code&amp;gt; Falls keine explizite Raum-Information in den an RHASSPY weitergegebenen Daten enthalten ist, ermittelt das Modul den Raum in der Regel aus dem Namen der &#039;&#039;siteId&#039;&#039;. So werden z.B. alle raumlosen Anweisungen von einem Satelliten names &#039;&#039;schlafzimmer&#039;&#039;, im Raum &#039;&#039;schlafzimmer&#039;&#039; ausgeführt werden (wenn möglich). Die Gruppenfunktion von Rhasspy wird unterstützt, so wird z.B. &#039;&#039;wohnzimmer.vorne&#039;&#039; ebenfalls automatisch dem Raum &#039;&#039;wohnzimmer&#039;&#039; zugeordnet. Über passende Angaben in &#039;&#039;siteId2room-Readings&#039;&#039; kann dieses Verhalten modifiziert werden:  &amp;lt;code&amp;gt;setreading siteId2room_mobile_phone1 wohnzimmer&amp;lt;/code&amp;gt; wird RHASSPY veranlassen, den Satelliten  &#039;&#039;mobile_phone1&#039;&#039; dem Raum &#039;&#039;wohnzimmer&#039;&#039; zuzuweisen. Hierzu ist in &#039;&#039;contrib&#039;&#039; auch eine Hilfsfunktion zu finden, mit der mobilen Satelliten per Sprachbefehl einem neuen Raum zugewiesen werden können.&lt;br /&gt;
*&amp;lt;code&amp;gt;siteId2doubleSpeak_&amp;lt;/code&amp;gt; RHASSPY antwortet immer über den Satelliten, von dem die jeweilige Sprachanweisung kam. Manchmal kann es erwünscht sein, zusätzliche Sprachrückmeldungen an einen weiteren Satelliten zu geben - z.B. weil der betreffende Lautsprecher (zeitweise) ausgeschaltet ist. Ist ein entsprechendes Reading gesetzt, erfolgen (zusätzliche!) Sprachausgaben an den dort als Readingwert angegebenen zweiten Satelliten; das Namensschema der Readings entspricht dem für site2room.&lt;br /&gt;
&lt;br /&gt;
== FHEM-Devices für die Verwendung mit Rhasspy konfigurieren ==&lt;br /&gt;
Um ein Gerät mit Rhasspy steuern zu können, muss Rhasspy einige Details über das Gerät kennen. Diese werden bekannt gemacht, in dem bei den Geräten Attribute gesetzt werden, die anschließend vom RHASSPY-Modul ausgewertet und an Rhasspy gesendet werden.&lt;br /&gt;
&lt;br /&gt;
Der einfachste - und empfohlene - Weg, dies zu erreichen, ist durch Setzen des Attributs &#039;&#039;&#039;&#039;&#039;genericDeviceType&#039;&#039;&#039;&#039;&#039;. Das Modul erkennt dann die möglichen Schalt - und Abfragemöglichkeiten des Gerätes automatisch.&lt;br /&gt;
&lt;br /&gt;
Sollte &#039;&#039;genericDeviceType&#039;&#039; (gDT) nicht ausreichen, gibt es noch weitere Attribute, die stattdessen oder ergänzend dazu verwendet werden können (z.b. rhasspyName, rhasspyRoom, ...). Die Namen dieser Attribute beginnen alle mit dem &#039;&#039;prefix&#039;&#039;, das in der DEF des RHASSPY-Moduls gesetzt wurde. Diese Dokumentation verwendet das Prefix &amp;lt;code&amp;gt;rhasspy&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Sind sowohl &#039;&#039;genericDeviceType&#039;&#039; als auch Spezial-Attribute vorhanden, werden die von gDT gesammelten Möglichkeiten durch die der Spezial-Attribute überschrieben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Wichtig:&#039;&#039;&#039;&lt;br /&gt;
*Nach JEDER Änderung an den folgenden Attributen muss ein &amp;lt;code&amp;gt;[[#set-update-devicemap|update devicemap]]&amp;lt;/code&amp;gt; ausgeführt werden. Sonst erfahren weder RHASSPY, noch Rhasspy von der Änderung.&lt;br /&gt;
*RHASSPY sammelt alle Informationen aus diesen Attributen in seinem eigenen Device-HASH. Dieser wird durch das &amp;lt;code&amp;gt;update devicemap&amp;lt;/code&amp;gt;-Kommando aktualisiert und kann mittels &amp;lt;code&amp;gt;[[List|list]]&amp;lt;/code&amp;gt;-Befehl angezeigt werden. Für diesen HASH werden alle Namen und sonstige &amp;quot;Labels&amp;quot; in Kleinbuchstaben umgewandelt. Sollte man Slots händisch befüllen, muss also darauf geachtet werden, dass Rhasspy ebenfalls Werte in Kleinbuchstaben liefert.&lt;br /&gt;
*Die Mindestvoraussetzungen für ein FHEM Device um mit RHASSPY zusammenzuarbeiten sind:&lt;br /&gt;
**Das Device muss von der devspec im Define des RHASSPY-Devices abgedeckt werden&lt;br /&gt;
**Es muss mindestens eines der folgenden Attribute (im Normalfall &#039;&#039;genericDeviceType&#039;&#039;) im Device gesetzt sein.&lt;br /&gt;
*Die Mapping-Logik (für Namen, mögliche Schaltzustände, etc.) ist wie folgt:&lt;br /&gt;
**Sind RHASSPY-spezifische Attribute gesetzt, werden ausschließlich diese verwendet. Natürlich nur für den Zweck des gesetzten Attributs. Ein gesetzter &#039;&#039;rhasspyName&#039;&#039; z.B. wird also nicht verhindern, dass die durch &#039;&#039;genericDeviceType&#039;&#039; ermittelten möglichen Schaltzustände ebenfalls gespeichert werden.&lt;br /&gt;
**Je spezifischer ein Attribut ist, desto eher wird überschreiben, was weniger speziell ist. Ein gesetzter &#039;&#039;alias&#039;&#039; wird also verhindern, dass der (technische) Device-Name verwendet wird. Aber ein gesetztes Attribut &#039;&#039;alexaName&#039;&#039;, &#039;&#039;gassistantName&#039;&#039; oder &#039;&#039;siriName&#039;&#039; wird (auch) den &#039;&#039;alias&#039;&#039; überschreiben. Sind zwei &amp;quot;gleichwertige&amp;quot; Attribute vorhanden (z.B. &#039;&#039;siriName&#039;&#039; und &#039;&#039;alexaName&#039;&#039;), werden beide verwendet.&lt;br /&gt;
*Attribut-Werte werden typischerweise &amp;quot;Zeile für Zeile&amp;quot; gelesen. Wobei gilt, eine Zeile pro Wert/Befehl/Funktionalität. Zeilenumbrüche &#039;&#039;&#039;müssen&#039;&#039;&#039; also an den richtigen Stellen gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;code&amp;gt;genericDeviceType&amp;lt;/code&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
Ist dieses Attribut gesetzt &#039;&#039;&#039;und&#039;&#039;&#039; entspricht der Devicename der devspec, wird RHASSPY das Mapping (und andere eventuell schon vorhandene Werte) automatisch ermitteln.&lt;br /&gt;
&lt;br /&gt;
Derzeit werden folgende Werte für das Attribut genericDeviceType unterstützt:&lt;br /&gt;
*switch&lt;br /&gt;
*light&lt;br /&gt;
*thermostat&lt;br /&gt;
*thermometer&lt;br /&gt;
*HumiditySensor&lt;br /&gt;
*blind/blinds/shutter&lt;br /&gt;
*media&lt;br /&gt;
*motion/contact/ContactSensor/lock/presence&lt;br /&gt;
&lt;br /&gt;
Wird &#039;&#039;genericDeviceType&#039;&#039; verwendet, werden unter anderem folgende Informationen gesammelt:&lt;br /&gt;
* der Name (&amp;lt;code&amp;gt;NAME&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;alias&amp;lt;/code&amp;gt;) des Devices&lt;br /&gt;
* der (FHEM-)Raum, in dem sich das Device befindet.&lt;br /&gt;
* die Gruppe, zu der das Device gehört (ggf. unter Beachtung des Schlüssels  &amp;lt;code id=&amp;quot;attr-rhasspytweaks-ignorekeywords&amp;quot;&amp;gt;gdt2groups&amp;lt;/code&amp;gt; aus &#039;&#039;rhasspyTweaks&#039;&#039;)&lt;br /&gt;
* wie Informationen vom Gerät abgefragt werden können&lt;br /&gt;
* wie Werte/Status am Gerät gesetzt werden können&lt;br /&gt;
&lt;br /&gt;
Die Verwendung von &#039;&#039;genericDeviceType&#039;&#039; ist der einfachste Weg, wie man FHEM-Devices dazu bringen kann, mit RHASSPY zusammenzuarbeiten. Manchmal liefert genericDeviceType aber nicht ausreichende oder nicht passende Informationen. In so einem Fall können die folgenden Attribute (zusätzlich) verwendet werden.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;code&amp;gt;rhasspyName&amp;lt;/code&amp;gt;===&lt;br /&gt;
Mit diesem Attribut kann der Name des Geräts eingestellt werden, mit dem es in einem Sprachbefehl angesprochen werden soll. Es können auch mehrere Namen - getrennt durch ein Komma - angegeben werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039; &amp;lt;code&amp;gt;attr &amp;lt;device&amp;gt; rhasspyName Lampe,Stehlampe,Wunderlicht&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es ist durchaus möglich, mehrere FHEM-Geräte mit dem selben Namen zu haben. Sie müssen dann nur in unterschiedlichen Räumen sein.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;code&amp;gt;rhasspyRoom&amp;lt;/code&amp;gt;===&lt;br /&gt;
Dieses Attribut kann verwendet werden, um Rhasspy mitzuteilen, in welchem physischem (oder logischen) Raum sich das Gerät befindet.&lt;br /&gt;
&lt;br /&gt;
Ist es nicht vorhanden, wird &amp;lt;code&amp;gt;alexaRoom&amp;lt;/code&amp;gt; oder das FHEM-Attribut &amp;lt;room&amp;gt; verwendet. Sind auch diese nicht vergeben, gehört das Gerät zum &amp;quot;Standard-Raum&amp;quot;, der im Define des RHASSPY-Devices angegeben wurde.&lt;br /&gt;
&lt;br /&gt;
Das Attribut ist nützlich, wenn man Sprachbefehle ohne explizite Raumangabe verwenden will. Gibt es z.B. ein Gerät mit dem Namen &#039;&#039;Lampe&#039;&#039; und dessen rhasspyRoom-Attribut ist gleich, wie die &#039;&#039;siteId&#039;&#039; von der aus der Sprachbefehl abgesetzt wird, reicht es zu sagen &amp;quot;Lampe ein&amp;quot;. Der Raum muss also nicht extra dazu gesagt werden.&lt;br /&gt;
&lt;br /&gt;
Es ist auch möglich, mehrere Raum-Namen zu vergeben sofern diese durch ein Komma voneinander getrennt werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039; &amp;lt;code&amp;gt;attr &amp;lt;device&amp;gt; rhasspyRoom livingroom&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hinweis: Wenn die &#039;&#039;siteId&#039;&#039; den Konventionen von Rhasspy zur Gruppierung von siteIds folgt (&#039;&#039;roomname.satellite&#039;&#039;), wird nur &amp;lt;code&amp;gt;roomname&amp;lt;/code&amp;gt; als Raum-Name angenommen. Beachte: Die automatisierte Zuweisung zu einem Raum kann durch &#039;&#039;siteId2room_.*&#039;&#039;-Readings modifiziert werden (s.o.). &lt;br /&gt;
===&amp;lt;code&amp;gt;rhasspyGroup&amp;lt;/code&amp;gt;===&lt;br /&gt;
Kommagetrennte Liste an Gruppen, zu denen das Gerät zugehörig ist&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039; &amp;lt;code&amp;gt;attr &amp;lt;device&amp;gt; rhasspyGroup Lampen,Beleuchtung Arbeitsfläche,Küchen Beleuchtung&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;code&amp;gt;rhasspyMapping&amp;lt;/code&amp;gt;===&lt;br /&gt;
Wenn die automatische Erkennung des richtigen Intents für ein Gerät nicht funktioniert oder nicht das gewünschte Ergebnis liefert, kann mit diesem Attribut angegeben werden, mit welchem Intent das Gerät gesteuert werden kann.&lt;br /&gt;
&lt;br /&gt;
Es ist möglich, mehrere verschiedene Intents pro Gerät zu verwenden. Es muss nur einfach eine neue Zeile für ein weiteres Mapping verwendet werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr &amp;lt;device&amp;gt; rhasspyMapping SetOnOff:cmdOn=on,cmdOff=off,response=&amp;quot;Alles klar&amp;quot;&lt;br /&gt;
GetOnOff:currentVal=state,valueOff=off&lt;br /&gt;
GetNumeric:currentVal=pct,type=brightness&lt;br /&gt;
SetNumeric:currentVal=brightness,cmd=brightness,minVal=0,maxVal=255,map=percent,step=1,type=brightness&lt;br /&gt;
Status:response=Die Helligkeit in der Küche ist bei [&amp;lt;device&amp;gt;:pct]&lt;br /&gt;
MediaControls:cmdPlay=play,cmdPause=pause,cmdStop=stop,cmdBack=previous,cmdFwd=next&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Formatierung von Befehlen und Readings innerhalb eines rhasspyMappings====&lt;br /&gt;
Manche Intents können FHEM-Kommandos oder -Readings verwenden, um Werte auszulesen oder zu setzen.&lt;br /&gt;
&lt;br /&gt;
Dabei gibt es drei Möglichkeiten, wie diese geschrieben werden können:&lt;br /&gt;
*Direktes Verwenden von SET-Kommando oder Reading des aktuellen Device:&lt;br /&gt;
:&amp;lt;code&amp;gt;cmd=on or currentReading=temperature&amp;lt;/code&amp;gt;&lt;br /&gt;
*Umleiten eines Kommando auf ein anderes Device oder Verwenden eines Readings aus einem anderen Gerät:&lt;br /&gt;
:&amp;lt;code&amp;gt;cmd=Otherdevice:on or currentReading=Otherdevice:temperature&amp;lt;/code&amp;gt;&lt;br /&gt;
*Perl-Code um einen Befehl auszuführen oder einen Wert zu setzen:&lt;br /&gt;
:Das ermöglicht sehr komplexe Anfragen.&lt;br /&gt;
:Der Code muss in geschwungenen Klammern sein.&lt;br /&gt;
:&amp;lt;code&amp;gt;{currentVal={ReadingsVal($DEVICE,&amp;quot;state&amp;quot;,0)}&amp;lt;/code&amp;gt;&lt;br /&gt;
:oder&lt;br /&gt;
:&amp;lt;code&amp;gt; cmd={fhem(&amp;quot;set $DEVICE dim $VALUE&amp;quot;)}&amp;lt;/code&amp;gt;&lt;br /&gt;
:$DEVICE ist das aktuelle FHEM-device. Der SetNumeric-Intent kann $VALUE für den Wert verwenden, der gesetzt werden soll.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;code&amp;gt;rhasspySpecials&amp;lt;/code&amp;gt;===&lt;br /&gt;
Dieses Attribut wirkt ähnlich wie [[#rhasspyTweaks| rhasspyTweaks]], verändert allerdings nur jeweils das Verhalten des Geräts, bei dem es gesetzt ist. Auch dieses Attribut wird zeilenweise eingelesen, es können ein oder mehrere der folgenden Optionen gesetzt werden:&lt;br /&gt;
&lt;br /&gt;
==== group ====&lt;br /&gt;
::Wird dieser Schlüssel gesetzt, wird das Gerät bei Gruppenaktionen nicht direkt adressiert, sondern die hier angegebene Gruppe. Details hierzu sind in [[RHASSPY/Vertiefung#Timing-Aspekte| Vertiefung - Timing-Aspekte]] zu finden.&lt;br /&gt;
&lt;br /&gt;
::&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
::&amp;lt;code&amp;gt;attr lamp1 rhasspySpecials group:async_delay=100 prio=1 group=lights&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== numericValueMap ====&lt;br /&gt;
::Ermöglicht es, statt der allgemeinen Methode zum Umgang mit numerischen Werten einzelnen Werten spezielle Kommandos zuzuweisen. Dies kann z.B. hilfreich sein, um spezielle Positionen für Rollladengeräte anzusteuern.&lt;br /&gt;
::&#039;&#039;&#039;Beispiel&#039;&#039;&#039;:&lt;br /&gt;
::&amp;lt;code&amp;gt;attr blind1 rhasspySpecials numericValueMap:10=&#039;Event Slit&#039; 50=&#039;myPosition&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
::führt dazu, dass ein numerischer Wert von 10 (im {Value}-key) das Kommando &amp;lt;code&amp;gt;set blind1 Event Slit&amp;lt;/code&amp;gt; ausführt.&lt;br /&gt;
&lt;br /&gt;
==== venetianBlind ====&lt;br /&gt;
Siehe [[RHASSPY/Vertiefung#Jalousien|Vertiefung - Jalousien]]&lt;br /&gt;
&lt;br /&gt;
==== colorCommandMap ====&lt;br /&gt;
Sowie **colorTempMap** und **colorForceHue2rgb**&lt;br /&gt;
Siehe [[RHASSPY/Vertiefung#Farben|Vertiefung - Farben]]&lt;br /&gt;
&lt;br /&gt;
==== priority ====&lt;br /&gt;
Ermöglicht es, Rückfragen zu vermeiden, wenn mehrere Geräte für bestimmte Aktionen in Frage kommen. Siehe [[RHASSPY/Vertiefung#Einer_statt_alle|Einer statt alle]]&lt;br /&gt;
&lt;br /&gt;
==== confirm ====&lt;br /&gt;
Ist eine Möglichkeit, Geräte nur nach Rückfrage und Bestätigung zu schalten (ähnlich wie &#039;&#039;confirmIntents&#039;&#039; in &#039;&#039;rhasspyTweaks&#039;&#039;). Es können entweder einfach nur Intent-Namen angegeben werden, oder Paare von **Intent** und zugehöriger **response**:&lt;br /&gt;
 SetOnOff=&amp;quot;Soll $target wirklich $Value geschaltet werden&amp;quot; SetScene&lt;br /&gt;
&lt;br /&gt;
==== confirmValueMap ====&lt;br /&gt;
Kann spezielle Übersetzungen für $Value enthalten, z.B. für Rollladen-Geräte:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;confirm: SetOnOff=&amp;quot;wirklich $Value $target&amp;quot;&lt;br /&gt;
confirmValueMap: on=öffnen off=schließen&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== scenes ====&lt;br /&gt;
Wird bei der automatisierten Erfassung erkannt, dass ein Gerät das Setzen von Szenen unterstützt, werden die erkannten Szenen-Namen an Rhasspy übergeben. Da diese häufig technischer Natur sind, eignen sie sich nicht für eine Spracherkennung. Über diesen Schlüssel können daher sprechbare Namen für jede Szene vergeben werden, und/oder einzelne bzw. alle Szenen von der Erkennung ausgenommen werden. Der Kenner &#039;&#039;none&#039;&#039; löscht die Szene von der Liste der übermittelten Szenen, wird die Kombination &#039;&#039;all=none&#039;&#039; angegeben, wird dieses Gerät insgesamt von der Vorbereitung für den Intent &#039;&#039;SetScene&#039;&#039; ausgeschlossen.&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;attr lamp1 rhasspySpecials scenes:scene2=&amp;quot;Kino zu zweit&amp;quot; scene3=Musik scene1=none scene4=none&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Siehe auch [[RHASSPY/Vertiefung#echte_Szenen|Vertiefung - echte Szenen]]. &lt;br /&gt;
&lt;br /&gt;
=== Veraltete Attribute ===&lt;br /&gt;
In der Regel sollte es ausreichen, die zu steuernden Devices über die oben genannten Attribute zu konfigurieren. Es gibt jedoch noch zwei ältere Methoden. Um diese zu verwenden, muss zuerst jeweils ein entsprechendes User-Attribut im FHEM-Device, das damit gesteuert werden soll, angelegt werden.&lt;br /&gt;
&lt;br /&gt;
====&amp;lt;code&amp;gt;rhasspyChannels&amp;lt;/code&amp;gt;====&lt;br /&gt;
Das Attribut wird vom Intent &#039;&#039;MediaControls&#039;&#039; verwendet. Es informiert den Intent darüber, welche (Medien-)Kanäle vorhanden sind und welcher FHEM-Befehl oder Perl-Code auszuführen ist, wenn auf diesen Kanal geschaltet werden soll.&lt;br /&gt;
&lt;br /&gt;
In diesem Attribut muss eine Zeile pro (Medien-)Kanal verwendet werden.&lt;br /&gt;
&lt;br /&gt;
Um rhasspyChannels zu verwenden, muss zuerst ein neues User-Attribut im FHEM-Device, das damit gesteuert werden soll, angelegt werden. Dafür kann z.B. dieses Beispiel verwendet werden: &amp;lt;code&amp;gt;attr &amp;lt;deviceName&amp;gt; userattr rhasspyChannels:textField-long&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr &amp;lt;device&amp;gt; rhasspyChannels orf eins=channel 201&lt;br /&gt;
orf zwei=channel 202&lt;br /&gt;
orf drei=channel 203&lt;br /&gt;
netflix=launchApp Netflix&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====&amp;lt;code&amp;gt;rhasspyColors&amp;lt;/code&amp;gt;====&lt;br /&gt;
Ältere Methode, die verwendet werden kann, um Lichtfarben zu wechseln. Es wird nachdrücklich empfohlen, die neueren Methoden über die (nummerisch zu übergebenden) allgemeinen Farbwerte und/oder ein &#039;&#039;colorCommandMap&#039;&#039; oder &#039;&#039;colorTempMap&#039;&#039; (siehe &#039;&#039;rhasspySpecials&#039;&#039;) zu konfigurieren!&lt;br /&gt;
&lt;br /&gt;
Um das Mapping zu verwenden, muss zuerst ein User-Attribut am zu steuernden Gerät angelegt werden. Z.B. &amp;lt;code&amp;gt;attr &amp;lt;deviceName&amp;gt; userattr rhasspyChannels:textField-long&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Eine Zeile pro Farbe&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Beispiel:&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
attr lamp1 rhasspyColors rot=rgb FF0000&lt;br /&gt;
grün=rgb 008000&lt;br /&gt;
blau=rgb 0000FF&lt;br /&gt;
gelb=rgb FFFF00&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Intents ==&lt;br /&gt;
Intents werden verwendet um FHEM zu sagen, was es nach einem erhaltenen Sprach-/Textkommand unternehmen soll. Dieses Modul stellt einige Intents bereit.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Wichtig&lt;br /&gt;
:*Bei Tags (&amp;lt;code&amp;gt;Value&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;, etc.) ist die Schreibweise sehr wichtig! Die sind case-sensitive. Bitte daher genau so schreiben, wie sie in dieser Dokumentation vorkommen.&lt;br /&gt;
:*RHASSPY erstellt bei einem &amp;lt;code&amp;gt;update slots&amp;lt;/code&amp;gt; auch Slots je nach Möglichkeiten der Geräte oder Gruppen. Unterstützt ein Gerät zum Beispiel den Intent &#039;&#039;GetNumeric&#039;&#039;, wird auch ein Slot &amp;lt;code&amp;gt;de.fhem.Device-GetNumeric&amp;lt;/code&amp;gt; erstellt. Ein Gerät, dass ein- und ausgeschalten werden kann, wird im Slot &amp;lt;code&amp;gt;de.fhem.Device-SetOnOff&amp;lt;/code&amp;gt; untergebracht. Ein einzelnes Gerät kann sich auch in mehreren Slots befinden. Um eine möglichst genaue Spracherkennung zu gewährleisten, ist &#039;&#039;&#039;empfohlen&#039;&#039;&#039;, diese &#039;&#039;&#039;spezifischen Slots&#039;&#039;&#039; - statt einfach nur &amp;lt;code&amp;gt;de.fhem.Device&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;de.fhem.Group&amp;lt;/code&amp;gt; - &#039;&#039;&#039;zu verwenden&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetOnOff ===&lt;br /&gt;
Intent um Geräte zwischen zwei Zuständen (ein/aus, auf/zu, start/stop) zu schalten.&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
SetOnOff:cmdOn=on,cmdOff=off&lt;br /&gt;
SetOnOff:cmdOn=on,cmdOff=off,response=&amp;quot;Sir yes Sir&amp;quot;&lt;br /&gt;
SetOnOff:cmdOn=on,cmdOff=off,response=&amp;quot;$DEVICE now [$DEVICE:state]&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Argumente:&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdOn&amp;lt;/code&amp;gt; Befehl um das Gerät einzuschalten. Siehe [[#Formatierung von Befehlen und Readings innerhalb eines rhasspyMappings|Formatierung von Befehlen und Readings innerhalb eines rhasspyMappings]].&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdOff&amp;lt;/code&amp;gt; Befehl um das Gerät auszuschalten. Siehe [[#Formatierung von Befehlen und Readings innerhalb eines rhasspyMappings|Formatierung von Befehlen und Readings innerhalb eines rhasspyMappings]].&lt;br /&gt;
&lt;br /&gt;
Optionale Argumente:&lt;br /&gt;
*&amp;lt;code&amp;gt;response&amp;lt;/code&amp;gt; Eine benutzerdefinierte Antwort auf den Befehl&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
schalten das licht ein&lt;br /&gt;
schließe den rollladen im schlafzimmer&lt;br /&gt;
starte die kaffeemaschine&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetOnOff]&lt;br /&gt;
(schalte|schalt|mache|mach|stelle|stell|starte) [den|die|das] $de.fhem.Device-SetOnOff{Device} [[(im|in dem|auf dem|in der|auf der)] $de.fhem.Room{Room}] (an|ein){Value:on}&lt;br /&gt;
(schalte|schalt|mache|mach|stelle|stell) [den|die|das] $de.fhem.Device-SetOnOff{Device} [[(im|in dem|auf dem|in der|auf der)] $de.fhem.Room{Room}] aus{Value:off}&lt;br /&gt;
(fahre|fahr) [den|die|das] $de.fhem.Device-blind{Device} [[(im|in dem|auf dem|in der|auf der)] $de.fhem.Room{Room}] ((hoch|auf){Value:on}|(zu|runter){Value:off})&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verpflichtende Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Value:on&amp;lt;/code&amp;gt; und/oder &amp;lt;code&amp;gt;Value:off&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetOnOffGroup ===&lt;br /&gt;
Intent um Gruppen von Geräte zwischen zwei Zuständen zu schalten.&lt;br /&gt;
&lt;br /&gt;
Dafür ist ein SetOnOff-Mapping benötigt und alle gewünschten Geräte müssen dasselbe Attribut &amp;lt;code&amp;gt;group&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;rhasspyGroup&amp;lt;/code&amp;gt; haben.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
schalte alle lampen in der küche aus&lt;br /&gt;
schließe alle rollläden im schlafzimmer&lt;br /&gt;
schalte alle lampen aus&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetOnOffGroup]&lt;br /&gt;
\[(schalt|mach)] (alle | sämtliche ) $de.fhem.Group-SetOnOff{Group} [[in|im|in der|auf der] [( überall:global | $de.fhem.Room ){Room}] ein{Value:on}&lt;br /&gt;
\[(schalt|mach)] (alle | sämtliche ) $de.fhem.Group-SetOnOff{Group} [[in|im|in der|auf der] [( überall:global | $de.fhem.Room ){Room}] aus{Value:off}&lt;br /&gt;
(öffne{Value:on}|schließe{Value:off}) (alle | sämtliche ) $de.fhem.Group-blind{Group} [[in|im|in der|auf der] [( überall:global{Room:global} | $de.fhem.Room{Room} )] &lt;br /&gt;
(fahr|fahre|mach|mache) [den|die|das] $de.fhem.Group-blind{Group} [[(im|in dem|in der)] ( überall:global{Room:global} | $de.fhem.Room{Room} )] ( auf{Value:on} | hoch{Value:on} | zu{Value:off} | runter{Value:off} )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verpflichtende Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Value:on&amp;lt;/code&amp;gt; und/oder &amp;lt;code&amp;gt;Value:off&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Group&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetTimedOnOff ===&lt;br /&gt;
Intent um Geräte für eine bestimmte Zeitspanne in einen bestimmten Zustand zu versetzten.&lt;br /&gt;
&lt;br /&gt;
Device muss ein SetOnOff-Mapping haben und die {{Link2CmdRef|Anker=setExtensions|Lang=de|Label=SetExtentions}} unterstützen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
schalte das licht für eine minute und dreißig sekunden aus&lt;br /&gt;
schalte die musik im bad bis zwei uhr ein&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetTimedOnOff]&lt;br /&gt;
schalte $de.fhem.Device-SetOnOff{Device} [$de.fhem.Room{Room}] für ([(1..60){Hour!int} (stunde|stunden)] [und] [(1..60){Min!int} (minute|minuten)] [und] [(1..60){Sec!int} (sekunde|sekunden)]) (ein{Value:on}|aus{Value:off})&lt;br /&gt;
schalte $de.fhem.Device-SetOnOff{Device} [$de.fhem.Room{Room}] bis (0..24){Hourabs!int} [(1..60){Min!int}] (ein{Value:on}|aus{Value:off})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verpflichtende Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Value&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Hour&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Min&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Sec&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Hourabs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetTimedOnOffGroup ===&lt;br /&gt;
Intent um eine Gruppe von Geräten für eine bestimmte Zeit zu schalten.&lt;br /&gt;
&lt;br /&gt;
Devices müssen ein SetOnOff-Mapping haben, in einer Gruppe sein und die {{Link2CmdRef|Anker=setExtensions|Lang=de|Label=SetExtentions}} unterstützen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
schalte alle lichter in der küche für fünfzig sekunden ein&lt;br /&gt;
schalte alle licher bis zwei uhr ein&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetTimedOnOffGroup]&lt;br /&gt;
schalte $de.fhem.Group-SetOnOff{Group} [$de.fhem.Room{Room}] für ([(1..60){Hour!int} (stunde|stunden)] [und] [(1..60){Min!int} (minute|minuten)] [und] [(1..60){Sec!int} (sekunde|sekunden)]) (ein{Value:on}|aus{Value:off})&lt;br /&gt;
schalte $de.fhem.Group-SetOnOff{Group} [$de.fhem.Room{Room}] bis (0..24){Hourabs!int} [(1..60){Min!int}] (ein{Value:on}|aus{Value:off})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Verpflichtende Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Value&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Group&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Hour&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Min&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Sec&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Hourabs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GetOnOff ===&lt;br /&gt;
Intent um den aktuellen Zustand eines Gerätes zu erfragen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
GetOnOff:currentVal=state,valueOff=closed&lt;br /&gt;
GetOnOff:currentVal=state,valueOn=on&lt;br /&gt;
GetOnOff:currentVal=pct,valueOff=0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Argumente:&lt;br /&gt;
Hinweis: nur &amp;lt;code&amp;gt;valueOn&amp;lt;/code&amp;gt; ODER &amp;lt;code&amp;gt;valueOff&amp;lt;/code&amp;gt; müssen gesetzt werden. Der jeweils andere Wert bekommt den anderen Status.&lt;br /&gt;
*&amp;lt;code&amp;gt;currentVal&amp;lt;/code&amp;gt; Reading aus dem der aktuelle Status hervorgeht&lt;br /&gt;
*&amp;lt;code&amp;gt;valueOff&amp;lt;/code&amp;gt; Wert, der den Zustand &#039;&#039;aus&#039;&#039; beschreibt&lt;br /&gt;
*&amp;lt;code&amp;gt;valueOn&amp;lt;/code&amp;gt; Wert, der den Zustand &#039;&#039;an&#039;&#039; beschreibt&lt;br /&gt;
&lt;br /&gt;
Optionale Argumente:&lt;br /&gt;
*&amp;lt;code&amp;gt;response&amp;lt;/code&amp;gt; Eine benutzerdefinierte Antwort auf den Befehl&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
ist das licht im bad ein&lt;br /&gt;
ist das fenster im wohnzimmer geöffnet&lt;br /&gt;
läuft die waschmaschine&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[en.fhem:GetOnOff]&lt;br /&gt;
ist $de.fhem.Device-GetOnOff{Device} [$de.fhem.Room{Room}] (ein|geöffnet){State:on}&lt;br /&gt;
ist $de.fhem.Device-GetOnOff{Device} [$de.fhem.Room{Room}] (aus|geschlossen){State:off}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zustände &#039;&#039;ein&#039;&#039; und &#039;&#039;aus&#039;&#039; sollten in unterschiedlichen Sentences sein und müssen &amp;lt;code&amp;gt;{State:on}&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;{State:off}&amp;lt;/code&amp;gt; beinhalten.&lt;br /&gt;
&lt;br /&gt;
Verpflichtende Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;State:on&amp;lt;/code&amp;gt; und/oder &amp;lt;code&amp;gt;State:off&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetNumeric ===&lt;br /&gt;
Intent, um Lampen zu dimmen, Rollladengeräte zu positionieren, Lautstärken oder Solltemperaturen zu ändern, usw.. &lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
SetNumeric:currentVal=pct,cmd=dim,minVal=0,maxVal=99,step=25,type=brightness&lt;br /&gt;
SetNumeric:currentVal=volume,cmd=volume,minVal=0,maxVal=99,step=10,type=volume&lt;br /&gt;
SetNumeric:currentVal=brightness,cmd=brightness,minVal=0,maxVal=255,map=percent,step=1,type=brightness&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Argumente:&lt;br /&gt;
*&amp;lt;code&amp;gt;currentVal&amp;lt;/code&amp;gt; Reading, in dem der aktuelle Wert zu finden ist (wird zwingend benötigt).&lt;br /&gt;
*&amp;lt;code&amp;gt;part&amp;lt;/code&amp;gt; Kann genutzt werden, um den Wert aus **currentVal** in mehrere Teile zu zerlegen (getrennt wird am Leerzeichen). Z.B. wenn currentVal 23 C ist, wird **part=0** **23** ergeben. Optionaler Parameter.&lt;br /&gt;
*&amp;lt;code&amp;gt;cmd&amp;lt;/code&amp;gt; Das **Set**-Kommando des Geräts, das in Folge des Sprachkommandos ausgeführt werden soll. (Notwendiger Parameter).&lt;br /&gt;
*&amp;lt;code&amp;gt;minVal&amp;lt;/code&amp;gt; Niedrigster zugelassener Wert, optional.&lt;br /&gt;
*&amp;lt;code&amp;gt;maxVal&amp;lt;/code&amp;gt; Höchster zugelassener Wert, optional.&lt;br /&gt;
*&amp;lt;code&amp;gt;step&amp;lt;/code&amp;gt; Schrittweite für relative Änderungen wie &amp;lt;code&amp;gt;mach lauter&amp;lt;/code&amp;gt;. Optional. Default: 10.&lt;br /&gt;
*&amp;lt;code&amp;gt;map&amp;lt;/code&amp;gt; Derzeit wird ausschließlich die Angabe **percent** ausgewertet. Optionaler Parameter, der bewirkt, dass alle Angaben als Prozentwert (zwischen minVal und maxVal) interpretiert werden und entsprechend gerechnet wird. So wird z.B. eine Leuchte mit **minVal=0** und **maxVal=255** beim Befehl &amp;quot;stelle das Licht auf 50&amp;quot; dies so verstehen, als wäre die Anweisung &amp;quot;stelle das Licht auf 50 Prozent&amp;quot; gewesen. Das Licht wird daher auf 127 gestellt, und nicht auf (absolut) 50.&lt;br /&gt;
*&amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; Zur Unterscheidung, falls mehrere SetNumeric-Intents für das Gerät möglich sind. Empfohlener Parameter.&lt;br /&gt;
&lt;br /&gt;
Gut zu wissen:&lt;br /&gt;
Um Kommandos wie **lauter** oder **leiser** ohne Angabe eines Gerätes ausführen zu können, muss RHASSPY zunächst ermitteln, welches Gerät gerade überhaupt etwas wiedergibt ist. Daher nutzt es die GetOnOff-Mappings, um festzustellen, welches Gerät vom **type=volume** überhaupt angeschaltet ist. Dabei wird wie üblich zunächst im aktuellen rhasspyRoom gesucht, bevor die Suche außerhalb fortgesetzt wird.&lt;br /&gt;
Setzt man also Mappings manuell, ist es ratsam, auch ein **GetOnOff**-Mapping zu setzen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zulässige Typen sind:&lt;br /&gt;
*&amp;lt;code&amp;gt;brightness&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;setTarget&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;temperature&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;volume&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
Stelle das Licht auf 30 Prozent&lt;br /&gt;
Mach das Radio leiser&lt;br /&gt;
Stell die Temperatur im Wohnzimmer 2 Grad wärmer&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
(Beachte: Wenn wie hier im Beispiel reele Zahlen (mit Komma) ermöglicht werden sollen (&amp;quot;acht Komma fünf&amp;quot;), wird ein [[#Custom Converter für reelle Zahlen| Custom Converter für reelle Zahlen]] benötigt)&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetNumeric]&lt;br /&gt;
den=(den|die|das)&lt;br /&gt;
cmdmulti=(schalte|schalt|mache|mach|stelle|stell)&lt;br /&gt;
rooms=([(im|in dem|auf dem|in der|auf der)] $de.fhem.Room{Room})&lt;br /&gt;
&amp;lt;cmdmulti&amp;gt; [&amp;lt;den&amp;gt;] $de.fhem.Device-SetNumeric{Device} auf (0..100){Value!int} [Prozent{Unit:percent}]&lt;br /&gt;
\[&amp;lt;cmdmulti&amp;gt;] [die Lautstärke [an|am]] [dem|&amp;lt;den&amp;gt;] $de.fhem.Device-media{Device} [&amp;lt;rooms&amp;gt;] [um] [(0..10){Value!float}] [dezibel{Unit:decibel}|Prozent{Unit:percent}] ( lauter:volUp | leiser:volDown ){Change}&lt;br /&gt;
&amp;lt;cmdmulti&amp;gt; [die Lautstärke [an|am]] [dem|&amp;lt;den&amp;gt;] [$de.fhem.Device-media{Device}] [&amp;lt;rooms&amp;gt;] [um] [(0..10){Value!float}] [dezibel{Unit:decibel}|Prozent{Unit:percent}] ( lauter:volUp | leiser:volDown ){Change}&lt;br /&gt;
&amp;lt;cmdmulti&amp;gt; [&amp;lt;den&amp;gt;] $de.fhem.Device-thermostat{Device} [&amp;lt;rooms&amp;gt;] [um] [(0..10){Value!int}] [Grad{Unit.degree}] ( wärmer:tempUp | kälter:tempDown ){Change}&lt;br /&gt;
&amp;lt;cmdmulti&amp;gt; [&amp;lt;den&amp;gt;] $de.fhem.Device-light{Device} [&amp;lt;rooms&amp;gt;] [um] [(0..30 [Komma:. 1..9]){Value!customFloat}] [Prozent{Unit:percent}] ( heller:lightUp | dunkler:lightDown){Change}&lt;br /&gt;
&amp;lt;cmdmulti&amp;gt; [&amp;lt;den&amp;gt;] ( $de.fhem.Device-light | $de.fhem.Device-media |$de.fhem.Device-blind){Device}  [&amp;lt;rooms&amp;gt;] auf [(0..30 [Komma:. 1..9]){Value!customFloat}]&lt;br /&gt;
( mehr{Change:lightUp} | weniger{Change:lightDown} ) $de.fhem.Device-light{Device} [&amp;lt;de.fhem:SetOnOff.rooms&amp;gt;]&lt;br /&gt;
( halte | stoppe | stop ) [&amp;lt;den&amp;gt;] $de.fhem.Device-blind{Device} [&amp;lt;de.fhem:SetOnOff.rooms&amp;gt;] [an] {Change:cmdStop}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Derzeit werden folgende Typen für das Feld &amp;lt;code&amp;gt;{Change}&amp;lt;/code&amp;gt; ausgewertet:&lt;br /&gt;
*&amp;lt;code&amp;gt;tempUp&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;tempDown&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;volUp&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;volDown&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;lightUp&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;lightDown&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;setUp&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;setDown&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notwendig sind:&lt;br /&gt;
*&amp;lt;code&amp;gt;Change&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Type&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Value&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Change&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optionale Tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Unit&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== SetNumericGroup ===&lt;br /&gt;
Intent, um Lampen zu dimmen, Rollladengeräte zu positionieren, Lautstärken oder Solltemperaturen zu ändern, usw.. Die Funktionsweise entspricht dabei dem des Intents &#039;&#039;SetNumeric&#039;&#039;, wobei eben statt eines einzelnen Devices eben ein oder mehrere Geräte über ihren Gruppennamen angesprochen werden. Statt des optionalen Tags &amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt; ist daher der Tag &amp;lt;code&amp;gt;Group&amp;lt;/code&amp;gt; zu übergeben.&lt;br /&gt;
Aus der Adressierung mehrerer Geräte ergeben sich einige Besonderheiten, die in der [[RHASSPY/Vertiefung]], dort speziell auch im Punkt [[RHASSPY/Vertiefung#Beispiel_SetOnOffGroup|Beispiel SetOnOffGroup]] näher erläutert sind. Wesentliche zu beachtende Aspekte sind:&lt;br /&gt;
* Vermeidung von Funk-Überschneidungen (&#039;&#039;Specials&#039;&#039; &#039;&#039;partOf&#039;&#039; und &#039;&#039;async_delay&#039;&#039;)&lt;br /&gt;
* Begrenzung der Gruppenzugehörigkeit durch die Raumzugehörigkeit (und die Aufhebung dieser Beschränkung durch die Übergabe des speziellen Raums &#039;&#039;global&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
=== GetNumeric ===&lt;br /&gt;
Intent, mit dem man Werte erfragen kann, wie z.B. die aktuelle Temperatur, Helligkeit, Lautstärke, ...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
GetNumeric:currentVal=temperature,part=1,type=temperature&lt;br /&gt;
GetNumeric:currentVal=pct,map=percent,minVal=0,maxVal=100,type=brightness&lt;br /&gt;
GetNumeric:currentVal=volume,type=volume&lt;br /&gt;
GetNumeric:currentVal=humidity,part=0,type=airHumidity&lt;br /&gt;
GetNumeric:currentVal=batteryPercent,type=battery&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Argumente:&lt;br /&gt;
*&amp;lt;code&amp;gt;currentVal&amp;lt;/code&amp;gt; Das Reading, das den abzufragenden Wert enthält&lt;br /&gt;
*&amp;lt;code&amp;gt;part&amp;lt;/code&amp;gt; Teile aus currentVal ableiten, indem am Leerzeichen getrennt wird. Ist &#039;&#039;currentVal&#039;&#039; beispielsweise &#039;&#039;23 C&#039;&#039;, entspricht &#039;&#039;part=1&#039;&#039; dem Wert &#039;&#039;23&#039;&#039;&lt;br /&gt;
*&amp;lt;code&amp;gt;map&amp;lt;/code&amp;gt; Die Funktionswiese entspricht dem &#039;&#039;SetNumeric&#039;&#039; Intent. Wandelt den vorhandenen Wert in eine Prozent-Angabe um.&lt;br /&gt;
*&amp;lt;code&amp;gt;minVal&amp;lt;/code&amp;gt; Niedrigster zulässiger Wert (nur benötigt, wenn &#039;&#039;map&#039;&#039; angegeben ist).&lt;br /&gt;
*&amp;lt;code&amp;gt;maxVal&amp;lt;/code&amp;gt; Höchster zulässiger Wert  (nur benötigt, wenn &#039;&#039;map&#039;&#039; angegeben ist).&lt;br /&gt;
*&amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; Dient der Unterscheidung zwischen mehreren GetNumeric-Anfragemöglichkeiten für dasselbe Gerät (auch relevant für SetNumeric-Anweisungen).&lt;br /&gt;
&lt;br /&gt;
Mögliche Abfragetypen:&lt;br /&gt;
*&amp;lt;code&amp;gt;airHumidity&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;battery&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;brightness&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;desired-temp&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;setTarget&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;soilMoisture&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;temperature&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;volume&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;waterLevel&amp;lt;/code&amp;gt;&lt;br /&gt;
Aus dem Abfragetypen ergibt sich die von RHASSPY ausgewählte Antwort.&lt;br /&gt;
&lt;br /&gt;
Beispiel Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
what is the temperature in the living room&lt;br /&gt;
how bright is the floor lamp&lt;br /&gt;
what is the volume of the tv&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
[en.fhem:GetNumeric]&lt;br /&gt;
#actual temperature&lt;br /&gt;
(what is|how high is) the temperature{Type:temperature} [$de.fhem.Device-GetNumeric{Device}] [$de.fhem.Room{Room}]&lt;br /&gt;
&lt;br /&gt;
#desired-temperature&lt;br /&gt;
\[what is the|how high is the] (desired temperature){Type:desired-temp} [$de.fhem.Device-GetNumeric{Device}] [$de.fhem.Room{Room}]&lt;br /&gt;
&lt;br /&gt;
#volume&lt;br /&gt;
(what is the|how high is the) volume{Type:volume} $de.fhem.Device-GetNumeric{Device} [$de.fhem.Room{Room}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Type&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional tags&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GetState ===&lt;br /&gt;
Intent to get specific information of a device. The respone can be defined.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
GetState:response=&amp;quot;Temperature is [$DEVICE:temp] degree at [Thermo:hum] percent humidity&amp;quot;&lt;br /&gt;
GetState:response={my $value=ReadingsVal(&amp;quot;$DEVICE&amp;quot;,&amp;quot;brightness&amp;quot;,&amp;quot;&amp;quot;); return &amp;quot;Brightness is $value&amp;quot;;}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Options:&lt;br /&gt;
*&amp;lt;code&amp;gt;response&amp;lt;/code&amp;gt; Text for the response Rhassyp will give.&lt;br /&gt;
:To use values from FHEM use format [Device:Reading].&lt;br /&gt;
:A comma within the response has to be escaped (\, instead of ,).&lt;br /&gt;
:Or you can use Perl-code enclosed in curley brackets to define the response.&lt;br /&gt;
:Mixing text and Perl-code is not supported.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
How is the state of the thermostat in the kitchen&lt;br /&gt;
state light in livingroom&lt;br /&gt;
state washer&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:GetState]&lt;br /&gt;
\[how is the] (state) $de.fhem.Device{Device} [$de.fhem.Room{Room}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== MediaControls ===&lt;br /&gt;
Intent to control media devices&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mapping:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
MediaControls:cmdPlay=play,cmdPause=pause,cmdStop=stop,cmdBack=previous,cmdFwd=next&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Options:&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdPlay&amp;lt;/code&amp;gt; Play command of the device. See chapter Formatting Commands and Readings inside a rhasspyMapping.&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdPause&amp;lt;/code&amp;gt; Command to pause the device.&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdStop&amp;lt;/code&amp;gt; Command to stop the device.&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdFwd&amp;lt;/code&amp;gt; Command to skip to the next track/channel/etc.&lt;br /&gt;
*&amp;lt;code&amp;gt;cmdBack&amp;lt;/code&amp;gt; Command to skip to the previous track/channel/etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note on issuing a voice-command without a room-name:&lt;br /&gt;
As described in the SetNumeric-Intent, it is recommended to define a GetOnOff-Mapping to use the MediaControls-Intent without a room name.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
skip to next track on the radio&lt;br /&gt;
pause&lt;br /&gt;
skip video on the dvd player&lt;br /&gt;
stop playback&lt;br /&gt;
next&lt;br /&gt;
previous&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:MediaControls]&lt;br /&gt;
(start){Command:cmdPlay} the playback [$de.fhem.Device-MediaControls{Device}]&lt;br /&gt;
(stop){Command:cmdStop} the playback [$de.fhem.Device-MediaControls{Device}]&lt;br /&gt;
(pause){Command:cmdPause} the playback [$de.fhem.Device-MediaControls{Device}]&lt;br /&gt;
(next){Command:Fwd} (song|title) [$de.fhem.Device-MediaControls{Device}]&lt;br /&gt;
(previous){Command:Back} (song|title) [$de.fhem.Device-MediaControls{Device}] [$de.fhem.Room{Room}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Command&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== MediaChannels ===&lt;br /&gt;
Intent to change radio-/tv channels, favorites, playlists, lightscenes, ...&lt;br /&gt;
&lt;br /&gt;
Instead of using the attribute rhasspyMapping, this intent is configured with an own attribute [[#rhasspyChannels]] in the respective device. Reason is the multiple-line-configuration.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
SWR3=favorite s_w_r_3&lt;br /&gt;
SWR1=favorite s_w_r_1&lt;br /&gt;
ARD=channel 204&lt;br /&gt;
Netflix=launchApp Netflix&lt;br /&gt;
Leselicht=set lightSceneWz scene Leselicht&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Notice on using the commands without a device name:&lt;br /&gt;
To start playback on a device without specifying the device name in the voice command, the module needs to know, which device should be used. Therefor it searches the attribute rhasspyChannels for suitable one. Devices in the actual or spoken room are preferred.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
play CNN on the radio in my office&lt;br /&gt;
switch to HBO&lt;br /&gt;
change channel on radio to BBC news&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[en.fhem:MediaChannels]&lt;br /&gt;
\[(play|switch to|change to)] ($de.fhem.MediaChannels){Channel} [($de.fhem.Device){Device}] [($de.fhem.Room){Room}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Channel&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetColor ===&lt;br /&gt;
Intent to change light colors&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Because of the multi-line settings, instead of configuring this intent with the attribute rhasspyMapping, a separate user-attribute [[#rhasspyColors]] is used.&lt;br /&gt;
&lt;br /&gt;
The content of the rhasspyColors uses the following format:&lt;br /&gt;
&amp;lt;code&amp;gt;Colorname=cmd&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Settings:&lt;br /&gt;
*&amp;lt;code&amp;gt;Colorname&amp;lt;/code&amp;gt; The name of the color you want to use in a voice-command&lt;br /&gt;
*&amp;lt;code&amp;gt;cmd&amp;lt;/code&amp;gt; The FHEM-command&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Mappings:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
red=rgb FF0000&lt;br /&gt;
green=rgb 00FF00&lt;br /&gt;
blue=rgb 0000FF&lt;br /&gt;
white=ct 3000&lt;br /&gt;
warm white=ct 2700&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
change light to green&lt;br /&gt;
lightstrip blue&lt;br /&gt;
color the light in the sleeping room white&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[en.fhem:SetColor]&lt;br /&gt;
\[change|color] $de.fhem.Device{Device} [$de.fhem.Room{Room}] $de.fhem.Color{Color}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags:&lt;br /&gt;
*&amp;lt;code&amp;gt;Color&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Device&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Optional tags&lt;br /&gt;
*&amp;lt;code&amp;gt;Room&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetColorGroup ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetScene ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GetTime ===&lt;br /&gt;
Intent um die Uhrzeit zu erfragen.&lt;br /&gt;
&lt;br /&gt;
Es werden keine Konfigurationen in FHEM benötigt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
wie spät ist es?&lt;br /&gt;
sag mir die uhrzeit&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:GetTime]&lt;br /&gt;
wie spät [ist es]&lt;br /&gt;
sag mir die uhrzeit&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GetDate ===&lt;br /&gt;
Intent um das aktuelle Datum zu erfragen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Keine FHEM Einstellungen nötig.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Satz:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
welcher tag ist heute&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:GetDate]&lt;br /&gt;
welcher tag ist heute&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetTimer ===&lt;br /&gt;
Intent to create a timer/countdown/alarm&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This intent creates an AT-command in FHEM with the given time and - currently - speaks the sentences &amp;quot;timer expired&amp;quot; when it has expired.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
No FHEM-settings needed&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
Set timer in bedroom to five minutes&lt;br /&gt;
Set countdown in the kitchen to two hours&lt;br /&gt;
set timer to five and a half hours&lt;br /&gt;
set alarm to 5 o&#039; clock&lt;br /&gt;
set timer to 3 hours and 20 minutes&lt;br /&gt;
set timer to 1 hour, 30 minutes and 15 seconds&lt;br /&gt;
stop the timer in bedroom&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentence:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetTimer]&lt;br /&gt;
labels=(alarm|teetimer|countdown|timer)&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in) [((1..60){Hour!int} (hour|hours))] [and] [((1..60){Min!int} (minute|minutes))] [and] [((1..60){Sec!int} (second|seconds))]&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in) (1..60){Hour!int} and (a quarter{Min:15}|a half{Min:30}|three quarters{Min:45}) (hour|hours)&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in) (1..60){Min!int} and (a quarter{Sec:15}|a half{Sec:30}|three quarters{Sec:45}) (minute|minutes)&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in) ((the fourth){Min:15}|(half a){Min:30}|(three fourth){Min:45}) (hour)&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in) ((the fourth){Min:15}|(half a){Min:30}|(three fourth){Min:45}) (minute)&lt;br /&gt;
\[&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}] (to|in|at) (1..24){Hourabs!int} [(1..60){Min!int}] o clock&lt;br /&gt;
&lt;br /&gt;
(cancel|remove|stop|delete){CancelTimer} [&amp;lt;labels&amp;gt;{Label}] [$de.fhem.Room{Room}]&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags to set a timer:&lt;br /&gt;
*&amp;lt;code&amp;gt;Label&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;Hour&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Hourabs&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Min&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;Sec&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Required tags to cancel a timer:&lt;br /&gt;
*&amp;lt;code&amp;gt;Label&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
rhasspyTweaks for Timer:&lt;br /&gt;
*&amp;lt;code&amp;gt;[[#attr-rhasspytweaks-timerlimits|timerLimits]]&amp;lt;/code&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;[[#attr-rhasspytweaks-timersounds|timerSounds]]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== SetMute ===&lt;br /&gt;
Intent to disable/enable the processing of intents on a specific siteId. Rhasspy will still listen to the wakeword but will not process any intents.&lt;br /&gt;
&lt;br /&gt;
This intents creates a Reading &amp;lt;code&amp;gt;mute_siteId&amp;lt;/code&amp;gt; for every siteId it get&#039;s a voice-command from.&lt;br /&gt;
&lt;br /&gt;
No FHEM-settings needed&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
good night&lt;br /&gt;
be quiet&lt;br /&gt;
good morning&lt;br /&gt;
make noise&lt;br /&gt;
start listening&lt;br /&gt;
stop listening&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetMute]&lt;br /&gt;
(good night|be quiet){Value:on}&lt;br /&gt;
(good morning|make noise){Value:off}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hinweis: Die Felder &amp;lt;code&amp;gt;{Value:on}&amp;lt;/code&amp;gt; bzw. &amp;lt;code&amp;gt;{Value:off}&amp;lt;/code&amp;gt; sind verpflichtend und &#039;&#039;case sensitive&#039;&#039;, der Wert &#039;&#039;on&#039;&#039; bzw. &#039;&#039;off&#039;&#039; ist in Englisch anzugeben!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ConfirmAction ===&lt;br /&gt;
Dies ist - wie die drei folgenden Intents &#039;&#039;CancelAction&#039;&#039;, &#039;&#039;ChoiceRoom&#039;&#039; und &#039;&#039;ChoiceDevice&#039;&#039; auch - ein Intent, der im Rahmen von Dialogen benötigt wird. Siehe dazu auch [[RHASSPY/Vertiefung#Dialoge|Vertiefung - Dialoge]].&lt;br /&gt;
Rückgabe ist zwingend &amp;lt;code&amp;gt;{Mode}&amp;lt;/code&amp;gt; mit dem Wert &#039;&#039;OK&#039;&#039;, alles andere wird so behandelt, als wäre der Intent &#039;&#039;CancelAction&#039;&#039; ausgewählt worden.&lt;br /&gt;
&lt;br /&gt;
=== CancelAction ===&lt;br /&gt;
Siehe &#039;&#039;ConfirmAction&#039;&#039;. Dieser Intent muss nicht zwingend existieren, es kann auch ein unpassender Rückgabewert in &#039;&#039;ConfirmAction&#039;&#039; angegeben werden, um die Abbruch-Routinen für Dialoge zu starten.&lt;br /&gt;
&lt;br /&gt;
=== ChoiceRoom ===&lt;br /&gt;
Siehe &#039;&#039;ConfirmAction&#039;&#039;. Dient im Rahmen von Dialogen der Auswahl eines Raums.&lt;br /&gt;
&lt;br /&gt;
=== ChoiceDevice ===&lt;br /&gt;
Siehe &#039;&#039;ConfirmAction&#039;&#039;. Dient im Rahmen von Dialogen der Auswahl eines Gerätes.&lt;br /&gt;
&lt;br /&gt;
=== ReSpeak ===&lt;br /&gt;
Wiederholt den letzten Satz, den Rhasspy gesprochen hat. Um genauer zu sein: Spricht den Inhalt des FHEM Readings &amp;lt;code&amp;gt;voiceResponse&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Keine Einstellungen in FHEM benötigt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Beispiel-Sätze:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
was hast du gesagt&lt;br /&gt;
kannst du das wiederholen&lt;br /&gt;
ich habe dich nicht verstanden&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example-Rhasspy-Sentences:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:ReSpeak]&lt;br /&gt;
was hast du gesagt&lt;br /&gt;
kannst du das [bitte] wiederholen&lt;br /&gt;
ich habe dich nicht verstanden&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Eigene Intents erstellen ==&lt;br /&gt;
Es ist auch möglich, eigene Intents zu erstellen, sollten die hier vorgestellten nicht reichen. Dafür gibt es zwei Wege: Für kleinere Intents können die Möglichkeiten von FHEMs [[99_myUtils_anlegen|99_myUtils.pm]] genutzt werden. Aufwendigere Intents können in jeweils eigenen Dateien abgelegt werden, die dann von RHASSPY ausgelesen werden.&lt;br /&gt;
=== Intents in 99_myUtils.pm ===&lt;br /&gt;
&lt;br /&gt;
Hier ein (veraltetes, siehe oben) Beispiel, mit dem die letzte &#039;&#039;voice response&#039;&#039; wiederholt werden kann.&lt;br /&gt;
&lt;br /&gt;
Ergänze deine 99_myUtils.pm mit folgender Funktion:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub Respeak(){&lt;br /&gt;
  #Credits to JensS&lt;br /&gt;
  my $name = &amp;quot;Rhasspy&amp;quot;; #Replace &amp;quot;Rhasspy&amp;quot; with the name of your RHASSPY-Device&lt;br /&gt;
  my $response = ReadingsVal($name,&amp;quot;voiceResponse&amp;quot;,&amp;quot;Ich kann mich leider nicht erinnern&amp;quot;);&lt;br /&gt;
  return $response;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ergänze im Attribut &#039;&#039;rhasspyIntents&#039;&#039; folgende Zeile (je Intent muss eine eigene Zeile verwendet werden):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
Respeak=Respeak()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ergänze einen neuen Intent in deinen &#039;&#039;sentence.ini&#039;&#039; an der Rhasspy base:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:Respeak]&lt;br /&gt;
was hast du gesagt&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Intents in eigenen Dateien ===&lt;br /&gt;
Beispiele: https://github.com/fhem/fhem-rhasspy/blob/main/FHEM/99_RHASSPY_Utils_Demo.pm&lt;br /&gt;
&lt;br /&gt;
==== Beispiel: Raumwechsel ====&lt;br /&gt;
Erforderlichen Code in das Modulverzeichnis holen und laden: &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;{ Svn_GetFile(&#039;contrib/RHASSPY/99_RHASSPY_Utils_siteId2room.pm&#039;, &#039;FHEM/99_RHASSPY_Utils_siteId2room.pm&#039;,sub(){ RHASSPY_Utils_siteId2room_Initialize() }) }&amp;lt;/syntaxhighlight&amp;gt;Ergänze im Attribut &#039;&#039;rhasspyIntents&#039;&#039; folgende Zeile (je Intent muss eine eigene Zeile verwendet werden):&lt;br /&gt;
&amp;lt;syntaxhighlight  lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
siteId2room=RHASSPY::siteId2room::siteId2room(NAME,DATA)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Ergänze einen neuen Intent in deinen &#039;&#039;sentence.ini&#039;&#039; an der Rhasspy base:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:siteId2room]&lt;br /&gt;
( Ortswechsel  | begib dich ) ( ins | in den ) $de.fhem.Room{Room}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tipps &amp;amp; Tricks ==&lt;br /&gt;
===Custom Converter für reelle Zahlen===&lt;br /&gt;
Rhasspy is (currently) not able to recognize spoken Real numbers (e.g. ten point five) as numbers. Instead it interprets them as two numbers and &amp;quot;point&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
To use Real numbers correctly, you have to create a [https://rhasspy.readthedocs.io/en/latest/training/#converters custom converter] and use this in your sentences.&lt;br /&gt;
&lt;br /&gt;
To do this, create a file under &amp;lt;code&amp;gt;&amp;lt;profile&amp;gt;/converters&amp;lt;/code&amp;gt;, name it as you wish and make it executable.&lt;br /&gt;
E.g.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
touch .config/rhasspy/profile/en/converters/customFloat&lt;br /&gt;
chmod +x .config/rhasspy/profile/en/converters/customFloat&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then fill it with the following example-code:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env python3&lt;br /&gt;
import sys&lt;br /&gt;
import json&lt;br /&gt;
&lt;br /&gt;
# [22, &amp;quot;.&amp;quot;, 5]&lt;br /&gt;
args = json.load(sys.stdin)&lt;br /&gt;
&lt;br /&gt;
# 22.5&lt;br /&gt;
num = &amp;quot;&amp;quot;.join(str(s).strip() for s in args)&lt;br /&gt;
&lt;br /&gt;
print(num)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Restart Rhasspy and afterwards you can use your custom-converter in your sentences.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[SetHeating]&lt;br /&gt;
set heating [to] (0..30 [point:. 0..99]){Value!customFloat}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Rhasspy speaks actual state of device after switching it===&lt;br /&gt;
JensS wrote a short script to let Rhasspy speak the actual state of a FHEM-device after switching it with a voice-command.&lt;br /&gt;
Add the following to your 99_myUtils.pm&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
sub ResponseOnOff($){&lt;br /&gt;
  my ($dev) = @_;&lt;br /&gt;
  my $room;&lt;br /&gt;
  my $state = lc(ReadingsVal($dev,&amp;quot;state&amp;quot;,&amp;quot;in unknown state&amp;quot;));&lt;br /&gt;
  my $name = (split(/,/,AttrVal($dev,&amp;quot;rhasspyName&amp;quot;,&amp;quot;error&amp;quot;)))[0];&lt;br /&gt;
  if (AttrVal($dev,&amp;quot;rhasspyRoom&amp;quot;,&amp;quot;&amp;quot;)){$room = &amp;quot; in &amp;quot;.(split(/,/,AttrVal($dev,&amp;quot;rhasspyRoom&amp;quot;,&amp;quot;&amp;quot;)))[0]};&lt;br /&gt;
  $state=~s/.*on/turned on/;&lt;br /&gt;
  $state=~s/.*off/turned off/;&lt;br /&gt;
  return &amp;quot;Ok - &amp;quot;.$name.$room.&amp;quot; is now &amp;quot;.$state&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
and add a response to the SetOnOff-Mapping of a device&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
SetOnOff:cmdOn=on,cmdOff=off,response={ResponseOnOff($DEVICE)}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [https://github.com/rhasspy/rhasspy Rhasspy auf Github]&lt;br /&gt;
* [https://rhasspy.readthedocs.io/en/latest/ offizielle Rhasspy Doku-Seite]&lt;br /&gt;
* [https://community.rhasspy.org/ Offizielles Rhasspy Forum]&lt;br /&gt;
* [https://github.com/fhem/fhem-rhasspy fhem-rhasspy Modul auf GitHub]&lt;br /&gt;
* [https://github.com/Romkabouter/ESP32-Rhasspy-Satellite ESP32-basierte Hardware als Satelliten]&lt;br /&gt;
* [https://github.com/razzo04/rhasspy-mobile-app App für Android-Satelliten]&lt;br /&gt;
* [https://www.youtube.com/watch?v=sWVl0ZoXZEo Video zu sentences.ini]&lt;br /&gt;
[[Kategorie:Sprachsteuerung]]&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
	<entry>
		<id>http://wiki.fhem.de/w/index.php?title=RHASSPY/Schnellstart&amp;diff=36513</id>
		<title>RHASSPY/Schnellstart</title>
		<link rel="alternate" type="text/html" href="http://wiki.fhem.de/w/index.php?title=RHASSPY/Schnellstart&amp;diff=36513"/>
		<updated>2021-12-04T19:18:07Z</updated>

		<summary type="html">&lt;p&gt;Drhirn: Rhasspys Mosquitto standardmäßig läuft auf Port 12183&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:Rhasspy Webinterface.png|thumb|right|Das Rhasspy-Webinterface nach erfolgreicher Installation und Aufruf des ersten Intents (GetTime)]]&lt;br /&gt;
Die folgende Kurzanleitung soll den Einstieg erleichtern. Es ist dabei wichtig, jeden der Schritte vollständig abgeschlossen zu haben, bevor mit dem nächsten begonnen wird!&lt;br /&gt;
&lt;br /&gt;
Voraussetzung für diese Anleitung ist, dass Rhasspy bereits funktionsfähig ist. Dazu bitte der Anleitung in der [https://rhasspy.readthedocs.io/en/latest/#getting-started offiziellen Dokumentation] folgen. Empfohlen wird, Rhasspy als [https://www.docker.com/ Docker Container] zu installieren. Und zwar aus folgenden Gründen:&lt;br /&gt;
* Alle Software-Abhängigkeiten sind aufgelöst&lt;br /&gt;
* Es kommt zu keinen Konflikten mit Abhängigkeiten anderer Anwendungen (Python-Version, Paket-Versionen, ...)&lt;br /&gt;
* Wird der Container wieder gelöscht, ist Rhasspy vollständig vom System entfernt&lt;br /&gt;
Soll Docker verwendet werden, finden sich am [[#Anhang|Ende dieser Anleitung]] zwei Docker-Compose Dateien für den schnellen Einstieg.&lt;br /&gt;
&lt;br /&gt;
Die Vorbereitung ist abgeschlossen, wenn im [https://rhasspy.readthedocs.io/en/latest/#web-interface Web-Interface von Rhasspy] der gesprochene Testsatz &#039;&#039;&#039;&#039;&#039;wie spät ist es&#039;&#039;&#039;&#039;&#039; erkannt wird und links als erkannter Intent &#039;&#039;&#039;&#039;&#039;GetTime&#039;&#039;&#039;&#039;&#039; angezeigt wird.&lt;br /&gt;
&lt;br /&gt;
==Installation FHEM Modul==&lt;br /&gt;
[[File:Rhasspy03.png|thumb|right|Installation/Update des RHASSPY Moduls via Kommando-Feld]]&lt;br /&gt;
Das RHASSPY-Modul kann ganz einfach mit einem einzelnen Befehl, der in die FHEM-Kommandozeile eingetragen werden muss, installiert werden:&lt;br /&gt;
&lt;br /&gt;
 { Svn_GetFile(&#039;contrib/RHASSPY/10_RHASSPY.pm&#039;, &#039;FHEM/10_RHASSPY.pm&#039;) }&lt;br /&gt;
&lt;br /&gt;
Danach muss FHEM neu gestartet werden.&lt;br /&gt;
&lt;br /&gt;
==Einrichtung des MQTT2_CLIENT==&lt;br /&gt;
[[File:Rhasspy02.png|right|thumb|Ein erfolgreich mit Rhasspy verbundenes MQTT2_CLIENT Device]]&lt;br /&gt;
Rhasspy kommuniziert hauptsächlich über das [[MQTT]]-Protokoll. Und zwar sowohl Rhasspy-intern, wie auch mit FHEM. Da dies auch für die übertragene Sprache und Audio-Dateien gilt und es daher zu sehr viel MQTT-Verkehr kommt, sollte der Rhasspy-interne MQTT-Server verwendet und die für FHEM relevanten Daten über einen [[MQTT2_CLIENT]] bezogen werden.&lt;br /&gt;
&lt;br /&gt;
Dieses Beispiel geht davon aus, dass Rhasspy auf dem selben Gerät installiert ist, auf dem auch FHEM läuft.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
defmod rhasspyMQTT2 MQTT2_CLIENT localhost:12183&lt;br /&gt;
attr rhasspyMQTT2 clientOrder RHASSPY&lt;br /&gt;
attr rhasspyMQTT2 subscriptions setByTheProgram&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Läuft Rhasspy auf einem anderen Server und/oder wird ein anderer Port verwendet, sind die passenden Daten im obigen &#039;&#039;defmod&#039;&#039; entsprechend anzupassen. Typischerweise ist der Rhasspy-interne MQTT-Server eines extern laufenden Rhasspy unter der Portnummer 12183 zu erreichen, die Definition wäre dann also&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
defmod rhasspyMQTT2 MQTT2_CLIENT &amp;lt;IP-Adresse&amp;gt;:12183&lt;br /&gt;
attr rhasspyMQTT2 clientOrder RHASSPY&lt;br /&gt;
attr rhasspyMQTT2 subscriptions setByTheProgram&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hat alles funktioniert, steht &#039;&#039;&#039;opened&#039;&#039;&#039; im &#039;&#039;STATE&#039;&#039; dieses Devices.&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Define eines RHASSPY Devices ==&lt;br /&gt;
Läuft der Rhasspy-Dienst auf derselben Maschine mit den Standardeinstellungen, genügt für ein erstes Kennenlernen:&lt;br /&gt;
 define rhasspy RHASSPY&lt;br /&gt;
Für einen entfernten Rhasspy-Dienst muss angeben werden, wo dessen &#039;&#039;&#039;Web-Interface&#039;&#039;&#039; zu erreichen ist:&lt;br /&gt;
 defmod rhasspy RHASSPY baseUrl=http://192.168.1.210:12101&lt;br /&gt;
&lt;br /&gt;
Dieser Schritt war erfolgreich, wenn &lt;br /&gt;
* im Device rhasspy ein Reading &#039;&#039;&#039;intents&#039;&#039;&#039; vorhanden ist, das z.B. den Wert &#039;&#039;GetTime&#039;&#039; enthält, und &lt;br /&gt;
* &#039;&#039;&#039;STATE&#039;&#039;&#039; dieses Devices auf &#039;&#039;online&#039;&#039; gegangen ist.&lt;br /&gt;
&lt;br /&gt;
==Spracheinstellungen==&lt;br /&gt;
===Basissprache===&lt;br /&gt;
{{Randnotiz|RNTyp=Info|RNText=Wird die Sprache im Device global nach Definition des RHASSPY-Devices geändert, kann es notwendig sein, die DEF des RHASSPY-Devices einmal ohne Änderungen zu bearbeiten (z.B. ein Leerzeichen anfügen).}}&lt;br /&gt;
[[File:Rhasspy05.png|thumb|rhasspy mit deutscher Spracheinstellung]]&lt;br /&gt;
In diesem Beispiel soll deutsch mit dem Sprachassistenten gesprochen werden. Das bedeutet&lt;br /&gt;
# Rhasspy - also die Anwendung im Docker_Container - muss ein deutsches Profil verwenden&lt;br /&gt;
# rhasspy - also das FHEM-Device - muss auf die deutsche Sprache eingestellt sein&lt;br /&gt;
# Eine deutsche [[#Sprachdatei|Sprachdatei]] muss installiert sein&lt;br /&gt;
&lt;br /&gt;
Welche Sprache das Device rhasspy verwendet, ist am &#039;&#039;&#039;Internal&#039;&#039;&#039; &#039;&#039;LANGUAGE&#039;&#039; zu erkennen.&lt;br /&gt;
&lt;br /&gt;
Sollte dieses Internal nicht &#039;&#039;&#039;de&#039;&#039;&#039; anzeigen, gibt es zwei Möglichkeiten, dies zu ändern:&lt;br /&gt;
# im FHEM-Device &#039;&#039;&#039;global&#039;&#039;&#039; wird das  Attribut &#039;&#039;language&#039;&#039; auf &#039;&#039;DE&#039;&#039; eingestellt oder&lt;br /&gt;
# die Definition des rhasspy-Devices um &#039;&#039;language=de&#039;&#039; ergänzt.&lt;br /&gt;
&lt;br /&gt;
  defmod rhasspy RHASSPY language=de&lt;br /&gt;
&lt;br /&gt;
===Sprachdatei===&lt;br /&gt;
Das Modul RHASSPY enthält einige vorgefertigte Antwortsätze für diverse Situationen. Um diese von Englisch auf Deutsch umzustellen, wird eine zusätzliche (Muster-) Sprachdatei benötigt, die man mit folgendem Befehl erhält:&lt;br /&gt;
 { Svn_GetFile(&#039;contrib/RHASSPY/rhasspy-de.cfg&#039;, &#039;./rhasspy-de.cfg&#039;) }&lt;br /&gt;
&lt;br /&gt;
Ergänzend muss dem Device rhasspy mitgeteilt werden, wo diese zu finden ist: &lt;br /&gt;
 attr rhasspy languageFile ./rhasspy-de.cfg&lt;br /&gt;
&lt;br /&gt;
Dieser Schritt war erfolgreich, wenn der Befehl &amp;lt;code&amp;gt;list Rhasspy&amp;lt;/code&amp;gt; einen Abschnitt &#039;&#039;lng&#039;&#039; enthält, der deutsche Antworten auflistet.&lt;br /&gt;
&lt;br /&gt;
== Erste Interaktion ==&lt;br /&gt;
[[File:Rhasspy06.png|thumb|Anpassung eines erstens Intents nach der Schnellstart-Anleitung]]&lt;br /&gt;
Um dem Sprachassistenten jetzt eine Antwort auf eine Frage zu entlocken, muss zuerst im Webinterface von Rhasspy - also in der Anwendung im Docker-Container - im Menüpunkt [https://rhasspy.readthedocs.io/en/latest/tutorials/#training Sentences] ein Intent erstellt werden. Für diese Schnellstart-Anleitung wird aber einfach der standardmäßig in Rhasspy vorhandene Intent &#039;&#039;[GetTime]&#039;&#039; verwendet. Um diesen aber benutzen zu können, muss er vorher umbenannt werden. Jede Instanz des RHASSPY-Moduls reagiert nur auf Intents, die &amp;quot;für sie&amp;quot; bestimmt und daher entsprechend gekennzeichnet sind. Diese Kennungzeichnung besteht aus:&lt;br /&gt;
# dem &#039;&#039;&#039;&#039;&#039;language&#039;&#039;-Kürzel&#039;&#039;&#039; (z.B. &amp;lt;code&amp;gt;de&amp;lt;/code&amp;gt;),&lt;br /&gt;
# der &#039;&#039;&#039;&#039;&#039;fhemId&#039;&#039;&#039;&#039;&#039; (z.B. &amp;lt;code&amp;gt;fhem&amp;lt;/code&amp;gt;) und&lt;br /&gt;
# dem &#039;&#039;&#039;Intent-Namen&#039;&#039;&#039; (z.B. &amp;lt;code&amp;gt;GetTime&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Der Name des Intents ist daher in der &#039;&#039;sentences.ini&#039;&#039; wie folgt zu ändern:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:GetTime]&lt;br /&gt;
wie spät ist es&lt;br /&gt;
sag mir die uhrzeit&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Jetzt kann der Sprachassistent nach der aktuellen Uhrzeit gefragt werden. Ist alles richtig konfiguriert, wird er diese Frage auf deutsch beantworten und die Readings des Moduls werden mit entsprechenden Werten befüllt.&lt;br /&gt;
&lt;br /&gt;
==Ein Gerät mit Rhasspy verbinden==&lt;br /&gt;
[[File:Rhasspy08.png|thumb|Erfolgreich befüllter Slot mit dem Alias der Lampe]]&lt;br /&gt;
[[File:Rhasspy07.png|thumb|Erfolgreich erstellte Helper für eine Lampe im RHASSPY Modul]]&lt;br /&gt;
Wenn nach dieser Anleitung vorgegangen wurde, ist das Modul so konfiguriert, dass es Rhasspy alle FHEM-Devices bekannt macht, bei denen das Attribut &#039;&#039;&#039;genericDeviceType&#039;&#039;&#039; definiert ist.&lt;br /&gt;
&lt;br /&gt;
Für die Verbindung eines FHEM-Devices mit Rhasspy sind also folgende Schritte auszuführen:&lt;br /&gt;
# &#039;&#039;&#039;genericDeviceType&#039;&#039;&#039; Attribut bei einem Device setzen (z.B. &#039;&#039;switch&#039;&#039;)&lt;br /&gt;
# einen &amp;quot;sprechbaren&amp;quot; Namen im Attribut &#039;&#039;&#039;alias&#039;&#039;&#039; vergeben&lt;br /&gt;
# &amp;lt;code&amp;gt;set rhasspy update devicemap&amp;lt;/code&amp;gt; ausführen, um das Device Rhasspy bekannt zu machen&lt;br /&gt;
&lt;br /&gt;
Anhand einer Lampe &amp;quot;Office&amp;quot;, die sich nur ein- und ausschalten lässt, könnte das z.B. so aussehen:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
attr Office genericDeviceType switch&lt;br /&gt;
attr Office alias Licht&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der &#039;&#039;genericDeviceType&#039;&#039; &#039;&#039;&#039;switch&#039;&#039;&#039; gibt für ein Gerät vor, dass es sich nur ein- und ausschalten lässt. Beim Typ &#039;&#039;&#039;light&#039;&#039;&#039; z.B. könnte man auch noch die Helligkeit und die Farbe regulieren.&lt;br /&gt;
Der &#039;&#039;alias&#039;&#039; &#039;&#039;&#039;Licht&#039;&#039;&#039; bewirkt, dass in Zukunft einfach &amp;quot;Licht aus&amp;quot; oder &amp;quot;Licht an&amp;quot; gesagt werden kann. Dazu aber später mehr.&lt;br /&gt;
&lt;br /&gt;
Die Lampe ist somit fertig vorbereitet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Damit Rhasspy auch von diesem Gerät erfährt, muss FHEM ihm davon erzählen. Das passiert, in dem folgender Befehl ausgeführt wird:&lt;br /&gt;
 set rhasspy update devicemap&lt;br /&gt;
Darauf hin werden mehrere Aktionen durchgeführt:&lt;br /&gt;
* Es werden in Rhasspy Slots erstellt, die später in Intents verwenden werden können&lt;br /&gt;
* Diese Slots werden mit den Daten befüllt, die in FHEM für die Verwendung in Rhasspy konfiguriert wurden. In diesem Fall nur der Alias dieser Lampe&lt;br /&gt;
* Ein Training von Rhasspy wird angestoßen, damit Rhasspy das Gerät in gesprochenen Sätzen erkennt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ob alles funktioniert hat, lässt sich an drei Dingen erkennen:&lt;br /&gt;
# Es gibt neue Slots in Rhasspy bzw. bereits vorhandene wurden mit neuen Werten ergänzt&lt;br /&gt;
# Ein &amp;lt;code&amp;gt;list rhasspy&amp;lt;/code&amp;gt; enthält den Helper &#039;&#039;&#039;devicemap&#039;&#039;&#039; mit den konfigurierten Geräten und dessen Steuermöglichkeiten (&#039;&#039;intents&#039;&#039;)&lt;br /&gt;
# In den Readings &#039;&#039;udpateSlots&#039;&#039; und &#039;&#039;training&#039;&#039; des Moduls ist kein Fehler zu erkennen (unter Umständen die Seite im Browser aktualisieren, wenn die Readings noch nicht vorhanden sind)&lt;br /&gt;
&lt;br /&gt;
==Einen ersten Intent erstellen==&lt;br /&gt;
{{Randnotiz|RNTyp=Info|RNText=Dieses Beispiel enthält bereits einige Sprech-Alternativen und optionale Elemente. Die vorhandenen Möglichkeiten sind zum Einen der offiziellen Dokumentation zu entnehmen, zur Vertiefung gibt es in den Links unten ein sehr informatives Video.}}&lt;br /&gt;
[[File:Rhasspy09.png|thumb|Ein erfolgreich von RHASSPY empfangener und umgesetzter Sprachbefehl]]&lt;br /&gt;
Um die konfigurierte Lampe schlussendlich auch steuern zu können, muss Rhasspy noch wissen, was nach einem erkannten Sprachbefehl anfangen soll. Dazu werden in Rhasspy Sentences/Intents erstellt. Im Falle dieser Lampe, reicht ein einfacher SetOnOff-Intent. Sie kann ja nicht mehr.&lt;br /&gt;
&lt;br /&gt;
Da der Intent aber potentiell für mehrere Geräte dienen können soll, wird es etwas komplizierter, als beim &#039;&#039;GetTime&#039;&#039; Intent. Da aber vom Modul schon passende Slots erstellt wurden, können wir diese in den Sätzen verwenden, anstatt einen eigenen Satz für jedes Gerät schreiben zu müssen. Zusätzlich müssen wir aber &#039;&#039;Tags&#039;&#039; verwenden, damit das Modul dann unterscheiden kann, ob ein von Rhasspy geliefertes Wort ein Gerät, ein Raum oder ein Nummernwert ist.&lt;br /&gt;
&lt;br /&gt;
Ein ganz einfacher Intent, um die Lampe ein- und ausschalten zu können, kann z.B. so aussehen:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ini&amp;quot;&amp;gt;&lt;br /&gt;
[de.fhem:SetOnOff]&lt;br /&gt;
schalte das $de.fhem.Device-SetOnOff{Device} ( an{Value:on} | aus{Value:off})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Kurz umrissen bedeuten die Teile des Satzes:&lt;br /&gt;
* &#039;&#039;&#039;$de.fhem.Device-SetOnOff&#039;&#039;&#039; ist der Slot, der die Geräte enthält, die mit diesem Intent gesteuert werden sollen. Das Dollarzeichen am Anfang des Slots wird gerne vergessen, darauf also besonders gut aufpassen&lt;br /&gt;
* &#039;&#039;&#039;{Device}&#039;&#039;&#039; ist ein Tag, der dem FHEM-Modul und Rhasspy verrät, dass es sich bei diesem Wort um ein Device handelt. Wichtig bei Tags, die in Verbindung mit diesem Modul verwendet werden ist, dass sie &#039;&#039;&#039;immer&#039;&#039;&#039; mit einem Großbuchstaben beginnen!&lt;br /&gt;
* &#039;&#039;&#039;( ... | ... )&#039;&#039;&#039; ist eine Gruppe. Wobei die runden Klammern eine Gruppe beschreiben, die einzelnen Mitglieder dieser Gruppe werden durch die &amp;quot;Pipe&amp;quot; getrennt. In diesem konkreten Fall bedeutet es, der Wert kann &amp;quot;an&amp;quot; ODER &amp;quot;aus&amp;quot; sein&lt;br /&gt;
*&#039;&#039;&#039;{Value:on}&#039;&#039;&#039;/&#039;&#039;&#039;{Value:off}&#039;&#039;&#039; ist wieder ein Tag. Dieser gibt an, dass es sich beim übergebenen Wort um einen Wert handelt. Da das Modul aber die deutschen Wörter &amp;quot;an&amp;quot; und &amp;quot;aus&amp;quot; nicht versteht, müssen hier Synonyme verwendet werden. Das sind jeweils die Werte hinter dem Doppelpunkt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Wichtig:&#039;&#039;&#039; Da mit Erstellen des ersten Intents wieder Änderungen an der Konfiguration vorgenommen wurden, muss jetzt wieder ein &amp;lt;code&amp;gt;set rhasspy update all&amp;lt;/code&amp;gt; ausgeführt werden. In diesem Fall, damit das Modul vom neuen Intent erfährt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ist man dieser Schnellstart-Anleitung gefolgt, können aus diesem Satz mit der vorhandenen Lampe jetzt zwei gesprochene Sätze gebildet werden:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
schalte das licht an&lt;br /&gt;
schalte das licht aus&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Infos, die daraus resultierend nach einem Sprachbefehl &amp;quot;schalte das licht an&amp;quot; im FHEM-Modul ankommen sind dann unter anderem:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
&amp;quot;intent&amp;quot;:&amp;quot;SetOnOff&amp;quot;&lt;br /&gt;
&amp;quot;Device&amp;quot;:&amp;quot;licht&amp;quot;&lt;br /&gt;
&amp;quot;Value&amp;quot;:&amp;quot;on&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Schlusswort==&lt;br /&gt;
Sind alle Punkte dieser Schnellstart-Anleitung erfolgreich abgeschlossen, kann damit begonnen werden RHASSPY auf die eigenen Bedürfnisse anzupassen und weitere Geräte damit zu steuern. Alle Informationen dazu finden sich auf der Hauptseite von [[RHASSPY]].&lt;br /&gt;
&lt;br /&gt;
==Anhang==&lt;br /&gt;
===Docker-Compose File - Base===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;yaml&amp;quot;&amp;gt;&lt;br /&gt;
version: &#039;3&#039;&lt;br /&gt;
&lt;br /&gt;
services:&lt;br /&gt;
    rhasspy:&lt;br /&gt;
        image: &amp;quot;rhasspy/rhasspy&amp;quot;&lt;br /&gt;
        container_name: rhasspy&lt;br /&gt;
        restart: unless-stopped&lt;br /&gt;
        volumes:&lt;br /&gt;
            - &amp;quot;.config/rhasspy/profiles:/profiles&amp;quot;&lt;br /&gt;
            - /etc/timezone:/etc/timezone:ro&lt;br /&gt;
        ports:&lt;br /&gt;
            - &amp;quot;12101:12101&amp;quot;&lt;br /&gt;
            - &amp;quot;12183:12183&amp;quot;&lt;br /&gt;
        command: --user-profiles /profiles --profile de&lt;br /&gt;
        environment:&lt;br /&gt;
          - TZ=Europe/Berlin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Docker-Compose File - Satellite===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;yaml&amp;quot;&amp;gt;&lt;br /&gt;
version: &#039;3&#039;&lt;br /&gt;
&lt;br /&gt;
services:&lt;br /&gt;
    rhasspy:&lt;br /&gt;
        image: &amp;quot;rhasspy/rhasspy&amp;quot;&lt;br /&gt;
        container_name: rhasspy&lt;br /&gt;
        restart: unless-stopped&lt;br /&gt;
        volumes:&lt;br /&gt;
            - &amp;quot;.config/rhasspy/profiles:/profiles&amp;quot;&lt;br /&gt;
            - &amp;quot;/etc/localtime:/etc/localtime:ro&amp;quot;&lt;br /&gt;
            - &amp;quot;/etc/asound.conf:/etc/asound.conf&amp;quot;&lt;br /&gt;
        ports:&lt;br /&gt;
            - &amp;quot;12101:12101&amp;quot;&lt;br /&gt;
        command: --user-profiles /profiles --profile de&lt;br /&gt;
        devices:&lt;br /&gt;
          - &amp;quot;/dev/snd:/dev/snd&amp;quot;&lt;br /&gt;
        ipc: host&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* [https://github.com/rhasspy/rhasspy Rhasspy auf Github]&lt;br /&gt;
* [https://rhasspy.readthedocs.io/en/latest/ offizielle Rhasspy Doku-Seite]&lt;br /&gt;
* [https://community.rhasspy.org/ Offizielles Rhasspy Forum]&lt;br /&gt;
* [https://github.com/fhem/fhem-rhasspy fhem-rhasspy Modul auf GitHub]&lt;br /&gt;
* [https://github.com/Romkabouter/ESP32-Rhasspy-Satellite ESP32-basierte Hardware als Satelliten]&lt;br /&gt;
* [https://github.com/razzo04/rhasspy-mobile-app App für Adroid-Satelliten]&lt;br /&gt;
* [https://www.youtube.com/watch?v=sWVl0ZoXZEo Video zu sentences.ini]&lt;br /&gt;
&lt;br /&gt;
[[Category:HOWTOS]]&lt;br /&gt;
[[Category:Sprachsteuerung]]&lt;/div&gt;</summary>
		<author><name>Drhirn</name></author>
	</entry>
</feed>