RHASSPY/Vertiefung: Unterschied zwischen den Versionen
K (syntax highlighting gefixt?) |
K (→Eigene Dialoge) |
||
(7 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) | |||
Zeile 1: | Zeile 1: | ||
== Erste Schritte == | == Erste Schritte == | ||
Diese Seite knüpft an die [[RHASSPY/Schnellstart| Schnellstart-Anleitung]] an, welche die ersten grundlegenden Schritte einfach erklärt. | Diese Seite knüpft an die [[RHASSPY/Schnellstart| Schnellstart-Anleitung]] an, welche die ersten grundlegenden Schritte einfach erklärt. | ||
Zeile 59: | Zeile 58: | ||
* alle nicht zwingend erforderlichen Angaben sollten in optionaler Form notiert werden | * alle nicht zwingend erforderlichen Angaben sollten in optionaler Form notiert werden | ||
* Stille wird auf den kürzesten verfügbaren Satz gemappt. Dieser kürzeste Satz sollte '''unbedingt dem Intent ''CancelAction'' zugeordnet''' sein! | * Stille wird auf den kürzesten verfügbaren Satz gemappt. Dieser kürzeste Satz sollte '''unbedingt dem Intent ''CancelAction'' zugeordnet''' sein! | ||
{{Hinweis|Das Verhalten von Rhasspy kann durch Änderungen der Einstellungen der STT-Engine oder deren komplettem Austausch geändert werden! Rhasspy ist in dieser Hinsicht sehr flexibel, allerdings werden in der Regel für schnelle und gute Ergebnisse mit anderen Einstellungen deutlich höhere Hardwareanforderungen gestellt.}} | |||
=== Namen === | === Namen === | ||
Zeile 72: | Zeile 73: | ||
Um eine Anweisung wie das oben genannte "schließe die Rollläden" umzusetzen, muss RHASSPY wissen, dass es (uU.) mehrere Geräte gibt, die unter einer Sammelbezeichnung angesprochen werden können. Ist also ein ''group''-Attribut vergeben, wird diese Angabe dann auch im ''rhasspy-list'' zu finden sein. | Um eine Anweisung wie das oben genannte "schließe die Rollläden" umzusetzen, muss RHASSPY wissen, dass es (uU.) mehrere Geräte gibt, die unter einer Sammelbezeichnung angesprochen werden können. Ist also ein ''group''-Attribut vergeben, wird diese Angabe dann auch im ''rhasspy-list'' zu finden sein. | ||
Um die automatische Gruppen-Zuordnung zu verbessern, stehen zwei Schlüssel für das Attribut ''rhasspyTweaks'' zur Verfügung: | Um die automatische Gruppen-Zuordnung zu verbessern, stehen zwei Schlüssel für das Attribut ''rhasspyTweaks'' zur Verfügung: | ||
<syntaxhighlight lang=" | <syntaxhighlight lang="perl"> | ||
attr rhasspy rhasspyTweaks ignoreKeywords=rooms=MQTT.*|alexa|homebridge|googleassistant|Steuerung.* groups=Türen.und.Fenster|Schalter\ | attr rhasspy rhasspyTweaks ignoreKeywords=rooms=MQTT.*|alexa|homebridge|googleassistant|Steuerung.* groups=Türen.und.Fenster|Schalter\ | ||
gdt2groups= blind=rollläden,rollladen thermostat=heizkörper light=lichter,leuchten | gdt2groups= blind=rollläden,rollladen thermostat=heizkörper light=lichter,leuchten | ||
Zeile 185: | Zeile 186: | ||
Da diese Vorgehensweise zwar häufig passende Ergebnisse liefert, aber manche Hardwaregeräte diese Befehle anders umsetzen wie üblich, kann über verschiedene Schalter in ''rhasspySpecials'' eine abweichende Behandlung erreicht werden: | Da diese Vorgehensweise zwar häufig passende Ergebnisse liefert, aber manche Hardwaregeräte diese Befehle anders umsetzen wie üblich, kann über verschiedene Schalter in ''rhasspySpecials'' eine abweichende Behandlung erreicht werden: | ||
==== colorForceHue2rgb ==== | ==== colorForceHue2rgb ==== | ||
Wird dieser Schalter (Syntax: <code>attr lamp1 rhasspySpecials colorForceHue2rgb:1</code> eingeschaltet, wird das Gerät so behandelt, als hätte es keinen Hue-Setter, also als reines rgb-Gerät. | Wird dieser Schalter (Syntax: <code>attr lamp1 rhasspySpecials colorForceHue2rgb:1</code>) eingeschaltet, wird das Gerät so behandelt, als hätte es keinen Hue-Setter, also als reines rgb-Gerät. | ||
==== colorCommandMap ==== | ==== colorCommandMap ==== | ||
Die hier angegebenen nummerischen Farbwerte werden auf andere Befehle abgeleitet - ganz ähnlich der oben genannten Option ''numericValueMap'' für ''blind''-Type-Geräte. Beispiel: | Die hier angegebenen nummerischen Farbwerte werden auf andere Befehle abgeleitet - ganz ähnlich der oben genannten Option ''numericValueMap'' für ''blind''-Type-Geräte. Beispiel: | ||
Zeile 207: | Zeile 208: | ||
==== Custom Intents ==== | ==== Custom Intents ==== | ||
Ist ähnlich wie ''rhasspyShortcuts'', bietet aber den vollen Zugriff auf die von Rhasspy übergebenen Daten und erfordert Perl-Code, über den dann auch Dialoge gestaltet werden können. | Ist ähnlich wie ''rhasspyShortcuts'', bietet aber den vollen Zugriff auf die von Rhasspy übergebenen Daten und erfordert Perl-Code, über den dann auch Dialoge gestaltet werden können. | ||
==== | ==== rhasspyChannels ==== | ||
Wäre eine weitere (veraltete) Methode, um eine ähnliche Funktionalität zu erzielen. | Wäre eine weitere (veraltete) Methode, um eine ähnliche Funktionalität zu erzielen. | ||
== Dialoge == | |||
Üblicherweise schließt RHASSPY den laufenden Dialog, wenn eine Aktion abgeschlossen werden konnte. Hier werden die Ausnahmen dargestellt: | |||
=== Rückfragen === | |||
Kann RHASSPY nicht feststellen, welches Gerät genau gemeint ist, erfolgt entweder die Rückmeldung, dass insgesamt zu wenige Angaben gemacht wurden (und die Sitzung wird geschlossen), oder es erfolgt eine Rückfrage nach dem Device (wenn mehrere passende Devices im "angefragten" Raum vorhanden sind) oder dem Raum (weil mehrere Räume in Frage kommen). | |||
Zur Weiterführung derartiger Rückfragen (oder deren vorzeitigem Abbruch) werden weitere Intents benötigt: | |||
<syntaxhighlight lang="ini"> | |||
[de.fhem:ChoiceRoom] | |||
nimm [das Gerät] ( aus ( dem | der ) | im | den | die ) $de.fhem.MainRooms{Room} | |||
[de.fhem:ChoiceDevice] | |||
ich hätte gerne [das Gerät] $de.fhem.Aliases{Device} | |||
[de.fhem:CancelAction] | |||
(lass es | nein | abbrechen | abbruch ){Mode:Cancel} | |||
</syntaxhighlight> | |||
=== Bestätigungen === | |||
Über ''rhasspyShortcuts'', ''rhasspyTweaks'' und/oder ''rhasspySpecials'' kann eine Bestätigungsanfrage ausgelöst werden. Um eine solche Aktion freizugeben, wird ein weiterer Intent benötigt, der genau ''OK'' als ''{Mode}'' zurückliefern muss. Dieser könnte in sentences.ini etwa so aussehen: | |||
<syntaxhighlight lang="ini"> | |||
[de.fhem:ConfirmAction] | |||
( ja mach | tu es | ist ok | aber gerne doch ){Mode:OK} | |||
</syntaxhighlight> | |||
=== Eigene Dialoge === | |||
Über Custom Intents in Verbindung mit passenden Rückgabewerten aus myUtils-Perl-Code lassen sich Sitzungen offen halten und so eigene Dialoge gestalten. (siehe [[RHASSPY#Intents_in_eigenen_Dateien| Intents in eigenen Dateien]]) | |||
== Links == | == Links == | ||
Zeile 214: | Zeile 243: | ||
* [https://www.youtube.com/watch?v=sWVl0ZoXZEo Video zu sentences.ini] | * [https://www.youtube.com/watch?v=sWVl0ZoXZEo Video zu sentences.ini] | ||
[[Kategorie:Sprachsteuerung]] | [[Kategorie:Sprachsteuerung]] | ||
[[Category:HOWTOS]] |
Aktuelle Version vom 8. Mai 2022, 15:28 Uhr
Erste Schritte
Diese Seite knüpft an die Schnellstart-Anleitung an, welche die ersten grundlegenden Schritte einfach erklärt. Es wird dabei davon ausgegangen, dass das Feature "useGenericAttrs" aktiv ist.
devspec=room=Wohnzimmer:FILTER=genericDeviceType=.+,room=Esszimmer:FILTER=genericDeviceType=.+
. Dies kann später ohne weiteres wieder erweitert werden.Ziel dieser Vertiefung ist zu zeigen, wie man auf einfachem Weg Sprachbefehle umsetzen kann wie - "schalte alle Lichter beim Sofa an" - "schließe die Rollläden" (gemeint: im Wohnzimmer) - "mach überall die Lichter aus"
Es empfiehlt sich für diese Vertiefung, einige wenige, jeweils gleichartige Geräte in einem oder besser zwei Räumen zu betrachten, also z.B. vier Leuchten (genericDeviceType light) und einige Rollläden oder Jalousien (blind). Im Folgenden wird unterstellt, dass je zwei light und blind-Geräte im Wohn- und Esszimmer vorhanden sind.
Die devicemap
Im Schnellstart im Abschnitt Ein Gerät mit Rhasspy verbinden wurde bereits darauf hingewiesen, dass mit Hilfe des Befehls list rhasspy
in Erfahrung gebracht werden kann, welche "Eigenschaften" die automatische Erkennung für die einzelnen Geräte erkannt hat. Wenn also im Folgenden Änderungen vorgenommen werden, empfiehlt es sich dann jeweils nach der Änderung ein set rhasspy update devicemap_only
durchzuführen und dann die Auswirkungen im list bei rhasspy zu betrachten. Sind alle Änderungen dann soweit ok, können diese mit set rhasspy update devicemap
an Rhasspy übergeben und das Training veranlasst werden.
Grundlegende Strukturierungsmerkmale
Für die Sprachsteuerung ist es wichtig, dass die Geräte möglichst eingängig und innerhalb nachvollziehbarer Strukturen angesprochen werden können. Alle verwendeten Begriffe, insbesondere die eigentlichen Geräte-Namen sollten daher folgende Bedingungen erfüllen: Sie sollten
- sprechbar
- hinreichend eindeutig und
- eingängig
sein. Doppelbelegungen sind zwar zulässig, es sollte aber für die Software auf der jeweiligen Stufe möglich sein, ein eindeutiges Ergebnis zu ermitteln. Dies geschieht in der Regel über den Kontext, in dem etwas gesagt wird - ganz wie im richtigen Leben macht es einen Unterschied, ob die Anweisung "Mach das Licht aus" im Wohnzimmer oder im Esszimmer erfolgt. Die Orts-Information ergibt sich hier z.B. aus dem Ort, an dem sich der Empfänger der Anweisung befindet.
Optionale Elemente in sentences.ini
Im Schnellstart wurde folgender Intent für das Ein- und Ausschalten vorgestellt:
[de.fhem:SetOnOff]
schalte das $de.fhem.Device-SetOnOff{Device} ( an{Value:on} | aus{Value:off})
Demgegenüber enthält der Abschnitt SetOnOff zu den einzelnen Intens eine deutlich erweiterte Variante:
[de.fhem:SetOnOff]
(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}
(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}
(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})
Spätestens jetzt ist zu empfehlen, das Informationsvideo zu den Optionen anzusehen, die sentences.ini innerhalb Rhasspy bietet! Hier ist bereits zu erkennen, dass es sinnvoll ist - optionale Zusatzinformationen (sprechend) ergänzen zu können (oder diese eben auszulassen) - bestimmte Wortkombinationen auf die Geräte-Typen zu beschränken, für die das sprachlich überhaupt paßt.
"Öffnen" oder "schließen" kann man ein Licht in der Regel nicht, einen Rollladen oder eine Tür sehr wohl. Unterstellt, es sind keine automtatischen Türöffner vorhanden, könnte vielleicht folgende Ergänzung sinnvoll sein:
(öffne{Value:on}|schliesse{Value:off})[den|die|das] $de.fhem.Device-blind{Device} [[(im|in dem|auf dem|in der|auf der)] $de.fhem.Room{Room}]
Werden alle drei Datenelemente (Value, Device und Room) übergeben, sollte es für RHASSPY möglich sein, ein FHEM-Device zu ermitteln, auf das die beiden wesentlichen Informationen (Device und Room) paßt. Fehlt Room, bleibt immer noch die Möglichkeit, dass RHASSPY die fehlende Information ergänzen kann - insbesondere, indem ausgewertet wird, wo die Information herkam.
Damit innerhalb des RHASSPY-Codes Verwechslungsgefahren minimiert werden, werden
- alle intern verwendeten Bezeichnungen klein gemacht, also insbesondere alle Namen, Gruppen- und Raumnamen werden nach devicemap in Kleinschreibung übernommen (und auch so an Rhasspy übermittelt),
- englische Schlüsselwörter für typische Kommandos verwendet (also z.B. on und off)
- Farbwerte und ähnliches nummerisch übergeben
Tauchen irgendwo Großbuchstaben auf, handelt es sich in der Regel um ein Schlüsselwort wie Value oder Room, dem dann ein Wert zugewiesen ist.
"must match"-Prinzip
Eine Besonderheit der in den Standardeinstellungen bei Rhasspy verwendeten speech-to-text-engine besteht darin, dass diese zwingend ein Ergebnis liefern muss. Daher sollten folgende Aspekte bei der Gestaltung der sentences.ini berücksichtigt werden:
- alle nicht zwingend erforderlichen Angaben sollten in optionaler Form notiert werden
- Stille wird auf den kürzesten verfügbaren Satz gemappt. Dieser kürzeste Satz sollte unbedingt dem Intent CancelAction zugeordnet sein!
Namen
Dem Umstand, dass die üblichen FHEM-Gerätenamen in der Regel nicht sprechbar sind, kann man dadurch begegnen, dass man einfach sprechbare Namen vergibt. Wie im wiklichen Leben ist es dabei denkbar, dass etwas unter mehreren Bezeichnungen bekannt ist. Im nebenstehenden rhasspy-list für das Gerät "Office" ist zu erkennen, dass dieses einen alias namens licht hat. Diese Information könnte entweder aus dem gleichnamigen (allgemeinen) Attribut kommen, es könnte aber auch die Folge davon sein, dass z.B. ein alexaName o.ä. vergeben ist, oder diese Bezeichnung im Attribut rhasspyName zu finden ist. Der Schlüssel alias wird immer nur eine (Haupt-) Bezeichnung enthalten, der weitere Schlüssel names kann eine im Prinzip unbeschränkter Werte enthalten.
Die Namen müssen nicht eindeutig sein, jedenfalls dann nicht, wenn sich aus dem Kontext ableiten läßt, welches Gerät gemeint ist. Es spricht also nichts dagegen, jeweils einen alias rollladen zu vergeben, wenn sich in einem Raum jeweils nur ein einziger befindet. Entsprechendes gilt für Lichter, wobei es durchaus zulässig ist, z.B. die Hauptbeleuchtung mit licht zu bezeichnen. Wird das Attribut rhasspyName verwendet, um diese Werte zu erzeugen, wird der erste angegebene Name als alias verwendet.
Exkurs: Die allgemeine Logik der rhasspy-Attribute
Es empfiehlt sich, bei einem Device nachzuvollziehen, wie ggf. vorhandene alias-, siriName- (etc.) und rhasspyName-Attribute zusammenwirken. RHASSPY wird dabei immer die eigenen Attribute bevorzugen, falls diese gesetzt sind, mit der Wirkung, dass andere, automatisch ermittelten Werte vollständig verdrängt werden. Dies gilt genauso z.B. für rhasspyMapping. Dieses Prinzip ist an vielen Stellen in RHASSPY anzutreffen. So gibt es teils Möglichkeiten, die man entweder allgemein in rhasspyTweaks einstellen kann, oder speziell für einzelne Devices in rhasspySpecials. Auch in diesen Fällen wird die spezifischere Angabe am Device die generelle Vorgabe (an rhasspy) verdrängen.
Gruppen
Um eine Anweisung wie das oben genannte "schließe die Rollläden" umzusetzen, muss RHASSPY wissen, dass es (uU.) mehrere Geräte gibt, die unter einer Sammelbezeichnung angesprochen werden können. Ist also ein group-Attribut vergeben, wird diese Angabe dann auch im rhasspy-list zu finden sein. Um die automatische Gruppen-Zuordnung zu verbessern, stehen zwei Schlüssel für das Attribut rhasspyTweaks zur Verfügung:
attr rhasspy rhasspyTweaks ignoreKeywords=rooms=MQTT.*|alexa|homebridge|googleassistant|Steuerung.* groups=Türen.und.Fenster|Schalter\
gdt2groups= blind=rollläden,rollladen thermostat=heizkörper light=lichter,leuchten
Der erste ignoreKeywords bewirkt (u.a.), dass bestimmte, im allgemeinen Attribut group vorzufindende Gruppennamen nicht ausgewertet werden, der zweite gdt2groups führt dazu, dass für die dirt genannten genericDeviceType bestimmte Gruppennamen automatisch vergeben werden. Auch hier kann diese generelle Vorgabe durch das Setzen des speziellen Attributs rhasspyGroup überschrieben werden, so dass dann z.B. eine Leinwand (gDT blind) dann auch wieder aus den Gruppen rollläden,rollladen genommen werden kann und z.B. der Gruppe mediengeräte zugeordnet werden könnte.
Räume
Das Vorgenannte gilt für Räume (allgemeines Attribut room vs- rhasspyRooms) entsprechend, wobei der erste in rhasspyRooms angegebene Raum dann ggf. wieder eine Sonderfunktion hat und daher dem Hauptraum entsprechen sollte, dem man dieses Gerät örtlich hauptsächlich zuordnet.
Gruppen vs. Räume
Worin besteht nun der Unterschied zwischen Gruppen und Räumen? Räume sind eher dazu gedacht, Geräte örtlich zu kennzeichnen, Gruppen sind dagegen eher funktional, und die Wirkung eines Gruppenbefehls ist in RHASSPY in der Regel (s.u.) begrenzt durch den Raum, der jeweils mit angesprochen wird. Ist in dem von Rhasspy an RHASSPY übergebenen Datensatz keine ausdrückliche {Room}-Information enthalten, wird RHASSPY daher in der Regel zunächst versuchen, dies aus der in der siteId enthaltenen Ortsinformation abzuleiten, und dann erst die Suche außerhalb des Raums fortsetzen, wenn dies nicht möglich ist. Natürlich ist es zulässig, auch in der Gruppenbezeichnung eine Ortsinformation mitzugeben, indem (zusätzliche) Gruppen gesetzt werden wie "lichter beim sofa", oder die Ortsinfo "beim sofa" als zusätzlichen Raum anzugeben (was aber dann dazu führt, dass "lichter beim sofa im wohnzimmer" uU. nicht zum gewünschten Ergebnis führt.
Gruppen, Räume und Funktionalitäten als slots
Die sich aus diesen ganzen Meta-Informationen ergebenden "sprechbaren" Informationsanteilen führt RHASSPY für Rhasspy zu einer Vielzahl von slots zusammen, mit deren Hilfe dann die Kombinationsmöglichkeiten für die eigentliche Spracherkennung soweit eingeschränkt werden kann, dass im Optimalfall dann nur (aus Sicht von RHASSPY) gültige Datensätze zurückkommen, die dann auch ausgeführt werden können. Es empfiehlt sich daher, sich etwas intensiver mit diesen slots zu befassen, die sich ergeben, sobald man die ersten paar Geräte in der devicemap sauber strukturiert hat. Sind in den slots Informationen enthalten, die so nicht erwartet wurden, kann man diese in der Regel über die devicemap im rhasspy-list zurückverfolgen und muss dann eben die entsprechenden Attribute anpassen bzw. ggf. den ignoreKeywords-Filter in rhasspyTweaks anpassen.
Einer statt alle
Wie bereits dargestellt, wird RHASSPY zunächst versuchen herauszufinden, an welches FHEM-Device ein Kommando eigentlich gerichtet ist. Ist kein Raum angegeben, wird der logische Kette von der siteId zu dem Raum gefolgt, in dem primär gesucht werden soll. Gibt es das Gerät dort nicht, aber systemweit nur ein Gerät mit einem bestimmten Namen, ist es hinreichend eindeutig. Was aber tun, wenn mehrere Geräte in Frage kommen, sei es innerhalb, sei es außerhalb des Raums des Sprechenden oder des angefragten Raumes? Klar, RHASSPY kann rückfragen und tut dann genau das... Zu Dialogen kommen wir aber erst später, hier soll nun eine andere Option erläutert werden, mit der man für mehr Eindeutigkeit sorgen kann. Wie üblich, wenn etwas als Device-spezifisches Extra anzusehen ist, ist dieses im Attribut rhasspySpecials zu finden. Das folgende Beispiel wird daher alle Anfragen, die entweder in dessen Raum erfolgen oder für die es kein Ergebnis innerhalb des Raums gibt auf diesen Sensor umleiten:
attr sensor_outside_main rhasspySpecials priority:inRoom=temperature outsideRoom=temperature,humidity,pressure
Entsprechend kann verfahren werden, wenn z.B. für die Regelung der Temperatur in einem Raum ein Wand-Thermostat verbaut ist, der dann seinerseit die Regelung der einzelnen Heizkörper übernimmt:
attr wall_thermostat rhasspySpecials priority:inRoom=desired-temp
Gruppen-Intents
Beispiel SetOnOffGroup
Ist die devicemap also soweit vorbereitet, dass sprechbare Namen vergeben sind und Gruppen- und Raumstrukturen (sprechbar) beschrieben sind, können wir den ersten Gruppen-Intent anlegen:
[de.fhem:SetOnOffGroup]
(schalte|schalt|mache|mach|stelle|stell|starte) ([überall{Room:global} [die]] | alle | sämtliche ) $de.fhem.Group-SetOnOff{Group} [[(im|in dem|auf dem|in der|auf der)] $de.fhem.Room {Room}] (an|ein){Value:on}
(schalte|schalt|mache|mach|stelle|stell) ([überall{Room:global} [die]] | alle | sämtliche ) $de.fhem.Group-SetOnOff{Group} [[(im|in dem|auf dem|in der|auf der)] $de.fhem.Room{Room}] aus{Value:off}
(fahre|fahr|mach|mache) ([überall{Room:global} [die]] | alle | sämtliche ) $de.fhem.Group-blind{Group} [[(im|in dem|auf dem|in der|auf der)] $de.fhem.Room{Room}] ((hoch|auf){Value:on}|(zu|runter){Value:off})
Die Unterscheidung zu dem einfachen SetOnOff-Intent besteht dabei sprachlich zum einen in den Gruppennamen, und zum anderen in der zusätzlich erforderlichen Angabe, ob überall oder alle bzw. sämtliche Geräte angesprochen werden sollen. global ist dabei ein spezieller Raumname, der schlicht alle passenden Geräte umfasst.
Timing-Aspekte
Werden gleichzeitig mehrere Geräte geschaltet, kann es zu Problemen kommen, insbesondere, wenn diese über Funk-Interfaces angesteuert werden. Um solche Probleme zu minimieren, stehen im Attribut rhasspySpecials mehrere Optionen zur Verfügung, die auch mehr oder weniger beliebig miteinander kombiniert werden können.
async_delay
Die einfachste ist, die Befehle für jedes der betroffenen Devices zeitlich zu entzerren.
attr lamp1 rhasspySpecials group:async_delay=0.3
Dies würde bewirken, dass das betreffende Device bei einem Gruppen-Intent mit 300 ms Verzögerung angesprochen wird, falls bei dem Gruppe-Befehl überhaupt weitere Geräte zu schalten sind (oder gerade weitere Gruppenbefehle abgearbeitet werden). RHASSPY wird dabei versuchen, immer zunächst den (verbleibenden) Befehl mit der geringsten Verzögerung zu verarbeiten und alle anderen dann entsprechend zurückstellen.
prio
Die Reihenfolge der Abarbeitung kann durch das weitere Element prio beeinflusst werden. Falls lamp1 zuerst eingeschaltet werden soll, wenn es über eine Gruppenschaltung mit lamp2 adressiert wird, kann dem anderen Gerät .
attr lamp1 rhasspySpecials group:async_delay=0.3 attr lamp2 rhasspySpecials group:prio=1
Dies würde bewirken, dass zuerst lamp1 geschaltet wird, und dann mit 300ms Verzögerung lamp2.
partOf
Zu guter Letzt ist es auch möglich, RHASSPY mitzuteilen, dass ein einzelnes Gerät bei Gruppenschaltung nicht als Einzeldevice behandelt werden soll, sondern als Teil von einer an anderer Stelle festgelegten Struktur. Dies könnte z.B. ein structure-Device sein oder eine gemeinsam steuerbare Hardware-Gruppe, wie sie z.B. ZigBee kennt:
attr lamp1 rhasspySpecials group:partOf=zigbeegr5
Dabei wird der betreffende Gruppenbefehl nur einmalig versendet, selbst wenn mehrere angesprochene Geräte Mitglied dieser externen Gruppe sind. Falls zugleich prio und/oder async_delay verwendet werden soll, ist dies bei allen zur externen Gruppe gehörenden Geräten einheitlich anzugeben!
Nummerische Werte
SetNumeric
Nummerische Sprachanweisungen sind in der sprachlichen Realität deutlich vielfältiger, als es auf den ersten Blick erscheinen mag. Die Bandbreite geht von klaren Anweisungen wie "Stelle die Leuchte am Esstisch auf die Helligkeit 72" über "mach dunkler" bis hin zu "halte den Rollladen an" und "erhöhe die Temperatur um 10%". RHASSPY enthält intern einen recht komplexen Code, der sowohl absolute wie relative Anweisungen verarbeiten kann und/oder aus (zuordenbaren) Richtungsangaben das/die passende/n Gerät/e ableitet. Je nachdem, welche Rahmenbedingungen sonst bekannt sind, kann eine Kombination der Datenfelder {Device}, {Value} (ein nummerischer Wert), {Change} oder {Type} ausreichend sein, {Room} ist optional. Ergänzend kann das optionale Feld {Unit} (ausschließlich mit dem Wert percent) genutzt werden, um prozentuale Berechnungen (immer bezogen auf die Spanne zwischen Minimal- und Maximal-Wert) zu starten. Für {Change} können folgende Werte ausgewertet werden:
- lightUp, lightDown (abgeleitet wird, dass ein setter vom {Type} brightness angesteuert werden soll)
- volUp, volDown (setter vom {Type} volume)
- tempUp, tempDown (setter vom {Type} temperature, wobei der setter in der Regel eher als desired-temp oä. angesteuert wird)
- setUp, setDown (allgemeiner setter vom {Type} setTarget)
- cmdStop (spezielles Kommando für genericDeviceType blind-Geräte)
Der passende Intent sähe dann z.b. so aus:
[de.fhem:SetNumeric]
\[ ( schalt | mach ) ] [(den | die | das )] $de.fhem.Device-media{Device} [[(im | in der )] $de.fhem.Room{Room}] [um] [(0..10){Value!int}] [dezibel{Unit:decibel}] ( lauter:volUp | leiser:volDown ){Change}
( mach | stelle ) [(den | die | das )] $de.fhem.Device-thermostat{Device} [[(im | in der )] $de.fhem.Room{Room}] [um] [(0..10){Value!int}] [grad{Unit:degree}] ( wärmer:tempUp | kälter:tempDown ){Change}
( mach |schalt|schalte|stelle) [(den | die | das )] $de.fhem.Device-light{Device} [[(im | in der )] $de.fhem.Room{Room}] [um] [(0..100){Value}] [prozent{Unit:percent}] ( heller:lightUp | dunkler:lightDown){Change}
(schalt | schalte | stelle ) [(den | die | das )] ( $de.fhem.Device-light | $de.fhem.Device-media |$de.fhem.Device-blind){Device} [[(im | in der )] $de.fhem.Room{Room}] auf (0..100){Value!float}
( mehr{Change:lightUp} | weniger{Change:lightDown} ) $de.fhem.Device-light{Device} [[(im | in der )] $de.fhem.Room{Room}]
(schalt | schalte | stelle ) $de.fhem.Device-SetNumeric{Device} auf (0..100){Value!float}
( mehr{Change:lightUp} | weniger{Change:lightDown} ) $de.fhem.Device-light{Device} [$de.fhem.Room{Room}]
( halte | stoppe ) ( den | die ) $de.fhem.Device-blind{Device} [[(im | in der )] $de.fhem.Room{Room}] [an] {Change:cmdStop}
SetNumericGroup
Geräte, die als Einzelgerät per SetNumeric-Intent gesteuert werden können, können auch über den entsprechenden Gruppen-Intent angesteuert werden. Wird dabei ein Gruppenname verwendet, in dem auch Geräte enthalten sind, die einzelen Gruppenbefehle nicht umsetzen können, werden diese Geräte einfach übergangen. So kann z.B. eine Gruppe, die über $de.fhem.Group-light uU. auch Geräte beinhaltet, die nur SetOnOff beherrschen, aber nicht gedimmt werden können, ohne weiteres über einen Helligkeitsbefehl angesteuert werden.
Rollladengeräte
Einen Sonderfall innerhalb der per SetNumeric steuerbaren Geräte stellen Rollladen-Geräte (genericDeviceType blind) dar. Zum einen kennen diese in der Regel Sonderbefehle wie "stop" oder gelegentlich auch spezielle Zwischenpositionen (wie "myPosition" für Somfy-Geräte), zum anderen kennen manche Aktoren auch einen "venetian mode", also die ergänzende Ansteuerung von drehbaren Lamellen (in diesem Sinne wird im Folgenden von Jalousie gesprochen).
Spezielle Positionskommandos
Für Rollladengeräte könnten z.B. folgende Beispiel-Sätze in sentences.ini für SetNumeric verwendet werden:
(halte|stopp|stoppe) [den|die|das] $de.fhem.Device-blind{Device} [[(im|in|in dem|auf dem|in der|auf der)] $de.fhem.Room{Room}] [an] {Change:cmdStop}
(fahre|fahr|stelle|stell) [den|die|das] $de.fhem.Device-blind{Device} [[(im|in|in dem|auf dem|in der|auf der)] $de.fhem.Room{Room}] auf Beschatten{Value:21.8}
- Der erste dient dazu, das "stop"-Kommando als relative Wertangabe zu übergeben. Ist im SetNumeric-Mapping ein entsprechende Kommando hinterlegt (dieses wird in der Regel automatisch erkannt, wenn vorhanden), wird der Rollladen schlicht an der aktuellen Position anhalten.
- Der zweite dient dazu, einen eher ungewöhnlichen Zahlenwert als Value zu übergeben. Dieser kann dann über einen 'numericValueMap'-Eintrag im Attribut rhasspySpecials auf ein beliebiges anderes Kommando an diesem Gerät umgeleitet werden (hier wird davon ausgegangen, dass Beschatten mit einem Befehl
set blind1 pct 30
umgesetzt werden soll, und es sind gleich noch einige weitere beispielhafte Optionen aufgeführt):
attr blind1 rhasspySpecials numericValueMap:21.8='pct 30' 10='Event Slit' 50='myPosition'
Jalousien
Für Jalousien ist es in der Regel erforderlich, zusätzlich zum eigentlichen Positionskommando (für die Behanghöhe) noch ein weiteres Positionskommando abzusetzen. Dazu muss RHASSPY zum einen wissen, dass das erforderlich ist, und zum anderen muss bekannt sein, ob es ein Befehl am selben Device ist oder an einem anderen, und wie dieser heißt. Diese ergänzenden Informationen sind im Attribut rhasspySpecials in einer Zeile für venetianBlind zu hinterlegen:
attr blind1 rhasspySpecials venetianBlind:setter=dim device=blind1_slats stopCommand="set blind1_slats dim [blind1_slats:dim]"
Hier würde also ein zusätzliches anderes Gerät mit gesteuert, wobei der setter dim verwendet würde. Als Wert für die Lamellendrehung wird dabei bei normalen Positionskommandos nochmals der Wert für die Behanghöhe verwendet, für stop-Kommandos wird im obigen Beispiel der letzte bekannte Lammellenwinkel verwendet. Diese Einstellungen sind passend für ZWave-Geräte, bei denen die Lamellen als eigenes Device abgebildet werden.
Farben
Farbangaben als Nummern
Farben - oder allgemeiner gesagt, alles, was mir Farbwerten zu tun hat (also auch Weißwerte und ggf. Farbsättigung) - erwartet RHASPY in nummerischer Form. In der Muster-Sprachdatei, die wir im Schnellstart kennengelernt haben, ist daher bereits eine beispielhafte "Umrechnungstabelle" von gesprochenen Farbangaben zu nummerischen Werten enthalten, die erforderlichenfalls angepaßt werden kann. Zum Start sollte z.B. folgender Eintrag in der sentences.ini genügen:
[de.fhem:SetColor]
\[setze|färbe|stelle] [(den | die | das )] $de.fhem.Device-light{Device} [[(im | in der )] $de.fhem.Room{Room}] [auf die Farbe] ( $de.fhem.Colors{Hue} | $de.fhem.Colortemp{Colortemp} )
Dadurch wird in der Regel der Farbwert in der Hue-Dimension innerhalb des HSV-Farbraums übergeben, also insbesondere ohne Helligkeitsangabe. Kennt ein Gerät keine Hue-Dimension in seinen settern, wird stattdessen der rgb-Farbraum verwendet, mit den aus der de-language-File ersichtlichen rgb-Entsprechungen der Hue-Werte.
Spezielle Mappings
Da diese Vorgehensweise zwar häufig passende Ergebnisse liefert, aber manche Hardwaregeräte diese Befehle anders umsetzen wie üblich, kann über verschiedene Schalter in rhasspySpecials eine abweichende Behandlung erreicht werden:
colorForceHue2rgb
Wird dieser Schalter (Syntax: attr lamp1 rhasspySpecials colorForceHue2rgb:1
) eingeschaltet, wird das Gerät so behandelt, als hätte es keinen Hue-Setter, also als reines rgb-Gerät.
colorCommandMap
Die hier angegebenen nummerischen Farbwerte werden auf andere Befehle abgeleitet - ganz ähnlich der oben genannten Option numericValueMap für blind-Type-Geräte. Beispiel:
attr lamp1 rhasspySpecials colorCommandMap:0='rgb FF0000' 120='rgb 00FF00' 240='rgb 0000FF'
colorTempMap
Entspricht dem zu colorCommandMap gesagten, nur dass hier als Eingangsinformation ein Weiß-Wert erforderlich ist statt einer Hue-Angabe.
Szenen
Um einzelne oder mehrere Geräte gleichzeitig in einen zueinander passenden Modus zu versetzen, stehen verschiedene Mechanismen bereit, die hier in der Zusammengschau kurz erläutert werden sollen:
echte Szenen
Viele Geräte kennen Optionen, bestimmte Einstellungen zu speichern und "auf Knopfdruck" wieder abrufen zu können, einige Interface-Typen kennen dies als Funktion, übergeordnet mehrere Geräte zu steuern und mit LightScene steht in FHEM auch ein Modul bereit, mit dem das ebenfalls für mehrere Geräte vorab abgespeicherte Zustände wieder hergestellt werden können.
Erkennt die automatische Geräte-Analyse, dass ein Gerät über eine Szenenfunktion verfügt, wird dieses Gerät auch für die Ansteuerung seiner Szenen vorbereitet. Allerdings sind diese Szenen in der Regel nicht sprechbar, und häufig werden auch sehr viele Szenen angeboten, die gar nicht genutzt werden.
Über das rhasspySpecial scene kann solchen Geräten sprechbare Szenenbezeichnungen zugeordnet werden, und es können mit der Angabe none auch einzelne oder alle Szenen deaktiviert werden. Details sind der commandref zu entnehmen.
ähnliche Optionen
Stehen keine direkten Szenen-Funktionen zur Verfügung, kann entweder ein LightScene-Gerät erstellt werden, oder es können alternativ folgende ähnliche Funktionalitäten verwendet werden, um ähnliche Ergebnisse zu erziehlen
rhasspyShortcuts
Dieser Intent ermöglicht es, verschiedenen Sprachsequenzen jeweils im Prinzip beliebigen Befehlen (FHEM-Kommandos oder Perl-Code) zuzuordnen.
Custom Intents
Ist ähnlich wie rhasspyShortcuts, bietet aber den vollen Zugriff auf die von Rhasspy übergebenen Daten und erfordert Perl-Code, über den dann auch Dialoge gestaltet werden können.
rhasspyChannels
Wäre eine weitere (veraltete) Methode, um eine ähnliche Funktionalität zu erzielen.
Dialoge
Üblicherweise schließt RHASSPY den laufenden Dialog, wenn eine Aktion abgeschlossen werden konnte. Hier werden die Ausnahmen dargestellt:
Rückfragen
Kann RHASSPY nicht feststellen, welches Gerät genau gemeint ist, erfolgt entweder die Rückmeldung, dass insgesamt zu wenige Angaben gemacht wurden (und die Sitzung wird geschlossen), oder es erfolgt eine Rückfrage nach dem Device (wenn mehrere passende Devices im "angefragten" Raum vorhanden sind) oder dem Raum (weil mehrere Räume in Frage kommen).
Zur Weiterführung derartiger Rückfragen (oder deren vorzeitigem Abbruch) werden weitere Intents benötigt:
[de.fhem:ChoiceRoom]
nimm [das Gerät] ( aus ( dem | der ) | im | den | die ) $de.fhem.MainRooms{Room}
[de.fhem:ChoiceDevice]
ich hätte gerne [das Gerät] $de.fhem.Aliases{Device}
[de.fhem:CancelAction]
(lass es | nein | abbrechen | abbruch ){Mode:Cancel}
Bestätigungen
Über rhasspyShortcuts, rhasspyTweaks und/oder rhasspySpecials kann eine Bestätigungsanfrage ausgelöst werden. Um eine solche Aktion freizugeben, wird ein weiterer Intent benötigt, der genau OK als {Mode} zurückliefern muss. Dieser könnte in sentences.ini etwa so aussehen:
[de.fhem:ConfirmAction]
( ja mach | tu es | ist ok | aber gerne doch ){Mode:OK}
Eigene Dialoge
Über Custom Intents in Verbindung mit passenden Rückgabewerten aus myUtils-Perl-Code lassen sich Sitzungen offen halten und so eigene Dialoge gestalten. (siehe Intents in eigenen Dateien)