CustomIntent mit Dialog

Begonnen von gregorv, 03 Oktober 2024, 10:54:24

Vorheriges Thema - Nächstes Thema

Beta-User

Moin. In der Tat testest du viel rum, mit "Tests" war aber ausdrücklich auch pah's Testsuite gemeint, die ich vor längerem hier mal verlinkt hatte; meine Empfehlung ist wirklich, sich mal zurückzulehnen und mit diesem Hilfsmittel anzuschauen, was dein Rhasspy damit so zurückgibt :) .

Dein jüngster input ist vielschichtig, ich würde das gerne erst mal "auseinandernehmen" und erst mal einen Teil der Punkte einzeln betrachten:

Zitat von: gregorv am 17 November 2024, 00:52:35Das wäre ja nötig, wenn man timedOn aus gdt herausnimmt.
Habe jetzt mal in handleIntentSetTimedOnOff() geschaut - das macht die "on-for-timer"-Prüfung at runtime, und vielleicht hilft dir ein Blick in die Hilfsfunktion _getSecondsfromData() ;) .
my $cmd = $value eq 'on' ? $cmdOn : $cmdOff;
    $cmd .= "-for-timer";

    my $allset = getAllSets($device);
    return respond( $hash, $data, getResponse($hash, 'NoTimedOnDeviceFound') ) if $allset !~ m{\b$cmd(?:[\b:\s]|\Z)}xms;

    my (undef , undef, $secsfromnow) = _getSecondsfromData($data);

    $cmd .= " $secsfromnow";
Bin übrigens immer noch dagagen, diese Funktionalität in setNumeric auszulagern :P .

Zitat von: gregorv am 17 November 2024, 00:52:35ähnlich wie gdt das mit timedOn oder brightness macht
Das Stichwort "timedOn" finde ich im aktuellen Code nur in dem oben genannten Zusammenhang, und das Parsing der rhasspyMappings macht intern splitMappingString(). Das sieht mir eher nach einfachen key-value-Paaren aus. Die komplexere Struktur (mit den "Doppelungen" mancher Stichworte) kommt aber zum Teil nach meiner Erinnerung auch davon, dass das rhasspyMapping am Anfang zu flach war, um alle Fälle abzufangen und ich daher die eher einfacheren Fälle stärker strukturiert habe als eigentlich notwendig, damit man immer dieselbe Logik zur Auswertung hernehmen kann.
Ergo dürfte es ausreichen, die Zeile mit "option" zu beginnen und dann die drei Werte "flach" reinzuwerfen (Factor=60,RetryIntent=true,reopenVoiceInput=25)
(Ich schreibe das nur, um die sachliche Frage zu beantworten, mit dem konkreten Vorschlag bin ich aber weiter nicht einverstanden...)

Zu den einzelnen Keys:
"Factor" Da ist mir im Moment unklar, für was der sein soll. Diskutiert hatten wir das im Zusammenhang mit timern, dazu hatte ich oben was geschrieben, und ansonsten fallen mir grade nur Schrittweiten bei setNumeric ein. Da gibt es aber schon einen setztbaren Parameter, soweit ich mich entsinne.

"RetryIntent" würde ich im Moment noch zurückstellen, weil mir nicht klar ist, wann dieser Parameter konkret zur Anwendung kommen soll. Es klingt ein wenig danach: Der User spricht ein Kommando zu einem bestimmten Device, das kann aber so nicht ausgeführt werden. Der User soll eine Rückmeldung erhalten, dass es so nicht geht, und kann es direkt nochmal versuchen?
Frage: Warum soll das nicht das default-Verhalten (für solche Fälle) sein/werden?
Im Zweifel könnte man für bestimmte Fälle/devices Ausnahmen vorsehen, in denen dann doch das Mikro zugemacht wird. Klingt insgesamt nach "rhasspyTweaks" (oder "specials"). 

"reopenVoiceInput" ist imo ein sehr klarer Kandidat für solche "specials" (eher wie als "tweak"). Falls dir nicht klar ist, was ich damit meine, versuche mal den Pfad für "ConfirmAction" nachzuvollziehen (und die Beschreibung zu "rhasspySpecials"- "confirm" und "confirmValueMap".
Als Ablauf beschrieben: Du willst nicht global reopenVoiceInput haben (das wäre "continuos session" aktivieren), sondern entweder bei allen Kommandos auf ein bestimmtes Device (=>Tweak) oder bei bestimmten Kommandos auf konkrete Devices das Mikro weiter öffnen, um eine weitere Benutzersteuerung zu ermöglichen?
Also "Schalte das Radio ein" - "Gerne" - "stelle auf SWR27" - "wird erledigt" - "mach leiser" - "ok" (und Schluss).
Soweit nachvollziehbar?
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

gregorv

Da habe ich noch einiges Nachzuarbeiten und wieder was gelernt. Ich beschäftige mich heute mal mit der Testsuite.

Aber vorab noch ein paar Kommentare:
ZitatFrage: Warum soll das nicht das default-Verhalten (für solche Fälle) sein/werden?
Da hätte ich im Prinzip eigentlich nichts dagegen.
Allerdings habe ich da auch die User im Auge, die auf das neue, vmtl. unerwartete 'wie bitte?' so reagieren, wie Sie es gewohnt sind, nämlich das Wake-Word sprechen um dann das Kommando zu wiederholen.
Schlecht ist dann, das die erwartete Reaktion auf das Wake-Word ausbleibt und statt dessen so lange mit 'wie bitte?' quittiert wird, bis der sessionTimeout abgelaufen ist. Damit inerhalb vom sessionTimeout das Wake-Word funktioniert, muss es einen sentence mein-wake-word{resetInput} geben.

An dieser Stelle habe ich noch einen Fehler im Code gefunden.
Die Zeile if ( !$data->{input} || defined $data->{customData}->{RetryIntent} ) { in der handleIntentNotRecognized()
muss durch
if ( !$data->{input} || (ref $data->{customData} eq 'HASH' && defined $data->{customData}->{RetryIntent} ) ) {ausgetauscht werden, sonst chrasht es wenn IntentNotRecognized direkt nach dem Wake-Word kommt (customData ist dann ein Text).
Als Key hatte ich RetryIntent gewählt, weil es exakt mit der Id für die responses im language file übereinstimmt. Es sollte als Key allerdings mit lower case starten, also retryIntent - falls es nicht immer aktiv werden soll.

ZitatHabe jetzt mal in handleIntentSetTimedOnOff() geschaut...
Ich jetzt auch - ein paar interessante Anregungen drin, aber mit diesem Intent bin ich nicht so recht zufrieden.

  • timedOnOff (on/off-for-timer) ist m.E. sehr nah verwandt mit Type brightness. Insofern ist es  nach meinem Empfinden inkonsistent das einerseits brightness in der handleIntentSetNumeric() behandelt wird, aber für on/off-for-timer ein besonderer Intent (handleIntentSetTimedOnOff()) gewählt wurde. Warum wurde beides unterschiedlich realisiert ?
  • Zudem denke ich das die Performance ungünstiger ist. Was getAllSets() genau macht (in welcher pm ist das?), weiß ich zwar nicht, aber ich bin fast sicher, dass es aufwändiger ist, als im gdt mapping nachzusehen - ganz abgesehen davon dass dann auch noch das Resultat nach cmd durchsucht wird - das sind bei mir 34KB.
  • Weiterhin ist mir aufgefallen, dass die Prüfung nach cmd nicht notwendigerweise sicherstellt (hat brightness auch), dass das Device auch on-for-timer kann. Selbst wenn man nach on-for-timer suchen würde, ist nicht sicher ob es auch off-for-timer gibt.
Zumindest denke ich, dass man sich für gtd Mapping (wird nur beim Start ausgeführt) oder die runtime Variante mit getAllSets() entscheiden sollte.

Das ist aber nur mein erster Eindruck - subjektiv gefärbt. Im übrigen denke ich bei meinen Ideen für die handleIntentSetNumeric() eher an eine mögliche handleIntentGeneric(), wo aber die handleIntentSetNumeric() eine gute Vorlage sein könnte.

Beta-User

Kurz zu timedOnOff: das getAll... wird u.a. von FHEMWEB verwendet, und es wird auch erkannt, was das Device wirklich kann (off-for...).

M.E. gibt es wirklich keinen Grund, das anders abzufackeln. Historisch gewachsenen, ja. Aber OK. Fertig dazu.
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

Hast du mal deinen aktuellen Code im Zusammenhang (pm als Anhang)? Ist vermutlich einfacher, wenn ich deine pm gegen svn/meinen Code von neulich automatisiert vergleichen kann...

Zitat von: gregorv am 17 November 2024, 12:55:43Da hätte ich im Prinzip eigentlich nichts dagegen.
Allerdings habe ich da auch die User im Auge, die auf das neue, vmtl. unerwartete 'wie bitte?' so reagieren, wie Sie es gewohnt sind, nämlich das Wake-Word sprechen um dann das Kommando zu wiederholen.
Na ja, Usergewohnheiten kann man ändern ;) . In der Regel kommen die recht gut damit klar, wenn es nachvollziehbar ist und eher einfacher geworden.
Den Teil würde ich daher per default aktivieren, wir müßten dann eben nur eine Option (Tweak?) vorsehen, um das bisherige Verhalten beizubehalten. Vorgewarnt sind die (FHEM konfigurierenden) User ja ;) .

Zitat von: gregorv am 17 November 2024, 12:55:43timedOnOff (on/off-for-timer) ist m.E. sehr nah verwandt mit Type brightness.
Wo siehst du die Parallele? Historisch entwickelt hat sich der Intent aus einer Mischung von "OnOff" und "SetTimer", und ich finde den "Ausgangspunkt" (also eine gesprochene Anweisung eines Nutzers) hinreichend klar abgegrenzt, dass man dafür durchaus weiter einen eigenen Intent bereithalten kann. Verbessern vielleicht (v.a. dahingehend: "Mach das Licht um 12 Uhr für 10 Minuten an"), aber prinzpiell ist das m.E. ansonsten wirklich "fertig" und bedarf auch (aus mehreren Gründen, die hier fast* alle schon genannt waren) keiner weiteren Code-Optimierung. *Die meisten Devices, die ich hier als OnOff-Devices habe, kennen auch (verschieden implementierte) on-for-timer-Anweisungen. Von daher reicht m.E. auch die "Eingangsabgrenzung" auf diese Gerätegruppe in meinen sentences.ini, um nicht allzu viele "false positives" zu generieren.


Eine Anmerkung noch zur Frage "at runtime" oder "vorab": Zum einen "brauchen" wir für die slots in Rhasspy jeweils sowas wie eine Liste, und zum anderen kann es wegen der diversen Mechanismen recht schwierig sein festzustellen, welches "mapping"-Attribut (gdt/rhasspyMapping/Tweaks/Specials) im Endeffekt greift und wie berücksichtigt wird. Von daher finde ich die Konsolidierung am Anfang schon sinnvoll, selbst wenn es effektiv (Sprachanweisungen sind ja eher selten!) bei der Umsetzung von Anweisungen in Aktionen praktisch kaum einen fühlbaren Performance-Vorteil bieten dürfte. Andererseits will ich den RHASSPY-Hash nicht wegen "seltener Fälle" unnötig weiter aufblähen.
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

gregorv

ZitatDen Teil würde ich daher per default aktivieren
Auch OK, allerdings sollte das dann immer funktionieren. Unmittelbar nach einem Wake-Word geht es derzeit nicht.
Wenn die Bedingung RetryIntent nicht mehr da ist, wird die sub ja immer an dieser Stelle beendet - wahlweise silent oder mit Ansage RetryIntent (wenn in Input was drin steht).
Eventuell kannst Du mal checken, unter welchen Bedingungen die sub weiterlaufen muss.

Ich musste mein Modul gerade noch etwas aufräumen:

gregorv

ZitatWo siehst du die Parallele? Historisch...
Oh... ich wollte die handleIntentSetTimedOnOff() nicht abschaffen. Die Behandlung von dem 'echten' on/off-for timer ist da ja eigentlich nur eine Nebenfunktion - der Name war für mich etwas irreführend
Die Verwandtschaft sehe ich in dem Commandset für brightness und timedOn und der Bearbeitung numerischer Werte in beiden.

Zitatwird auch erkannt, was das Device wirklich kann (off-for...).
Ja, das stimmt, aber handleIntentSetTimedOnOff() schaut nur nach cmd und setzt dann voraus, dass die eigentlichen Kommandos funktionieren.

Kannst Du mir sagen in welchem modul die rhasspyXxx Optionen gelesen werden, dann schau ich mal wie man erreichen kann, dass z.B. reopenVoiceInput in $data übertragen kann.




Beta-User

Zitat von: gregorv am 18 November 2024, 12:38:00Kannst Du mir sagen in welchem modul die rhasspyXxx Optionen gelesen werden, dann schau ich mal wie man erreichen kann, dass z.B. reopenVoiceInput in $data übertragen kann.
Deswegen hatte ich direkt die Schlüsselwörter genannt
Zitat von: Beta-User am 17 November 2024, 09:15:10"ConfirmAction" [...] "rhasspySpecials" - "confirm" und "confirmValueMap"
Eingelesen werden die über Attr() bzw. _analyze_rhassypAttr() (in dener Fassung ab Zeile 1097), ausgewertet dann jeweils an der erforderlichen Stelle.
Zitat von: gregorv am 18 November 2024, 12:38:00Ja, das stimmt, aber handleIntentSetTimedOnOff() schaut nur nach cmd und setzt dann voraus, dass die eigentlichen Kommandos funktionieren.
$cmd wird erweitert. Allerings habe ich grade gemerkt, dass das dann schwierig wird, wenn man unbeding "An" oder "Aus" als xxCmd haben will: "An-for-timer" wird in der Regel tatsächlich nicht exisiteren...

Zitat von: gregorv am 18 November 2024, 12:38:00Die Verwandtschaft sehe ich in dem Commandset für brightness und timedOn und der Bearbeitung numerischer Werte in beiden.
Na ja, das kann man zwar so sehen, aber bei Timern sind "numerische Werte" eigentlich immer Vielfaches von einer ganz speziellen Basisgröße, nämlich Sekunden. Und zum Umgang mit dieser Art von Werten gibt es eine spezielle Hilfsfunktion, um daraus was "maschinenlesbares" (aka Sekunden) zu machen...

Mir ist schon klar, dass das unglaublich viel Code ist, den du da versuchst auf einmal zu verstehen, und du machst das auch sehr aber gut! Aber offen gesagt irritiert es mich, wenn ich mir doppelt die Mühe machen muss, sowas wie das mit "from my side: no changes in timedOn" mehrfach zu erklären oder (abgesehen von Kleinigkeiten wie dem "Auf-for-timer") zu verteidigen.
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

#172
Bin mal über deine pm drüber.

Ein paar Sachen sollten wir klären, in order of appearance in code:
- "pos" - Was sind das für Devices (TYPE)? Das sieht mir auch irgendwie "generisch" aus, und ich befürchte Verwechslungen (können wir uns dann drum kümmern, wenn das der Fall ist). Kommt aber erst nach pct, dann wird das vorrangig verwendet, falls beides geht. Schwierigkeiten damit?

- zu "defined $data->{customData}->{reopenVoiceInput} ) ) { # GV: ich würde vorschlagen, [...]" Da ist mir der Grund noch unklar, warum der timeout nicht in "SilentClosure" stehen dürfte? Anmerkung: Der Zweig ist insgesamt noch nicht "ausgereift", m.E. sollten wir erst klären, wann woher welche Keys (und Werte) kommen können/sollen. Dass das aus den sentences.ini kommt, dürfte künftig eher die Ausnahme sein.

- das activateVoiceInput() direkt danach stammte aus der Überlegung, dass uU. das Mikro nicht automatisch vom SessionManager aufgemacht werden könnte. Wenn wir ohne das direkt was sprechen können, ist es ok, wenn wir das an der Stelle raus nehmen.

- 'my $json = toJSON($sendData); # @@@ error with "true"' müssen wir klären: _toCleanJSON() gibt es nämlich deswegen, weil Rhasspy Probleme mit puren "toJSON()"-Anweisungen hatte. Ergo müssen wir das m.E. auf der RHASSPY-Empfangsseite klären, wie wir das mit der "1" abgefangen bekommen. In dem Zusammenhang kann es uU. auch einen großen Unterschied machen, welcher JSON-Decodierer de facto aufgerufen wird mit JSON->new->decode().

- zu
if ( ! defined $mapping->{$change} ) { # @@@
        $cmd     = $mapping->{cmd} // return defined $data->{'.inBulk'} ? undef : respond( $hash, $data, getResponse( $hash, 'NoMappingFound' ) );
    }
Zum einen meine ich, dass man die Eingangsbedingung erweitern müßte:
if ( !defined $change || !defined $mapping->{$change} ) {(das führt sonst uU. dazu, dass es ab der 2. Anfrage definiert ist... (Edit: Wir arbeiten an der Stelle mit einer Kopie und nicht mit dem Original (ref), das sollte also effektiv kein Thema sein))
Aber wichtiger: Mir ist nicht klar,
a) was bei "seltsamen" change-Anweisungen passieren würde und
b) wie der Code mit ".inBulk"-Fällen umgeht.
Hast du dazu Infos, bevor ich mir da theoretisch was zusammenfieseln muss?

Trockenübungs-Revision anbei ;D .
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

gregorv

Zitat"pos" - Was sind das für Devices (TYPE)?
Das sind Dooya Rolladen Steuerungen als Type ist ja SetTarget angegeben - dass habe ich aus pct übernommen.

- zu "defined $data->{customData}->{reopenVoiceInput} ) SilentClosure hieß anfangs silent und ist gedacht, um bei einem CustomIntent, der den Dialog offen hält, die Fehleransage nach dem Ablauf des sessionTimeout (schaltbar zu unterdrücken).

M.E. kann das aber ganz entfallen. Zumindest hast Du für reopenInputVoice den timeout Ablauf ja generell stumm gemacht.
Aber es hatte ohnehin nichts mit reopenInputVoice zu tun - insofern denke ich, dass der sessionTimeout für reopenInputVoice besser nur da auch eingestellt wird.
Dass ich ursprünglich bei silent binäre Werte übergeben hatte, sollte dazu dienen, die Stellen, die stumm sein sollen unterschiedlich einstellen zu können.

Zitatdas activateVoiceInput() direkt danach stammte aus der Überlegung, dass uU. das Mikro nicht automatisch
Ja,geht. Der Aufruf von activateVoiceInput() an dieser Stelle bewirkt das die durch den Zweig #use default hotword mechanism läuft und dann sind alle Daten weg und offenbar kommt Rhasspy durcheinender, weil keine Spracheingabe mehr angenommen wird (vermutlich weil während einer Session mit einer bestimmten siteId keine neue Session mit der gleichen siteId gestartet werden kann).
Zitatmy $json = toJSON($sendData); # @@@ error with "true"' müssen wir klären
Jep, das denke ich auch. Das Problem liegt nicht bei Rhasspy sondern entsteht beim encoden - so wie ich das auf die Schnelle gemacht hatte ist es ein Workaround, keine Lösung

ZitatAber wichtiger: Mir ist nicht klar, ...
Die Frage hatte ich erwartet - ich weiß es nicht mehr. Ich hatte viel mit Optionen und Types experimentiert, aber das kläre ich noch. Mit der Erweiterung hast Du recht - das müsste noch rein.





gregorv

#174
Thema Optionen via Specials.
Ich habe für rhasspySpecials mal den Key options eingeführt.
        if ($key eq 'options') { # @@@
            $hash->{helper}{devicemap}{devices}{$device}{options} = $named if $named;
Damit landet die Einstellung rhasspySpecials -> options:reopenVoiceInput=25 RetryIntent=true so im hash (print von device)
$VAR1 = {
  "alias" => "licht",
  "group_specials" => {
    "async_delay" => "0.5"
  },
  "groups" => "lampen",
  "intents" => {
    "GetOnOff" => {
      "GetOnOff" => {
        "currentVal" => "state",
        "type" => "GetOnOff",
        "valueOff" => "off"
      }
    },
    "SetNumeric" => {
      "timedOn" => {
        "cmd" => "on-for-timer",
        "currentVal" => "timedOn",
        "type" => "timedOn"
      }
    },
    "SetOnOff" => {
      "SetOnOff" => {
        "cmdOff" => "off",
        "cmdOn" => "on",
        "type" => "SetOnOff"
      }
    }
  },
  "names" => "licht,lampe,b\303\274ro licht",
  "options" => {
    "RetryIntent" => "true",
    "reopenVoiceInput" => 25
  },
  "rooms" => "arbeitszimmer,b\303\274ro"
};
(ganz unten in der Sektion options)
In handleIntent muss der Inhalt dann in $data geschrieben werden:
    my $options = $hash->{helper}->{devicemap}->{devices}->{$device}->{options}; # @@@
    for my $key (keys %{$options}) {
        $data->{$key} = $options->{$key};
    }
Da der Device Name (zumindest bei handleIntentSetNumeric()) erst da drin ermittelt wird, kann man die options erst danach lesen und in $data anhängen.
Vermutlich kennst Du eine Lösung, wie man das schon in der analyzeMQTTmessage() machen kann - dann braucht man die handleIntent...() Prozeduren nicht mit redundantem Code füllen)

Was mir aber noch fehlt, wäre die Möglichkeit das bei dem Rhasspy Modul zu setzen, damit das gleich für alle einschalten kann - rhasspySpecials funktioniert da offenbar nicht. Jedenfalls sehe ich im hash keine Spur von meinen versuchten Settings (für async_delay wäre das auch nicht schlecht, wenn man das da setzen könnte). Hast du da eine Idee?

Ein Dummy device mit Namen 'options' wäre zwar möglich, würde mir aber gar nicht gefallen.

Beta-User

#175
Zitat von: gregorv am 18 November 2024, 22:48:02Thema Optionen via Specials.
Wir kommen voran :) .

Zum Verständnis: "specials" und "tweaks" in meiner Terminologie sind nach meinem bisherigen Verständnis dasselbe wie das, was du unter "options" verstehst. Anders gesagt: Jedes "special" ist bereits eine "option" auf Device-Ebene, ein "tweak" ist das, was du ggf. notfalls in einem Dummy (bäh) unterbringen wolltest ;) . (Nachtrag: Es braucht m.E. daher auch keine weitere Abstufung im RHASSPY-Hash nach "options" oä.)

Als Ziel würde ich für "specials" bzw. "tweaks" in etwa so eine Notation sehen:
attr blind1 rhasspySpecials reopenVoiceInput:SetOnOff=50 SetNumeric:30
RetryIntent:SetNumeric
attr rhasspy rhasspyTweaks reopenVoiceInput=SetOnOff=blinds:35Das Beispiel sollte - erst mal nur bezüglich der reopen-Angaben, "retry" würde ich erst mal noch zurückstellen - in etwa das bewirken, was du mit deinem "blinds"-Intent vorhattest: Wenn man nur "auf" oder "zu" anweist (über SetOnOff), geht das Mikro wieder allgemein für 30 Sekunden auf (tweak), es sei denn, es gäbe dazu was auf Device-Ebene, z.B. weil "blind1" eine Jalousie ist, die sehr viel längere Laufzeiten hat wie die übrigen Rollläden. Für setNumeric würde dann eine etwas kürzere Zeit gelten.

Zitat von: gregorv am 18 November 2024, 22:48:02wie man das schon in der analyzeMQTTmessage() machen kann - dann braucht man die handleIntent...() Prozeduren nicht mit redundantem Code füllen)
Sowas geht (leider?) nur, wenn man es (weiter erst mal nur bzgl. reopen) innerhalb der Intent-Verarbeitung abarbeitet, von daher würde ich das halt in eine eigene sub auslagern - ganz analog zu dem, was mit "confirm" bereits vercoded ist, nur dass man vermutlich besser die Referenz auf den $data-Hash weitergibt und den innerhalb der sub ergänzt (gefahrgeneigt!).

Ist jetzt klarer, wie es von meiner Seite gedacht ist?


Zitat von: gregorv am 18 November 2024, 22:48:02async_delay wäre das auch nicht schlecht, wenn man das da setzen könnte
Im Moment bin ich der Ansicht, dass wir nicht noch weitere Baustellen aufreißen sollten. Ich fahre hier ein ziemlich gemischtes setup, und was "gleichzeitig" geht, ist sehr individuell. Wenn man es "global" aktivieren könnte, fürchte ich, dass potentielle User genau das machen - und dann nicht mehr darauf achten, was eigentlich individuell sinnvoll wäre ;) . Das ist nämlich oft was ganz anderes, wie man vielleicht zuerst denken würde...

Zitat von: gregorv am 18 November 2024, 22:15:43Das sind Dooya
Habe zum Code an sich - bis auf die Reihenfolge im Code - keine Einwände, es kommt mir nur "speziell" vor, so dass ich gerne im Code vermerken würde, wo es herkommt und in der Form paßt. Dann kann man ggf. anhand des TYPE weiter verzweigen, wenn jemand mit was anderem kommt ;) .


Zitat von: gregorv am 18 November 2024, 22:15:43SilentClosure hieß anfangs silent und ist gedacht, um bei einem CustomIntent, der den Dialog offen hält, die Fehleransage nach dem Ablauf des sessionTimeout (schaltbar zu unterdrücken).
OK, dann muss das "Kind", das da in meinem Hinterkopf rumspukt vermutlich anders heißen: In dem Moment, in dem wir den default dahingehend ändern, dass das Mikro eher wieder für weitere Ansagen offen bleiben soll, braucht es eine Option, das Verhalten aktiv abzuschalten. Das kann per expliziter Ansage erfolgen (=>sentences.ini-Key, insbes. für "CancelAction"), oder eben pro Intent oder Gerät (tweak / special)?


Das mit toXyJSON() muss ich mir gesondert auch auf der MQTT-Ebene mal ansehen. Wird dauern.
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

gregorv

Rückfrage zur Funktionsweise:
attr rhasspy rhasspyTweaks reopenVoiceInput=SetOnOff=blinds:35Auswirkung: setzt reopenVoiceInput=35, aber nur, wenn gerade ein SetOnOff Intent behandelt wurde und das Device zur Gruppe blinds gehörte.

Alternativ aber auch möglich:
attr rhasspy rhasspyTweaks reopenVoiceInput:35um das sozusagen global (für diese RHASSPY Instanz) zu aktivieren

Oder auch Einschränkungen wie nur für blinds oder nur für SetOnOff Intents:
[code]attr rhasspy rhasspyTweaks reopenVoiceInput=blinds:35
Im hash sollte das dann so aussehen:
    "tweaks" => {
      "reopenVoiceInput" => {
        "SetOnOffGroup" => {
          "blinds" => 35
...
oder auch alternativ:
    "tweaks" => {
      "reopenVoiceInput" => 35
...

Ziel ist am Ende, dass, unter Berücksichtigung eventueller Einschränkungen (blinds ond/oder SetOnOff), "reopenVoiceInput" => 35 in $data steht und wie bisher geprüft wird.
reopenVoiceInput ist da natürlich ein unpassendes Beispiel weil man das in der Regel wohl immer aktiv haben will oder eben nicht, aber ich möchte nur wissen, ob ich das Funktionsprinzip von Tweaks richtig verstanden habe.


Beta-User

Zitat von: gregorv am 19 November 2024, 12:01:59möchte nur wissen, ob ich das Funktionsprinzip von Tweaks richtig verstanden habe.
Das ist ziemlich genau das, was ich mir vorgestellt hatte. Über die konkrete Funktionsweise bzw. in welchen Fällen was ggf. sinnvoll ist, sollte natürlich vorab Klarheit herrschen, das ist jetzt erst mal "ins Unreine" formuliert, um einen Eindruck von den Möglichkeiten zu geben, die sich da ggf. eröffnen könnten.

Anmerkungen noch:
- "tweak" und "special" haben in vielen Fällen denselben Zweck (so wäre es auch hier), und eine (funktionsgleiche) Angabe in "special" hat dann ggf. Vorrang.
- wenn etwas "immer" gelten soll, steht in tweak/special in der Regel irgendwo ein "all". Anders gesagt: defaults schreibt man ggf. nach "all", und schaut dann, ob es was spezielleres gibt oder "all" gelten soll.

Also in der Richtung:
 
"tweaks" => {
      "reopenVoiceInput" => {
        "all" => 35
...
(kann sein, dass man ein "doppeltes all" braucht, um bestimmte Kombinationen abzubilden, mal sehen.)
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

gregorv

#178
Ich fasse hier mal zusammen, was es für neue Parameter gibt und deren Funktion
  • reActiateVoiceInput = nn:      -> sonst noch was? Funktion
Einstellung: in der Rhasspy Konfiguration am Ende eines sentence []{reActiateVoiceInput=nn} anhängen (gilt dann nur für dieses Kommando).
Besser Alternativ: in FHEM rhasspyTweaks die Zeile reActiateVoiceInput=all=nn (gilt immer). Statt all sind auch andere Bedingungen einstellbar. SetOnOff bewirkt z.B., dass 'sonst noch was' nur für SetOnOff Intents eingeschaltet ist. Welche Bedingungen einstellbar sind wird später noch beschrieben.
bewirkt, dass nach der Behandlung eines Kommandos die Session für die Dauer von nn Sekunden offen bleibt.
Nach jedem Kommando wird der Timer neu gestartet. Erfolgt kein Kommando mehr, wird die Session nach Ablauf der Zeit beendet still beendet.
Wenn ein Kommando nicht verstanden wurde, wird die Session beendet - außer man kombiniert mit der wie bitte? Funktion.
Szenario: Wenn man ohne erneutes Wake-Word noch andere Kommandos geben will.
Zusätzlich: Es wurde die responseId ContinueSession in der rhassp-de.cfg hinzugefügt, unter der man Alternativen für den Text "Sonst noch was?" einstellen kann.

  • retryInput = true              -> wie bitte? Funktion
Einstellung: in der Rhasspy Konfiguration am Ende eines sentence  []{retryInput=true} anhängen (gilt dann nur für dieses Kommando).
Besser Alternativ: in FHEM rhasspyTweaks die Zeile retryInput=all=true (gilt immer). Statt all sind auch andere Bedingungen einstellbar.
bewirkt, dass wenn ein Kommando nicht verstanden wurde, statt der Standardansage die Ansage wie bitte? und der Dialog offen bleibt, damit man das fehlerhafte Kommando ohne erneutes Wake-Word korrigieren kann. Die Dauer, die der Dialog offen bleibt wird von dem Timeout bestimmt, der beim Start einer Session gesetzt wurde und verlängert sich durch wie bitte? nicht.
Zusätzlich: Es wurde die responseId RetryInput in der rhassp-de.cfg hinzugefügt, unter der man Alternativen für den Text "wie bitte?" einstellen kann.

  • noResponse = true:            -> Standard Antwort eines Intent unterdrücken, nur sinnvoll, wenn reActiateVoiceInput oder retryInput aktiv ist.
bewirkt, dass nach Abarbeitung eines Intent keine Ansage erfolgt.
Einstellung: in der Rhasspy Konfiguration am Ende des betreffenden sentence für etwas höher, leiser, heller ... noch []{noResponse:true} anhängen.
Szenario Bei einer Steuerung von Lampen oder Rollläden können so Kommandos wie 'etwas heller' oder 'etwas runter' / 'Stop' ggf. mehrfach hintereinander gegeben werden, ohne dass man auf das Ende einer Ansage warten muss. Wenn diese Art Kommandos gegeben werden, sieht/hört man ja das Ergebnis.

  • closeSession                      ->sei still Funktion, nur sinnvoll, wenn reActiateVoiceInput oder retryInput aktiv ist.
Einstellen: in der Rhasspy Konfiguration einen weiteren sentence z.B. (fertig|sei still){closeSession:true} unter CancelAction einfügen.
Funktionserweiterung für CancelAction bewirkt, dass die laufende Session mit einer anderen Ansage (responseId CloseSession) beendet wird.
Szenario: es ist gerade eine Session offen z.B. durch reopenVoiceInput und das Telefon klingelt. Rhasspy hört dann gerade auf ein Kommando und wird ständig dazwichen reden, während man sich unterhält. Mit dem Kommando 'sei still' kann man Rhasspy zum schweigen bringen als Antwort erhält man nicht das unpassende 'habe abgebrochen' sondern z.B. ein kurzes 'OK'
Zusätzlich: Es wurde die responseId CloseSession in der rhassp-de.cfg hinzugefügt, unter der man Alternativen für den Text "OK" einstellen kann.

  • resetInput                      -> Alles auf Anfang
Einstellen:  in der Rhasspy Konfiguration den sentence Wake-Word{resetInput} bei irgend einem Intent einfügen.
bewirkt, dass sofort eine neue Session gestartet wird, wenn das Wake-Word gesprochen wird. Man vermeidet ein "Das habe ich nicht verstanden" oder "wie bitte", wenn man während einer laufenden Session versehentlich das Wake-Word spricht.
Szenario: es ist gerade eine Session offen z.B. durch reopenVoiceInput und das Wake-Word wird gesprochen. Wegen der offenen Sesssion ist z.B. Porcupine nicht aktiv und Rhasspy würde vergeblich versuchen einen passenden Intent zu finden. Durch resetInput kann man sein Wake-Word bei einem Intent unterbringen und Rhasspy versteht das Wake-Word als Kommando. Damit gibt es kein IntentNotRecognized mehr. Intern wird der betreffende Intent dann nicht ausgeführt, und statt dessen - wie man ja nach einem Wake-Word erwartet - eine Neue Session gestartet.

  • silentClosure = true          -> Session Ende erfolgt ohne Ansage
Einstellung: In einem hash als return eines CustomIntent übergeben.
Hauptsächlich gedacht für CustomIntents.
Wenn ein CustomIntent eine Session für eine angegebene Zeit offen hält, wird am Ende der Session die Standard Antwort unterdrückt.
Zusätzlich: es wurde die responseId SilentClosure eingeführt, die man auch als response übergeben kann und eine stille Ausführung eines Kommandos bewirkt.

Hinweis für CustomIntents:
Wenn reActiateVoiceInput eingeschaltet ist, erfolgt anschließend die Frage sonst noch was?. In dem obigen Fall möchte man das eventuell nicht haben. Bei einem CustomIntent kann man im return hash den Key reActiateVoiceInput mit dem Wert undef übergeben, um den Start einer neuen Session zu vermeiden.



Allgemein:
Alle obigen Einstellungen, die in rhasspyTweaks möglich sind, können auch als Device Einstellung unter rhasspySpecials vorgenommen werden und gelten dann nur für dieses Device. Bitte das nötige Specials-Format beachten: die Tweaks Einstellung retryInput=all=true muss bei Specials retryInput:all=true geschrieben werden (der ':'). Specials sind vorrangig vor Tweaks.
Bei der Einstellung unter rhasspyTweaks können statt all Bedingungen wie SetOnOff angegeben werden, auch kombiniert in der Form SetOnOff|SetNumeric wober die betreffende Einstellung nur für die Intents SetOnOff, bzw. SetOnOff oder SetNumeric gilt.
Mögliche Bedingungen (derzeit) sind: Intent, Group, gdt, Type, Name, Device, Room
Beispiel:
reActiateVoiceInput=light=15 -> sonst noch was? für 15 Sekunden, gilt nur für Geräte deren attr GenericDeviceType light ist.
Oder:
reActiateVoiceInput=SetOnOff=32 Lampen|Rollläden=25 -> für Intent SetOnOff gilt sonst noch was? für 32 Sekunden, ansonsten für die Gruppen Lampen und Rolläden eben 25 Sekunden.
Die erste Bedingung (von linkst nach rechts), die zutrifft, bestimmt die Zeiteinstellung.

Wer eigene Daten in als customData an Rhasspy übertragen will, kann die mit Tweaks so übergeben:
customData=myKey100=myValue100 myKey200=myValue200
oder mit Specials so:
customData:myKey1=myValue1 myKey2=myValue2
Diese Daten werden dann als JSON - String gepackt an Rhasspy weitergeleitet.


gregorv

Zu Tweaks/Specials:
Prima, dann werde ich gleich mal an die nötigen hash Einträge für Tweaks/Specials machen und mir schon mal die Funktion überlegen, die das dann in $data schreibt.
bzgl. all wäre es zumindest für die Funktion nicht nötig das mehrfach zu verschachteln - oder gibt es da schon eine Funktion, die das so erwartet ?