Talk2Fhem

Aus FHEMWiki
Talk2Fhem
Zweck / Funktion
Das Modul stellt eine Verbindung zwischen natürlicher Sprache und FHEM Befehlen her
Allgemein
Typ undefiniert
Details
Dokumentation ModUndef
Support (Forum) Unterstützende Dienste
Modulname 39_Talk2Fhem.pm
Ersteller Oliver Georgi
Wichtig: sofern vorhanden, gilt im Zweifel immer die (englische) Beschreibung in der commandref!




Clock - Under Construction.svg An dieser Seite wird momentan noch gearbeitet.



Diese Seite beschreibt die Funktionsweise und Konfiguration des Moduls 39_Talk2Fhem.pm

Voraussetzungen

Es ist sehr zu empfehlen, für die Konfiguration des Moduls, im Webfrontend von FHEM die Syntaxhervorhebung zu aktivieren. Die Aktivierung des erweiterten Editors ist hier Konfiguration#Syntaxhervorhebung beschrieben.

Kenntnisse im Bereich Regulärer Ausdrücke (RegExp) in Perl sind hilfreich, aber nicht zwingend erforderlich. Ein kurzer Einstieg kann hier eingesehen werden. Modul_Talk2Fhem#RegExp_Crashkurs

Allgemeines

Das Modul Talk2Fhem stellt eine Verbindung zwischen natürlicher Sprache und FHEM Befehlen her. Es ist ein überaus flexibles und relativ einfach zu konfigurierendes Script mit dem man sehr natürlich kommunizieren kann. Die Konfiguration erfolgt dabei über das FHEM Webfrontend.

Bei der Analyse der Sprachbefehle erfolgt keine grammatikalische Analyse, sondern es wird auf definierte Schlüsselwörter reagiert. Das Modul erkennt von sich aus diverse Zeit- und Datumsangaben und löst bei Bedarf zu diesen Zeiten die FHEM Kommandos aus.

Funktionsweise

Die Zerlegung des Sprachbefehls erfolgt in mehreren Schritten.

  1. Aufteilen des Sprachbefehls in einzelne Kommandos anhand des Wortes UND
  2. Erkennen von Zeit- und Datumsangaben und entfernen für die weitere Verarbeitung
  3. Entfernung unnötiger Wörter
  4. Vergleich mit den definierten Schlüsselwörtern
  5. Konvertieren in ein FHEM Kommando
  6. Zeitgebundenes auslösen des FHEM Kommandos

Zeitenerkennung

Die Zeit- und Datum Eingabe kann auf viele verschiedene Arten erfolgen.
Die Datumerkennung umfasst folgende Phrasen:

  • morgen, übermorgen
  • in ... Wochen, Monat, Jahr
  • nächste Woche, Monat, Jahr
  • Wochentage
  • in ... Tagen
  • am DATUM

Die Zeiterkennung umfasst folgende Phrasen:

  • in,nach ... stunden,minuten,sekunden
  • um ... (Uhr) (...)
  • heute - entspricht 12:00
  • früh - entspricht 9 Uhr
  • abend - entspricht 18 Uhr
  • nachmittag - entspricht 16 Uhr
  • vormittag - entspricht 10:30 Uhr
  • mittag - entspricht 12 Uhr
  • gleich - entspricht 5 Minuten
  • nachher - entspricht 30 Minuten
  • später - entspricht 1 Stunde
  • jetzt
  • sofort

Datum und Zeitangaben können natürlich kombiniert werden.
Wird eine Zeit erfolgreich erkannt erfolgt die Ausführung des FHEM-Kommandos über das Modul at. Hier wird ein at Eregnis angelegt welches den Namen at_<name>_ erhält.

Bei mehreren Kommandos über das Schlüsselwort UND wirkt sich der Zeitpunkt des ersten Kommandos auch auf das zweite aus und dritte usw.

Schalte die Heizung um 20 Uhr aus und mache die Rollläden runter

Das erfolgt dann beides um 20 Uhr.

Hat das zweite Kommando ebenfalls eine Zeitphrase wird diese Zeit angenommen.

schalte die Heizung heute Abend ab und mache die Rollläden jetzt runter

Zeitenmodifikation

Wie oben gesehen wird der Zeitpunkt des ersten Kommandos vor dem "und" auch für das zweite nach dem "und" angenommen. Vorausgesetzt sie wird beim 2. Kommando nicht durch eine eigenständige Zeit (hier "jetzt") überschrieben. Wenn man die Zeit des zweiten Kommandos, relativ zum ersten setzen möchte, kann dies mit den Schlüsselwörtern dann, danach oder wieder formulieren.

Fahre um 14 Uhr die Rollläden an der Terrasse runter und schalte dann in 2 Minuten die Bewässerung an

oder

Mach am Freitag um 5 Uhr die Heizung aus und in einer Woche wieder an

Es lässt sich ein Offset auf den ermittelten Zeitpukt hinzufügen, um den Zeitpunkt modifizieren zu können.
Beispiel

dusche\S?$ = (offset=>-3600, cmd=>'set d_log bad warm')

Der Sprachbefehl

ich will um 18:30 Uhr duschen

Legt folgendes at Ergnis an

define at_assi_1513096200 at 2017-12-12T17:30:00 set d_log bad warm

Installation

Solange das Modul noch nicht offiziell aufgenommen wurde, muss die Datei 39_Talk2Fhem.pm manuell in das Verzeichnis FHEM/ kopiert werden. Siehe Forumsbeitrag. [1]

Definition

define talk Talk2Fhem

Zum testen der Konfiguration ist es Ratsam vorerst das Attribut disable auf 1 zu setzen. Hierbei wird die Auslösung der FHEM Kommandos unterdrückt.

attr talk disable 1

Anwendung

Der Sprachbefehl wird über das Kommando "set" an das Modul geleitet.

set talk Guten Morgen liebes Zuhause

Readings

Im Reading set steht der letzte gesendete Sprachbefehl. Im Reading cmds steht das letzte ausgeführte FHEM-Kommando.

Die Antworten und Fehler werden in den Readings answers und err ausgegben. Diese können dann über ein notify weiterverarbeitet werden.

Beispiel

Erstellen eines Notify

define n_talk notify talk:.* {}

Folgendes in der Definition von n_talk einfügen

talk:.* {
# Sende die Antwort per Telegram und gebe es über das GoogleHome aus
	if ($EVENT =~ s/^answers: //) {
		fhem("set telegram _msg \@USER $EVENT");
		fhem("set d_googlespeak $EVENT");	
	}

# Schicke den Fehler per Telegram und sag am GoogleHome das es nicht geklappt hat.
	if ($EVENT =~ s/^err: //) {
		fhem("set telbot _msg \@Oliver $EVENT");
		my @a = ("Das hat leider nicht geklappt", "Es gab leider einen Fehler", "Es tut mir leid. Das hat nicht funktioniert.", "Es ist leider zu einem Fehler gekommen","Könntest du das vielleicht nochmal anders sagen", "Mhhh, das kann ich so nicht verstehen");
		fhem("set d_googlespeak $a[int(rand($#a))]");
	} 

# Schick mir alle ausgeführten Befehle als Telegram

	if ($EVENT =~ s/^cmds: //) {
		fhem("set telbot _msg \@USER $EVENT");
	} 

}

Konfiguration

Die Konfiguration des Moduls wird hauptsächlich über die Definition (DEF) vorgenommen. Eine Konfiguration beginnt immer mit der Definition der gesuchten Schlüsselwörtern gefolgt von einem Gleichheitszeichen (siehe Randnotiz). Diese werden Anhand von Regulären Ausdrücken (RegExp) beschrieben. Also z.B.:

garage auf =

Das bededutet, sobald die Wörter in der Reihenfolge "garage" und "auf" erkannt werden, wird der Kommandoteil der Konfiguration ausgeführt. Groß- und Kleinschreibung wird grundsätzlich ignoriert.

Info green.pngWichtig

Vor und nach dem Gleichheitszeichen muss mindestens ein Trennzeichen vorhanden sein

  • Vor dem "=" mindestens ein Leer- oder Tabulatorzeichen
  • Nach dem "=" können zusätzlich auch Zeilenumbrüche eingefügt werden

Der Kommandoteil folgt dem Gleichheitszeichen (siehe Randnotiz). Und kann auf folgende Arten vorliegen.

  • FHEM Kommando
  • { Perl Befehl }
  • ( erweiterte Talk2Fhem Befehlskonfiguration )

Übersicht

<regexp> = <command>

Im ganzen könnte die Konfiguration dann so aussehen:

garage\S* auf = set dev_garage open

\S* Siehe hierzu "Häufig Verwendete RegExp".

Bei dem vorherigen Beispiel, würde der FHEM Befehl "set garage open" bei allen folgenden Sprachbefehlen ausgeführt werden.

Mach bitte die Garage auf
Das haus soll das Garagentor aufmachen
Garagentür in 5 Minuten auf
Die Garagen soll in einer Stunde aufgemacht werden

Klammerüberführung

Es ist nicht notwendig für jeden Zustand oder jedes Gerät eine eigene Konfigurationzeile zu erzeugen. Hierfür gibt es die Möglichkeit, wie bei Regulären Ausdrücken üblich, Klammern "( )" im <regex>-Teil zu erfassen. Dies erfolgt über die Standartvariablen $1, $2, ..., $n. "n" steht hier für die nte Klammer. Zusätzlich gibt es in Talk2Fhem die Möglichkeit die Klammern zu modifizieren.

Soll die Garage auf und zugemacht werden, lässt sich folgendermaßen beschreiben.

Beispiel:

garage\S* (\S*) = set dev_garage $1

Der Satz: "Mach die Garage auf" ergibt dann als FHEM Kommando

set dev_garage auf

Klammermodifikation

Da es in den meißten Fällen nicht gewünscht ist, nur das gefunde Wort in das FHEM Kommando zu überführen, lässt sich zusätzlich das gefundene Wort modifizieren.

Variante 1: nach Typ

Hier kann die Klammer auf ihren Typ hin modifiziert werden.

Definition
$n{ typ => modification, typ2 => mod2, ..., typn => modn }

typ kann eines der folgenden Wörtern enthalten:

  • true sind alle Wörter die eine positive Richtung enthalten. Wie z.B. auf, ein, hoch, an, usw.
  • false sind alle Wörter die eine negative Richtung enthalten. Wie z.B. ab, aus, runter, zu, usw.
  • integer Wort enthält eine Zahl
  • empty Wort enthält eine Leere Zeichenkette
  • /<regexp>/ Wort entspricht der <regexp> ###TODO###
  • else Falls keines der Fälle zutrifft

modification enthält das einzufügende Wort.

Beispiel
garage\S* (\S*) = set dev_garage $1{true=>open,false=>close}

Die Sätze:

mach die Garage auf
bitte Garagentor schließen 

würden hier folgende Befehle auslösen

set dev_garage open
set dev_garage close
Befehlsumkehr

Ein zusätzlicher Vorteil dieser Methode ist, dass über das Schlüsselwort "wieder" ein Befehlsumkehr ausgelöst werden kann.

Beispiel

mach bitte die Garage auf und in 5 Minuten wieder zu

Variante 2: nach Liste

Hier kann die Klammer anhand einer oder zweier Listen selektiert werden.

Definition
$n[ wert1, wert2,,,,, wertn ]

oder

$n[ @liste ]

Innerhalb der Klammern [ ] wird eine Komma separierte Liste mit Namen erwartet die als Modifikatorliste dient. Die sogenannte Modwordlist. Die Werte sind immer optional und können leer gelassen werden. Über das Attribut T2F_modwordlist können diese Listen zur Übersicht und Wiederverwendbarkeit angelegt werden. Siehe Attribute. Auf diese Listen, lässt sich über den Namen der Liste, mit einem vorangestelltes '@' zugreifen.

Beispiel nach Position

Beim ersten Beispiel wird eine Zahl im regex-Teil erwartet (\d+). Diese Zahl entscheidet welche Position aus der Modwordlist ausgewählt werden soll.

ventilator auf (stufe )?(\d+) = set aircon $2[ off, level1, level2, level3 ]

(Stufe )? bedeutet: Das Wort Stufe kann, muss aber nicht.

Die Sätze:

Ventilator in 10 Minuten auf Stufe 0
Ventilator auf 3

würden hier folgende Befehle auslösen

set aircon off
set aircon level3
Beispiel nach Vergleichsliste

Hier kommt eine weitere Liste ins Spiel. Die sogenannte Keywordlist ist eigentlich nur eine RegExp "Ver-oder-ung".

(key1|key2|...|keyn)

oder

(@keylist)

Diese Liste mit Schlüsselwörtern wird im <regex>-Teil angegeben. Hier entscheidet nicht eine Zahl über die Position, sondern die Position die in der Keywordlist einen Treffer hat wird in der Modwordlist ausgewählt. Im Attribut T2F_keywordlist können vordefinierte Listen angelegt werden und mit @keylist ausgewählt werden

blendet.* (Wohnzimmer|Esszimmer|Küche) = set $1[act_lvgroom, act_dinroom, act_kitchen] 70

.* beliebig viele Zeichen

Die Sätze:

es blendet im Esszimmer
ich sitze geblendet im Wohnzimmer
die sonne blendet in der Küche

würden hier folgende Befehle auslösen

set act_dinroom 70
set act_lvgroom 70
set act_kitchen 70
Ergänzung

Ähnlich wie in Variante 1, könne auch hier auf die Schlüsselwörte

empty für leere Zeichenkette 

und

else für alle anderen Fälle

zugegriffen werden. Hierbei wird der Modwordlist einfach empty oder else gefolgt von dem gewünschten Wert als nächstes Element angehängt.

$n[ wert1, wert2,,,, empty, wert3, else, wert4 ]

erweiterte Befehlskonfiguration

Um Talk2Fhem in den Konfigurationszeilen weitere Parameter zu übergeben, ist eine gesonderte Syntax zu verwenden.

<regexp> = ( option => 'value'  ,
             opt2   => 'value2' ,
             ... 
             optn   => 'valuen' ) 

Es stehen folgende Optionen zur Verfügung:

  • cmds => enthält das FHEM Kommando. Wie oben beschrieben.
  • answer => Ein in Anführungszeichen (" oder ') gesetzter Perl-Befehl, dessen Rückgabe in das Reading answer geschrieben wird.
  • offset => Ganzzahliger Wert in Sekunden der dem Zeitpunkt addiert wird

Attribute

Folgende Attribute werden zur Zeit unterstützt

T2F_keywordlist

<Name> = <Liste>

Name: Name der Liste
Liste: Eine Kommaseparierte Liste mit RegExp
Beispiel

rooms = haus|..?berall,wohnung,wohnzimmer,esszimmer,bad\S*,toilette|wc,b..?ro,schlafzimmer,ankleide|garderobergescho\S*
names = Mama,Papa,Kevin,Jacqueline
channels = ard|das erste,zdf,rtl,sat 1,vox,rtl2,prosieben,kabel eins,arte

T2F_modwordlist

<Name> = <Liste>

siehe T2F_keywordlist

roll = rollos_alle,rollos_alle,d_rollo_wz,hm_roll_ess,hm_roll_bad.*,hm_roll_wc,hm_roll_buero.*,d_rollo_schlaf,hm_roll_umkleide
gtags = gtag_green,gtag_red,gtag_blue,gtag_white

T2F_language

Legt die verwendete Sprache fest. Alternativ wird das Globale Attribut language verwendet werden.

disable

Deaktiviert das Ausführen des FHEM Kommandos

verbose

Anwendungsbeispiele

RegExp Crashkurs

Perl Regular Expression, also ein regulärer Ausdruck der Programmiersprache Perl, ist eine Werkzeug um Zeichenketten zu beschreiben. Hier wird versucht kurz einen Einblick auf die hier häufig benutzten RegExp zu geben.

Eine kurze Übersicht der verwendeten Zeichen kann hier eingesehen werden. [2]

RegExp Beschreibung
\S+ Mehr als ein Zeichen (+) welches kein Leerzeichen ist (\S)
\S\S? Ein oder zwei Zeichen die keine Leerzeichen sind. Das "?" wirkt hier nur auf das angrenzende "\S".
Sollte für Umlaute verwendet werden, da bei manchen Eingabemethoden Probleme mit Umlauten auftreten können.
(wort )? Ein bestimmtes Wort oder nicht.
(wort1|wort2) Entweder wort1 oder Wort2
wort$ Nur wenn das Wort am ende der Zeichenkette steht.
(\S+){,2} Keins, eins oder zwei Wörter. Kann für Artikel wie z.B. "(in der|in dem|im|auf der|...)?" eingesetzt werden


Eingabebeispiele

Links