RHASSPY/Vertiefung

Aus FHEMWiki
Version vom 7. Dezember 2021, 13:45 Uhr von Beta-User (Diskussion | Beiträge) (SetNumeric für 'blind')


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


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.

Info green.pngFalls bereits eine andere Sprachsteuerungslösung installiert ist, kann es sein, dass RHASSPY bereits sehr viele Geräte in der devicemap enthält. Wem dies zu unübersichtlich ist, kann den devspec-Parameter in der DEF z.B. so anpassen, um z.B. zunächst nur Geräte im Wohnzimmer zu erfassen: 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

Info green.pngEs ist zu empfehlen, hin und wieder auch zu überprüfen, ob alle Wörter auch für Rhasspy hörbar sind. Dazu ist die Words-Seite in der Rhasspy-Konfiguration aufzurufen, mit derem Hilfe man bisher unbekannte Wörter phonetisch beschreiben kann.

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

Helper für eine Lampe im RHASSPY Modul: Unter dem technischen Namen ist der alias aufgelistet, darunter ggf. die weiteren Namen, unter denen das Gerät ansprechbar ist

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.

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

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 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

Farben

Links