Modulentwicklung für Rhasspy Sprachassistent

Begonnen von drhirn, 11 März 2021, 15:59:50

Vorheriges Thema - Nächstes Thema

drhirn

Also, am einfachsten wäre, du benennst den Satellit in küche um.

siteId2room ist auch eine Möglichkeit. Empfehle ich in dem Fall aber eher nicht.
Ist auf jeden Fall ein eigener "Custom Intent". Dazu müsstest du 99_RHASSPY_Utils_siteId2room.pm aus SVN oder GitHub holen und sie in deinem FHEM-Installationsordner ablegen (Berechtigungen nicht vergessen). Und dann einen rhasspyIntent anlegen: siteId2room=RHASSPY::siteId2room::siteId2room(NAME,DATA)

Beta-User

#571
Zitat von: drhirn am 30 April 2021, 08:52:40
siteId2room ist auch eine Möglichkeit. Empfehle ich in dem Fall aber eher nicht.
Schließe mich der Empfehlung grundsätzlich an.

Das mit dem Code ist dazu gedacht, das im laufenden Betrieb (einfach und per Sprache) ändern zu können, was klasse ist, wenn man einen "mobilen Satelliten" hat.
Der CustomIntent-Code macht aber nichts anderes, wie ein bestimmtes Reading auf einen neuen Wert zu setzen. Das Modul selbst schaut auch ohne die myUtils-Geschichte nach dem Wert des Readings, man kann das also einfach auf via "setreading" auf den passenden Wert setzen.

Der Code zur Auswertung (und Bildung) des Reading-Namens in RHASSPY sieht wie folgt aus:
1342        my $rreading = makeReadingName("siteId2room_$siteId");
1343        $siteId =~ s{\A([^.]+).*}{$1}xms;
1344        utf8::downgrade($siteId, 1);
1345        $room = ReadingsVal($hash->{NAME}, $rreading, lc $siteId);


Bei "satellite-kueche" müsste also "siteId2room_satellite-kueche" als Readingname passen...

Die Doku zum (myUtils-) Code an sich ist in der dortigen commandref enthalten. Vorschläge zur Verbesserung nehmen wir aber natürlich gerne entgegen, das habe ich erst mal zur Lösung des spezifischen Problems entwickelt...

EDIT: Das mit der Reading-Abfrage wäre btw. auch ein Anknüpfungspunkt, um ganz ohne RHASSPY-Hilfe im laufenden Betrieb den Standort eines Satelliten zu ändern, z.B. anhand der RSSI-Werte einer Bluetooth-Verbindung zu einem oder mehreren BT-Dongles oä..
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Beta-User

#572
 ::) Bitte nicht erschrecken, wenn du das diff machst...

Anbei eine neue, experimentelle (!) Version (also vorerst bitte nicht nach contrib damit...).

Kann sein, dass damit das mit dem Bestätigungsdialog nicht mehr funktioniert und/oder andere schwerwiegende Probleme auftreten, wenn man was "dialogisches" versucht (Rest müsste weiter passen).
Es gibt jetzt drei weitere Intents, von denen einer aktiv geschaltet sein sollte, nämlich "CancelAction". Ich empfehle für diese Version, dazu einen eigenenen Zweig in den sentences aufzumachen, der Inhalt kann derselbe Abbruchsatz sein wie bisher der in "ConfirmAction".

Dieses Aufsplitten hat folgenden Hintergrund:
Künftig brauchen wir das mit dem Abbrechen (und Bestätigen) ggf. von unterschiedlichen Satelliten aus und für unterschiedliche Intents parallel, zumindest war das die "logische Hürde", die sich mir beim Nachdenken über das "welches Räumchen hätten Sie denn gerne" gestolpert bin. Die bisherige "Verwaltung" bestand darin, einfach genau eine Dialog-Option zu "parken", was m.E. das Risiko birgt, dass irgendwann alles durcheinandergeht, wenn mal tatsächlich mehreres gleichzeitig ausgeführt werden soll und dann ggf. ganz komische Dinge passieren, wenn der falsche Code aufgerufen wird...

Daher bin ich jetzt auf die Idee verfallen, einfach den ganzen $data-Inhalt in "custom_intent" wieder auf die Reise zu schicken wie in https://rhasspy-hermes-app.readthedocs.io/en/latest/usage.html#continuing-a-session beschrieben und das anzureichern mit den Infos, was in dem Zusammenhang an intents aktiviert bzw. deaktiviert wurde. (Soweit alles klar, oder... ::) ??? ::) )
Vermutlich habe ich dabei auch den Grund gefunden, warum "ConfirmAction" (mit dem kurzen "nein") immer funktioniert hat, obwohl es vermeintlich deaktiviert war: Der Deaktivierungsbefehl ging wohl schlicht an die falsche Adresse :o . Nach ersten Tests ist das jetzt "besser" (wobei ich nicht sicher bin, ob das "Ableiten" der Stille nach "SilentCancellation" nicht allgemein eine gute Idee ist, aber das wäre dann eine andere Diskussion), aber alles in allem ist es schlicht und ergreifend so, dass die ganzen Änderungen so massiv sind, dass ich für's erste schon mal froh wäre, das mit der "simplen" Bestätigung würde wieder funktionieren (ich kann's voraussichtlich frühestens morgen irgendwann testen, bin aber optimistisch, nach meinen erfolglosen Tests noch ein paar Lücken geschlossen zu haben. Testen aber bitte auf einer Test-Installation!).

Für die "welcher Raum"-Abfrage könnte man dann da auch die im ersten Durchgang erkannten Raum- (oder Device-) Optionen mit reinpacken und so feststellen, ob die Wahl zur Frage paßt usw.....

Und weil man ja bei einer entsprechenden Abfrage auch was zur Auswahl anbieten muss, gibt es jetzt nicht nur einen "Hauptnamen" ("alias" im Hash) für jedes Device, sondern auch einen "Haupt-Raum" - nämlich der erste, der in "rooms" zu finden ist (wer mit rhasspyRooms arbeitet, kann das also beeinflussen). Beides ergibt dann wieder je einen slot, damit wir den für die noch deaktivierten weiteren Intents dann schon mal haben.

Vermutlich ist dann der "DialogManager" immer noch zu simpel, weil man "eigentlich" überwachen müsste, für welche Intent-Satellit-Kombi denn grade welcher andere Intent aktiviert ist bzw. deaktiviert werden soll, aber a) ist auch das wieder "nun ja", b) sind die potentiellen Problemfälle tendenziell deutlich weniger und c) bin ich nicht sicher, ob da überhaupt noch eine logische Lücke ist.



ZitatIrgendwie müssen wir die neue siteId in den Slot Rooms bringen
Das mit satellite2room für "Missmatches" habe ich gesehen, bin aber noch nicht sicher, ob es wirklich sinnvoll ist, die Satellitennamen (bzw. Teile davon bei Gruppen?) automatisch den Räumen hinzuzufügen. Ich _vermute_, dahinter steckt in aller Regel ein Konfigurationsproblem, das ggf. durch das "siteId2room"-Reading gelöst werden kann, falls man die Benennung des Satelliten nicht anfassen will. Bin aber grade nicht sicher, ob das für die Timer-Anlage auch gilt.

EDIT: Bisher keine Abstürze, dafür m.E. halbwegs konsistente Datenübergaben an Rhasspy... (Aber kein Dialog.)

EDIT 2: Dialoge laufen jetzt wieder. Fyi: customData hat sich als Problem erwiesen. Wenn man das nutzt, bekommt man mind. an der Handy-App keine Tonausgabe. Die Daten werden daher jetzt wieder intern gepuffert, aber nicht mehr unter einem "Einheitsnamen", sondern unter der Session-ID. Damit sollte nun der Weg frei sein für sowas wie eine "welches Schweinderl..."-Abfrage :) .
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Beta-User

#573
Soooo....

Jetzt geht auch das mit der Device-Wahl, wenn es mehrere gibt. Der Haken: Man muss den Intent "treffen".

Erst mal die weiteren sentences:

[de.fhem:ChoiceRoom]
nimm das Gerät aus ( dem | der ) $de.fhem.MainRooms{Room}

[de.fhem:ChoiceDevice]
ich hätte gerne das Gerät $de.fhem.Aliases{Device}

Muss jetzt erst mal noch checken, ob die Choice-Intents wirklich sauber deaktiviert werden, dann könnte man es ggf. auf das Schlagwort reduzieren, aber der Rhasspy-Teil ist immer noch etwas "black box".

Das ganze ist auch etwas "langatmig", von daher wird der eine oder andere das vermutlich (teilweise?) deaktivieren wollen (z.B. begrenzen auf die Raumauswahl). Aber wie war das mit "Rom" und so...?

(und zur Sicherheit CancelAction etc.):
[de.fhem:ConfirmAction]
(ja mach | tu es | ist ok | aber gerne doch){Mode:OK}
(lieber doch nicht ){Mode}

[de.fhem:CancelAction]
(lass es | nein | abbrechen | abbruch ){Mode:Cancel}
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

drhirn

Morgen Jörg,

noch nichts getestet bisher. Kam nicht dazu.
Aber eine Frage in Bezug auf deinen Beitrag im Developer-Bereich: Reicht dir die SessionId von Rhasspy nicht als Identifier? Die wird ja durch den ganzen Dialog mitgeschleppt. Sollte zumindest. Und wofür brauchen wir eigentlich die Timer?

Beta-User

Zitat von: drhirn am 03 Mai 2021, 08:19:27
noch nichts getestet bisher. Kam nicht dazu.
Kein Ding, hat ja keine Eile.

Bin zwar sehr zufrieden, dass das jetzt "an und für sich" läuft, aber nicht unbedingt mit den "praktischen Ergebnissen" ::) . Beispiel: Im WZ sind  zwei Thermostate und ein Raumfühler vorhanden. Wenn alles sauber läuft, sind die Ist-Temparaturen an den Thermostaten identisch mit dem Raumfühler (es kann kurzzeitige Abweichungen geben). Jetzt wird man aber immer gefragt, welcher es denn sein soll, was in der Konstellation einfach unnötig ist. Denke, es braucht eine Möglichkeit, "prios" zu vergeben, und das vermutlich noch getrennt für "inside" und "outside room"...
(Aber Rom und so)

Zitat
Aber eine Frage in Bezug auf deinen Beitrag im Developer-Bereich: Reicht dir die SessionId von Rhasspy nicht als Identifier? Die wird ja durch den ganzen Dialog mitgeschleppt. Sollte zumindest. Und wofür brauchen wir eigentlich die Timer?
Ja, die SessionId ist ausreichend, und die wird jetzt auch verwendet. Die Timer sind dazu da, dass RHASSPY die Dialoge dann abschließt, wenn zu lange nicht passiert (auch da braucht es vermutlich noch eine Schnittstelle für die Dauer der timeouts, getrennt nach "ja/nein" und "welches Schweinderl...".
Das Problem ist, dass verschiedene Satelliten _gleichzeitig_ Dialoge offen haben können, also muss der Timeout-Funktion bei Ablauf mitgegeben werden, welcher Dialog/welche SessionId eigentlich gerade zu schließen ist.

(Das Problem ist nicht, dass das nicht funktionieren würde, die Frage ist eher die, ob das "clever" gelöst ist, wie es jetzt gelöst ist und ob man die Funktionen ggf. auslagern sollte, damit andere, die _genau_ diese Art Problemstellung auch haben, einfach die betr. Funktionen einbinden können...).
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

drhirn

Dann hab ich das eh richtig verstanden mit den Timern. Aber, beendet nicht Rhasspy selbst den Dialog (bzw. die Session), wenn nichts kommt?

Beta-User

Zitat von: drhirn am 03 Mai 2021, 09:05:26
Aber, beendet nicht Rhasspy selbst den Dialog (bzw. die Session), wenn nichts kommt?
Hmm, vermutlich...
Allerdings wenn, dann erst nach ziemlich langer Dauer, was mir danach klingt, also wäre es besser bzw. von vornherein eigentlich so gedacht, das auf Seite des Dialog-Partners (also RHASSPY) zu lösen. Kann aber sein, dass das falsch ist (habe aber auch keine Option gesehen, den Timeout für Rhasspy ggf. zu beeinflussen), und es gibt dann auf alle Fälle eine Art Lücke:
Es werden bestimmte Intents ja erst freigeschaltet (bzw. das ist jedenfalls so beabsichtigt), wenn überhaupt passende Fragen bestehen. Wird der Dialog geschlossen (von wem auch immer), sollte das auch wieder auf die Default-Werte. (Im Moment passiert das über den timeout, so dass ggf. dann trotzdem noch irgendwas ausgegeben wird, aber das ist m.E. zumindest im Moment kein echtes Problem).
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Beta-User

#578
...vor lauter Analyse des Timer-Codes sind mir dann noch ein paar "kleinere" Unsauberkeiten aufgefallen, die hoffentlich nebenwirkungsfrei beseitigt sind...
(Der Code an sich verschickt jetzt zwar die Daten vermutlich richtig (ich konnte keine "working examples" dazu finden), aber soweit ich das verstanden habe, ist Rhasspy gar nicht in der Lage, z.B. Intents@runtime zu (de-) aktivieren... Kann also sein, dass die jetzige Fassung aus diesem kühnen Grunde nicht optimal ist, v.a., wenn Rhasspy zwischendurch mal trainiert wird ??? .)
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

drhirn

Ich hab gerade einen kleinen Punkt für die ToDo-Liste gefunden: Ist ein "genericDevice" z.B. im FHEM-Web-Raum "schlafzimmer->temperatur" ist es das natürlich auch für Rhasspy. Das wird relativ kompliziert mit der Aussprache :D

Beta-User

 :) Das ist aber nur solange ein Problem, wie kein rhasspyRoom gesetzt ist, oder?

Oder ist das ToDo das, den "->" per default durch ein Leerzeichen zu ersetzen? (Wäre auch keine große Sache).
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

drhirn

Genau. Lösung ist, einen rhasspyRoom zu setzen.

Ich weiß leider nicht, wie andere die Möglichkeit mit dem -> nützen. Drum kann ich auch nicht sagen, was man am Besten damit tun sollte. Spontan hätte ich eiskalt alles ab -> abgeschnitten. Aber wie gesagt, das täte nur mit meiner Logik funktionieren.
Beim dritten Nachdenken drüber: Lassen wir's, wie's ist.

drhirn

Ich hab jetzt schon das zweite "thermometer", bei dem ich nicht auf Luftfeuchtigkeit abfragen kann. Im "list" sieht das gut aus, aber Matches werden keine gefunden.

         enoTemperaturAussen01:
           alias      temperatur
           groups     aussentemperatur
           names      temperatur
           rooms      draußen
           intents:
             GetNumeric:
               humidity:
                 currentVal humidity
                 type       humidity
               temperature:
                 currentVal temperature
                 type       temperature



2021.05.03 16:46:49 5: RHASSPY: [Rhasspy] Parse (IO: rhasspyMQTT2): Msg: hermes/intent/de.fhem_GetNumeric => {"input": "airHumidity draußen", "intent": {"intentName": "de.fhem:GetNumeric", "confidenceScore": 1.0}, "siteId": "wohnzimmer", "id": null, "slots": [{"entity": "Type", "value": {"kind": "Unknown", "value": "airHumidity"}, "slotName": "Type", "rawValue": "wie hoch ist die luftfeuchtigkeit", "confidence": 1.0, "range": {"start": 0, "end": 11, "rawStart": 0, "rawEnd": 33}}, {"entity": "de.fhem.Room", "value": {"kind": "Unknown", "value": "draußen"}, "slotName": "Room", "rawValue": "draußen", "confidence": 1.0, "range": {"start": 12, "end": 19, "rawStart": 34, "rawEnd": 41}}], "sessionId": "wohnzimmer-porcupine_raspberry-pi-611d2436-64b9-4ea3-9f96-172a7c4aa08c", "customData": "porcupine_raspberry-pi", "asrTokens": [[{"value": "airHumidity", "confidence": 1.0, "rangeStart": 0, "rangeEnd": 11, "time": null}, {"value": "draußen", "confidence": 1.0, "rangeStart": 12, "rangeEnd": 19, "time": null}]], "asrConfidence": 0.99112795, "rawInput": "wie hoch ist die luftfeuchtigkeit draußen", "wakewordId": "porcupine_raspberry-pi", "lang": null}
2021.05.03 16:46:49 5: Parsed value: airHumidity draußen for key: input
2021.05.03 16:46:49 5: Parsed value: airHumidity for key: Type
2021.05.03 16:46:49 5: Parsed value: wohnzimmer for key: siteId
2021.05.03 16:46:49 5: Parsed value: draußen for key: Room
2021.05.03 16:46:49 5: Parsed value: wie hoch ist die luftfeuchtigkeit draußen for key: rawInput
2021.05.03 16:46:49 5: Parsed value: wohnzimmer-porcupine_raspberry-pi-611d2436-64b9-4ea3-9f96-172a7c4aa08c for key: sessionId
2021.05.03 16:46:49 5: Parsed value: GetNumeric for key: intent
2021.05.03 16:46:49 5: Parsed value: 1 for key: probability
2021.05.03 16:46:49 5: handleIntentGetNumeric called
2021.05.03 16:46:49 5: matches in room: , matches outside:
2021.05.03 16:46:49 1: PERL WARNING: Use of uninitialized value $text in concatenation (.) or string at fhem.pl line 1006.
2021.05.03 16:46:49 5:
2021.05.03 16:46:49 5: Response is: Tut mir leid, ich konnte kein passendes Gerät finden


Das hat keinen Zusammenhang mit "humidity" statt "airHumidity", oder?

Beta-User

doch, das ist das Problem.

Allerdings bin ich mir im Moment unsicher, wie man die verschiedenen Feuchtigkeiten unterscheiden soll und tendiere dazu, "humidity" mit "airHumidity" gleichzusetzen. Muss aber mal bei Gelegenheit checken, ob das irgendwie durchgängig ist...
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

drhirn

Ja, würde ich so machen. "airHumidity" klingt eh irgendwie blöd ;D