NEWS
Rhasspy: Sprachsteuerung für BRING!-Adapter
-
Hallo an alle Interessierten,
Mit Hilfe des von @joergeli erstellten Skripts ist es mir gelungen, den BRING!-Adapter über Rhasspy mit Sprachkommandos zu steuern und eine akustische Bestätigung zu erhalten. Voraussetung ist natürlich, dass Der BRING!-Adapter im ioBroker installiert ist und man einen BRING!-Account besitzt, dessen Daten im Adapter hinterlegt sind.
Mit diesem Teil des Skripts werden die notwendigen Vorbereitungen zur Übergabe der Sprachdaten an die TTS-API von Rhasspy vorgenommen:
// Skript zur Ausgabe von Voice über TTS an Rhasspy // Für Rhasspy-TTS: let http = require('http'); let options = { host: '192.168.13.157', //Rhasspy IP-Adresse port: 12101, //Rhasspy Port path: "/api/text-to-speech", method: 'POST', headers: { 'User-Agent' : 'ioBroker', 'Content-Type': 'text/plain', // 'Content-Length': data.length } }; //______________________________________________________________________________ function httpPost(data) { let req = http.request(options, function(res) { console.log("http Status: " + res.statusCode); // Header (Rückmeldung vom Webserver) console.log('HEADERS: ' + JSON.stringify(res.headers), (res.statusCode != 200 ? "warn" : "info")); }); // Fehler abfangen req.on('error', function(e) { console.log('ERROR: ' + e.message,"warn"); }); // write data to request body console.log("Data to request body: " + data); (data ? req.write(data) : console.log("Daten: keine Daten vorhanden")); req.end(); }
Danach folgen die Skripte, die man per Sprache steuern will. Wird eine Bestätigung per Voice (TTS) gewünscht, müssen folgende Zeilen in die jeweiligen Skripte eingebaut werden:
// Diese Zeilen jeweils in die nachfolgenden Skripte innerhalb von onID eintragen, wenn Sprachausgabe stattfinden soll data = 'Es sind momentan ' + value.val + ' Grad Celsius'; // Text und Werte ggf anpassen console.log("data: " + data); // kann man nach dem Testen auskommentieren log(value.val); // kann man nach dem Testen auskommentieren httpPost(data); //Ende
Und dann folgt noch das eigentliche Skript zur Steuerung der States des BRING!_Adapters:
// Hier Skript zum Befüllen der Einkaufslisten im Bring-Adapter var intentResult = $('mqtt.0.rhasspy.intent.SetShop*'); var intentArray = []; for(var i = 0; i < intentResult.length; i++) { log(intentResult[i]); intentArray.push(intentResult[i]); } on({id: intentArray, change: "any"}, function (obj) { log(obj.newState.val); // kann man nach dem Testen auskommentieren oder löschen let intentObject = JSON.parse(obj.newState.val); if(intentObject.hasOwnProperty('device')) { var deviceID = intentObject.device; var command = intentObject.command; var state = intentObject.state; var value = intentObject.value; log('value:'+value); // kann man nach dem Testen auskommentieren oder löschen let data = value + ' auf die Einkaufsliste gesetzt'; if(command === "false") { log('command:'+command); // kann man nach dem Testen auskommentieren oder löschen state = ".removeItem"; log('state:'+state); // kann man nach dem Testen auskommentieren oder löschen data = value + ' von der Einkaufsliste entfernt'; log("data:"+data) // kann man nach dem Testen auskommentieren oder löschen } log(deviceID + state + value); // kann man nach dem Testen auskommentieren oder löschen log('state:'+state); // kann man nach dem Testen auskommentieren oder löschen setState(deviceID + state, value); console.log("data: " + data); // kann man nach dem Testen auskommentieren oder löschen httpPost(data); } });
Auf Seiten von Rhasspy werden nun noch die Sentences und die Slots benötigt. Der Sentence für die Eingabe eines Artikels in die Einkaufsliste(n) von Bring! sieht bei mir wie folgt aus:
[SetShoppingList] ($synonyms_change_command) {command} ($shopping_item) {value} [auf] [die] ($device_name_shoppinglist) {device}(:){state:.saveItem}
Und in den Slots habe ich folgende Werte aufgenommen:
"device_name_shoppinglist": [ "(Mann | Mannsliste):bring.0.e4xxxxxxxxxx", "(haushaltsliste | einkaufsliste):bring.0.fexxxxxxxxxxxx", "(Frau | Frausliste):bring.0.92xxxxxxxxxxxx" ], "shopping_item": [ "(Butter)", "(Deo)", "(Watte)", "(Weißwein)", "(Lippenstift)", "(Shampoo)", "(Seife)", "(Rotwein)", "(Milch)", "(Käse)", "(Brot)", "(Bier)", "(Sekt)", "(Schinken)", "(Duschgel)" ], "synonyms_change_command": [ "mach:true", "schalte:true", "setz:true", "mach mal:true", "stell:true", "setze:true", "schalt:true", "stelle:true", "schliesse:false", "lösche:false", "entferne:false" ],
Anmerkung1: Die synonyms_change_command-Liste benutze ich auch zum Steuern von Lampen, Rollos usw. Deshalb enthält sie mehr Kommandos, als nur für den Bring!-Adapter notwendig.
Anmerkung 2: Die "shopping_items" müssen hier in den Slots und auch im Wörterbuch vollständig erfasst werden. Hierzu ist manuelle Pflege erforderlich, wenn mal ein Wort fehlt. Das halte ich momentan noch für machbar, auf Dauer jedoch für etwas umständlich. Vielleicht fällt ja einem ioBroker user eine elegantere Lösung ein.
Und nun viel Spaß beim Ausprobieren. Fragen und Anregungen willkommen.
Gruß, Thomas
PS: @Bluefox, @hiasii12 meine Anfrage zu MQTT hat sich damit erledigt. Vielen Dank.
-
@tobetobe
hi, vielen Dank für dein tolles Skript. Ich bekomme jedoch folgenden Fehler:javascript.0 (7578) script.js.Rhasspy.Datenpunkte_setzen_schalten): Rhasspy: Funktion ist nicht definiert --> Fehler bei Intent SetShoppingList
Bei slots "device_name_shoppinglist" habe ich folgendes eingetragen:
(haushaltsliste | einkaufsliste):bring.0.787XXXXXXXXXXXXXXX9
Der Sprachbefehl wird richtig erkannt und in die SetShoppingList gesetzt. Was eben nicht funktioniert ist das setzen des Befehls in den BRING-Adapter.
Woran könnte das liegen?
Der Fehler liegt wohl bei diesem Skript:
Woran könnte das liegen?
Hier noch das Skript des BRING-Adapters:
Muss noch das Sternchen weg bzw. muss bei Array noch was eingetragen werden?
var intentResult = $('mqtt.0.hermes.intent.SetShoppingList*'); var intentArray = [];
-
@jwerlsdf sagte in Rhasspy: Sprachsteuerung für BRING!-Adapter:
Muss noch das Sternchen weg
Hallo, sorry, dass du warten musstest. Nun konnte ich mir deine Angelegenheit einmal anschauen. Deine Skripte sind natürlich schon an deine Belange angepasst und nicht mehr identisch mit meinen. Dennoch glaube ich, etwas gefunden zu haben. Es ist wohl so, wie du vermutet hast:
var intentResult = $('mqtt.0.hermes.intent.SetShoppingList*')
Das Sternchen muss weg. In meinem Skript ist das * hinter intent. in Ordnung, weil ich damit mehrere aus Rhasspy gelieferte Intents addressiere (Licht, Temperaturen, usw). Davon ist die ShoppingList ein Intent. Somit habe ich nur EIN Skript für alle möglichen Intents.
Bei dir sieht es so aus, als würdest du das BRING-Skript auch wirklich nur für den Datenpunkt ShoppingList verwenden.
Die Frage ist somit, ob du überhaupt mehrere ShoppingList-Objekte hast, die das Sternchen und die weitere Variable "intentArray" benötigen bzw rechtfertigen. Bitte schau dazu in deine Objekte unter mqtt.0.hermes.intent. Wenn du wirklich nur ein Objekt für die ShoppingList hast, kannst du die Adressierung vereinfachen.
Aus
var intentResult = $('mqtt.0.hermes.intent.SetShoppingList*')
wird dann einfach
var intentResult = 'mqtt.0.hermes.intent.SetShoppingList'
Und den weiteren Aufwand mit dem intentArray und der nachgelagerten Schleife zum durchsuchen des intentArrays kannst du dir auch sparen.
Unabhängig davon verwende ich tatsächlich mehrere ShoppingLists (individuell für mich und für meine Frau, gemeinsam Haushalt), die aber alle nur mit dem einen Objekt abgefangen werden. Die Detailinformation, welche dieser ShoppingLists befüllt werden soll, schicke ich in der Definition des Intents mit, also direkt vom Rhasspy.
Schau mal, ob dir das weiterhilft
-
@tobetobe
danke für die Rückmeldung.var intentResult = 'mqtt.0.hermes.intent.SetShoppingList';
brachte leider keinen Erfolg.
In der intents
hermes/intent/SetShoppingList
bekomme ich folgendes angezeigt:
{"input": "true Milch auf die bring.0.78XXXXXXXXXXXXX79 .saveItem", "intent": {"intentName": "SetShoppingList", "confidenceScore": 1.0}, "siteId": "Wohnzimmer", "id": "fed0e13d-5607b1d7a243", "slots": [{"entity": "synonyms_change_command", "value": {"kind": "Unknown", "value": "true"}, "slotName": "command", "rawValue": "setze", "confidence": 1.0, "range": {"start": 0, "end": 4, "rawStart": 0, "rawEnd": 5}}, {"entity": "shopping_item", "value": {"kind": "Unknown", "value": "Milch"}, "slotName": "value", "rawValue": "Milch", "confidence": 1.0, "range": {"start": 5, "end": 10, "rawStart": 6, "rawEnd": 11}}, {"entity": "device_name_shoppinglist", "value": {"kind": "Unknown", "value": "bring.0.787XXXXXXXXXXXXXX9"}, "slotName": "device", "rawValue": "Haushaltsliste", "confidence": 1.0, "range": {"start": 19, "end": 63, "rawStart": 20, "rawEnd": 34}}, {"entity": "state", "value": {"kind": "Unknown", "value": ".saveItem"}, "slotName": "state", "rawValue": "", "confidence": 1.0, "range": {"start": 64, "end": 73, "rawStart": 35, "rawEnd": 34}}], "sessionId": "fed0e13d-5607-31a1b1d7a243", "customData": null, "asrTokens": [[{"value": "true", "confidence": 1.0, "rangeStart": 0, "rangeEnd": 4, "time": null}, {"value": "Milch", "confidence": 1.0, "rangeStart": 5, "rangeEnd": 10, "time": null}, {"value": "auf", "confidence": 1.0, "rangeStart": 11, "rangeEnd": 14, "time": null}, {"value": "die", "confidence": 1.0, "rangeStart": 15, "rangeEnd": 18, "time": null}, {"value": "bring.0.78XXXXXXXXXXXXX9", "confidence": 1.0, "rangeStart": 19, "rangeEnd": 63, "time": null}, {"value": ".saveItem", "confidence": 1.0, "rangeStart": 64, "rangeEnd": 73, "time": null}]], "asrConfidence": null, "rawInput": "setze Milch auf die Haushaltsliste", "wakewordId": null, "lang": null}
sieht für mich erst einmal richtig aus.
-
@jwerlsdf sagte in Rhasspy: Sprachsteuerung für BRING!-Adapter:
sieht für mich erst einmal richtig aus
Hallo,
das stimmt!!! Das sieht bei mir genauso aus. Daran liegt es also nicht
Der Fehler liegt wohl bei diesem Skript:
Ich versuche mal, mich dort einzulesen. Das Skript ist allerdings sehr mächtig und man müsste sicher sein, dass es nicht das BRING-Skript selbst ist, was den Fehler verursacht. Von daher einige Fragen: Welche Steuerungen funktionieren? Ist das Triggern der Einkaufsliste bzw. des BRING-Adapters die einzige Funktion, die nicht geht? Und was sagen die Logs im BRING-Skript, wenn du diese einschaltest?Aufgefallen ist mir folgendes:
Die Fehlermeldung stammt ja wohl aus diesem Teil deines Skripts, da die if-Bedingung nicht erfüllt wird. Hier könntest du selbst nachforschen. Bist du zB sicher, dass diese Adressierung korrekt ist:id: /mqtt\.0\.hermes\.intent\..*/
müsste sie nicht eher so aussehen:
id: 'mqtt.0.hermes.intent.ShoppingList'
-
@tobetobe
das ist ein anderes Skript, mit dem ich alles andere schalte (Lampen, webradio, etc.).
Als ich das Skript deaktiviert habe, hat das Bring-Skript von dir immer noch nicht die Werte in den Bring-Adapter geschrieben.
Testweise habe ich in meiner VIS die Daten mal eingegeben und diese werden auch korrekt in der Objektstuktur angelegt und per Telegram versendet. Sollte also auch nicht am Bring-Adapter an sich liegen -
@jwerlsdf sagte in Rhasspy: Sprachsteuerung für BRING!-Adapter:
das ist ein anderes Skript,
Hallo, ich hatte dir einen Vorschlag zur weiteren Fehlersuche gemacht. Hast du den gesehen?
-
@tobetobe said in Rhasspy: Sprachsteuerung für BRING!-Adapter:
id: /mqtt.0.hermes.intent..*/
Die Adressierung ist korrekt, da diese ja mit meinen anderen Sprachbefehlen läuft...Es sind ja noch ein paar andere Intents, die ich auslese. Mit deinem Vorschlag ging es leider auch nicht.