NEWS
Rhasspy Offline Sprachsteuerung
-
Hallo Thomas,
@tobetobe sagte in Rhasspy Offline Sprachsteuerung:Ich konnte dort Text hinschicken, der aber nicht am Rhasspy-Lautsprecher ausgegeben wurde. Dazu ist wohl noch eine längere Auseinandersetzung mit dem Thema erforderlich.
Bei mir ist die mqtt.1-Instanz als Client/subscriber eingestellt.
IMHO kann die Instanz nur auf "subscribte" Topics hören, aber nicht an "hermes/tts/say" senden, bzw. publishen?Gruß
Jörg -
@joergeli
danke für die Anleitung
Also die 2.5.0-pre ist installiert, so wie erklärt/gezeigt.
Die Klinke habe ich abgeschaltet, weil ich einen Lautsprecher am Anschluss "Speaker" habe.
Der Lautsprecher funktioniert und ich kann über "Speak" auch Wörter darüber ausgeben.
Rhasspy reagiert auf Wörter, aber wenn ich sage: "rolladen stoppen" wird "offen sag mir stoppen" verstanden
Ich habe auf "Train" gedrückt und es funktioniert
Jetzt müssten die Wörter nur noch per MQTT an den ioBroker übergeben werden und ich bin glücklich.
Ich sehe gerade @tobetobe hatte mir ja schon alles mit MQTT erklärt, aber du hast da eine simplere Idee?
Ich hatte mir ganz unvoreingenommen vorgestellt Rhasspy könnte MQTT von haus aus!?
Ich stelle mir nur grad vor was passiert wenn ein Update von Rhasspy kommt, dann habe ich direkt MQTT als weitere Baustelle.Danke und VG
Leif -
@capitaenz
Hallo Leif,
na, das ist doch schon die halbe Miete@capitaenz sagte in Rhasspy Offline Sprachsteuerung:
Ich hatte mir ganz unvoreingenommen vorgestellt Rhasspy könnte MQTT von haus aus!?
Tja, da muss ich etwas ausholen:
In der vorigen Rhasspy-Version 2.4.19 konnte man einfach in ioBroker einen MQTT Server/broker-Adapter mit beliebigem Port installieren. In Rhasspy hat man dann einfach bei MQTT "extern" gewählt und IP-Adresse von ioBroker und MQTT-Port eingetragen. Dann wurden die entspr. Rhasspy-Topics automatisch abonniert und entspr. Datenpunkte angelegt.
Auf Änderung dieser Datenpunkte konnte man dann z.B. JavaScript reagieren und z.B. eine Lampe ein-/ausschalten.Mit der neuen Rhasspy 2.5-pre geht das zwar auch, doch ist es - wie wir mühsam herausgefunden haben -, etwas umständlicher. Deshalb brauchen wir hier auch den zusätzlichen MOSQUITTO auf dem Rhasspy-Raspi.
Vorgehensweise:
Falls bei Dir schon ein ioBroker MQTT Server/broker-Adapter(z.B. mqtt.0) läuft, eine weitere Instanz (mqtt.1) hinzufügen und als Client/subscriber einrichten. Bei den Verbindungseinstellungen die IP Deines Rhasspy-Raspi und Port 1883 eintragen. Das ist dann der zuvor auf dem Rhasspy installierte MOSQUITTO:
Es reicht aus, nur auf diese 3 Topics hermes/intent/#, hermes/asr/startListening, hermes/nlu/intentNotRecognized von Rhasspy zu subscriben:
Wenn Du jetzt noch mal "snowboy" "rolladen hochfahren" sagst, sollte dann unter den ioBroker-Objekten u.a. mqtt.1.hermes.intent.Rolladen mit dem entspr. Befehl, bzw. JSON "rolladen hochfahren" erscheinen:
Bei meinem Screenshot sind noch weitere intents zu sehen, da ich natürlich noch andere Sache schalte, als die Rolläden.Damit hätten wir schon mal die Info von Rhasspy in ioBroker, daß die Rolladen hochgefahren werden sollen.
Jetzt fehlt nur noch die Auswertung der Info, d.h. wie soll ioBroker darauf reagieren.
@tobetobe und ich machen das via JavaScript, wobei wir da unterschiedliche Varianten bevorzugen, @tobetobe hat da eine elegante Variante, die aber momentan mit der 2.5-pre noch nicht zu 100% funktioniert.
Ich stelle Dir deshalb mal meine Quick & Dirty-Variante vor (ich bin kein JS-Crack).Ich habe folgende Sentences in Rhasspy angelegt:
(ich verwende - aus Faulheit - keine sog. Slots, wie das eigentlich in der Rhasspy-Doku beschrieben ist, geht aber trotzdem)[Temperatur] temperatur_name = (temperatur) {name} temperatur_state = (draussen| wohnzimmer | keller | schlafzimmer | badewasser) {state} wie (warm | kalt) ist [es | das] [(im)] <temperatur_state> [Ereignis] ereignis_name = (ereignis) {name} ereignis_state = (termine) {state} liegt heute etwas an (gibt es) [(heute)] <ereignis_state> [(heute)] [Zeit] zeit_name = (zeit) {name} zeit_state = (spät | uhr | uhrzeit) {state} (wie | wieviel | sag mir) [(ist die | die)] <zeit_state> [(ist es | haben wir)] [Datum] datum_name = (datum) {name} datum_state = (tag | datum) {state} ( welchen | welches) <datum_state> [ist | haben wir] [ heute] [Drucker] drucker_name = (drucker) {name} drucker_state = (weit) {state} wie <drucker_state> ist der drucker [Fenster] fenster_name = (fenster) {name} fenster_state = (offen | zu) {state} (sind) [(noch)] [(alle Fenster | Fenster )] <fenster_state> [Regen] regen_name = (regen) {name} regen_state = (geregnet) {state} hat es [(heute)] <regen_state> [Lampen] lampen_name = (moodlight |stimmungslicht|fernsehlicht|esstischlampe|essecke|wandspots|regal|couchjoerg|couchrenate|hydro|ledcube|radio ) {name} lampen_state = (ein | aus) {state} schalte [ (die | den | das )] <lampen_name> <lampen_state> [Moodlight] moodlight_name = (moodlight) {name} moodlight_state = (regenbogen | polizei | running | wischen | christmas) {state} <moodlight_state> [Scenes] scene_name = (schlafen | fernsehabend) {name} scene_state = (aktivieren | gehen ) {state} <scene_name> <scene_state> [Rolladen] rolladen_name = (rolladen ) {name} rolladen_state = (hochfahren | runterfahren | stoppen ) {state} <rolladen_name> <rolladen_state>
Dementsprechend werden bei Aufruf des entspr. Sentence die ioBroker-Datenpunkte angelegt.
z.B. : "snowboy" "wie warm ist es im wohnzimmer" der Datenpunkt mqtt.1.hermes.intent.Temperatur
(das kennen wir schon vom Rolladen-Beispiel)Dann habe ich ein JS gebastelt, was auf Änderung des entspr. Datenpunktes (hier: Temperatur) reagiert, bzw. getriggert wird.
Anschließend erfolgt eine if-Abfrage, was übergeben wurde (draussen, wohnzimmer, keller, schlafzimmer, badewasser)
Anhand des Ergenisses der if-Abfrage wird dann der Datenpunkt (hier: wohnzimmer) ausgelesen und an die Sprachausgabe für Rhasspy übergeben:let data = "Es sind " + innentemp + " Grad im Wohnzimmer" ;
Am Anfang des Scriptes ist übrigens definiert, daß die Sprachausgaben an die HTTP-Api von Rhasspy gesendet werden.
Dazu muß im Script die entspr. IP-Adresse editiert werden:Hier nun also mein kpl. Script, wobei Du natürlich die Datenpunkte der Sensoren/Aktoren, etc. an Deine Gegebenheiten anpassen musst:
//########################################################################## // Rhasspy-Voltron-intents via MQTT-Client empfangen und entspr.Datenpunkte setzen/schalten // Ausgabe ueber Lautsprecher //########################################################################## let http = require('http'); // Für Sprachausgabe auf Rhasspy let options = { host: 'xxx.xxx.xxx.xxx', // Deine Rhasspy IP-Adresse port: 12101, //Rhasspy Port muss so bleiben 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.write(data); req.end(); } //______________________________________________________________________________ const szenen = 'mqtt.1.hermes.intent.Scenes' // Broadlink-Szenen const rolladen = 'mqtt.1.hermes.intent.Rolladen' // Rolladen const lampen = 'mqtt.1.hermes.intent.Lampen' // Lampen, bzw. Funksteckdosen const drucker = 'mqtt.1.hermes.intent.Drucker' // 3D Drucker const fenster = 'mqtt.1.hermes.intent.Fenster' // Anzahl offene Fenster const regen = 'mqtt.1.hermes.intent.Regen' // Regen heute const ereignis = 'mqtt.1.hermes.intent.Ereignis' // Heutige Termine const zeit = 'mqtt.1.hermes.intent.Zeit' // Uhrzeit const datum = 'mqtt.1.hermes.intent.Datum' // Datum const temperatur = 'mqtt.1.hermes.intent.Temperatur' // Temperatur //______________________________________________ // Termine on({id: ereignis, change: "any"},function(obj) { let empf_code = getState(ereignis).val ; let empf_json = JSON.parse(empf_code); let state = empf_json.state; GetEvent(); }); //______________________________________________ // Regen on({id: regen, change: "any"},function(obj) { let empf_code = getState(regen).val ; let empf_json = JSON.parse(empf_code); let state = empf_json.slots[0].value.value; //log ("state: " + state); if (state == "geregnet") { GetRain(); } }); //______________________________________________ // Fenster on({id: fenster, change: "any"},function(obj) { let empf_code = getState(fenster).val ; let empf_json = JSON.parse(empf_code); let state = empf_json.slots[0].value.value; //log ("state: " + state); if (state == "offen" || state == "zu") { GetWindows(); } }); //______________________________________________ // 3d-Drucker on({id: drucker, change: "any"},function(obj) { let empf_code = getState(drucker).val ; let empf_json = JSON.parse(empf_code); let state = empf_json.slots[0].value.value; //log ("state: " + state); if (state == "weit") { GetPrinterTime(); } }); //______________________________________________ // Uhrzeit on({id: zeit, change: "any"},function(obj) { let empf_code = getState(zeit).val ; let empf_json = JSON.parse(empf_code); let name = empf_json.name; let state = empf_json.state; //log ("state: " + state); //if (state == "sp\u00e4t") { GetCurrentTimeStamp(); // } }); //______________________________________________ // Datum on({id: datum, change: "any"},function(obj) { let empf_code = getState(datum).val ; //log ("empf_code: " + empf_code); let empf_json = JSON.parse(empf_code); let intent = empf_json.intent.intentName; //log ("intent: " + intent); if (intent == "Datum") { GetCurrentDate(); } }); //______________________________________________ // Temperaturen on({id: temperatur, change: "any"},function(obj) { let empf_code = getState(temperatur).val ; //log ("empf_code: " + empf_code); let empf_json = JSON.parse(empf_code); let state = empf_json.slots[0].value.value; //log ("state: " + state); if (state == "draussen") { let aussentemp_obj = "hm-rpc.2.CUX0100001.1.TEMPERATURE"; let aussenfeuchte_obj = "hm-rpc.2.CUX0100001.1.HUMIDITY"; let aussentemp_wert = getState(aussentemp_obj).val; let aussenfeuchte_wert = getState(aussenfeuchte_obj).val; let aussentemp_string = String(aussentemp_wert); let aussenfeuchte_string = String(aussenfeuchte_wert); let aussentemp = aussentemp_string.replace(".",","); let aussenfeuchte = aussenfeuchte_string.replace(".",","); //log ( " Aussen-Temperatur ist " + aussentemp + " Grad" ); let data = 'Es sind ' + aussentemp + ' Grad draussen bei ' + aussenfeuchte + ' Prozent Luftfeuchtigkeit'; httpPost(data); } else if(state == "innen" || state == "wohnzimmer") { let innentemp_obj = "sonoff.0.Kodi-Stecker.AM2301_Temperature"; let innentemp_wert = getState(innentemp_obj).val; let innentemp_string = String(innentemp_wert); let innentemp = innentemp_string.replace(".",","); //log ( " Innen-Temperatur ist " + innentemp + " Grad" ); let data = "Es sind " + innentemp + " Grad im Wohnzimmer" ; httpPost(data); } else if(state == "schlafzimmer") { let schlafzimmer_obj = "javascript.0.DHT22.Schlafzimmer.Temp"; let schlafzimmer_wert = getState(schlafzimmer_obj).val; let schlafzimmer_string = String(schlafzimmer_wert); let schlafzimmer = schlafzimmer_string.replace(".",","); //log ( " Schlafzimmer-Temperatur ist " + schlafzimmer + " Grad" ); let data = "Es sind " + schlafzimmer + " Grad im Schlafzimmer"; httpPost(data); } else if(state == "badewasser") { let badewasser_obj = "javascript.0.SolarParser.Daten5"; let badewasser_wert = getState(badewasser_obj).val; let badewasser_string = String(badewasser_wert); let badewassertemp = badewasser_string.replace(".",","); //log ( " Badewasser-Temperatur ist " + badewassertemp + " Grad" ); let data = "Das Badewasser hat " + badewassertemp + " Grad"; httpPost(data); } }); //______________________________________________ // Lampen, bzw. Funksteckdosen on({id: lampen, change: "any"},function(obj) { let empf_code = getState(lampen).val ; //log ("EMPF-CODE: " + empf_code); let empf_json = JSON.parse(empf_code); let name = empf_json.slots[0].value.value; //log ("name: " + name); let state = empf_json.slots[1].value.value; //log ("state: " + state); if(name == "wandspots" && state == "ein") { setState ('hm-rpc.2.CUX4000001.7.PRESS_LONG', true); //setState ('broadlink2.0.RM:0x27a9_34:ea:34:55:3a:50.L.Licht_Wandspots_An', true); } else if(name == "wandspots" && state == "aus") { setState ('hm-rpc.2.CUX4000001.7.PRESS_SHORT', true); setState ('broadlink2.0.RM:0x27a9_34:ea:34:55:3a:50.L.Licht_Wandspots_Aus', true); } else if(name == "regal" && state == "ein") { setState ('hm-rpc.2.CUX4000001.1.PRESS_LONG', true); setState ('broadlink2.0.RM:0x27a9_34:ea:34:55:3a:50.L.Licht_Regal_An', true); } else if(name == "regal" && state == "aus") { setState ('hm-rpc.2.CUX4000001.1.PRESS_SHORT', true); setState ('broadlink2.0.RM:0x27a9_34:ea:34:55:3a:50.L.Licht_Regal_Aus', true); } else if(name == "couchjoerg" && state == "ein") { setState ('hm-rpc.2.CUX4000001.10.PRESS_LONG', true); setState ('broadlink2.0.RM:0x27a9_34:ea:34:55:3a:50.L.Licht_CouchJoerg_An', true); } else if(name == "couchjoerg" && state == "aus") { setState ('hm-rpc.2.CUX4000001.10.PRESS_SHORT', true); setState ('broadlink2.0.RM:0x27a9_34:ea:34:55:3a:50.L.Licht_CouchJoerg_Aus', true); } else if(name == "couchrenate" && state == "ein") { setState ('hm-rpc.2.CUX4000001.3.PRESS_LONG', true); setState ('broadlink2.0.RM:0x27a9_34:ea:34:55:3a:50.L.Licht_CouchRenate_An', true); } else if(name == "couchrenate" && state == "aus") { setState ('hm-rpc.2.CUX4000001.3.PRESS_SHORT', true); setState ('broadlink2.0.RM:0x27a9_34:ea:34:55:3a:50.L.Licht_CouchRenate_Aus', true); } else if(name == "hydro" && state == "ein") { setState ('hm-rpc.2.CUX4000001.8.PRESS_LONG', true); setState ('broadlink2.0.RM:0x27a9_34:ea:34:55:3a:50.L.Licht_HydroTV_An', true); } else if(name == "hydro" && state == "aus") { setState ('hm-rpc.2.CUX4000001.8.PRESS_SHORT', true); setState ('broadlink2.0.RM:0x27a9_34:ea:34:55:3a:50.L.Licht_HydroTV_Aus', true); } else if(name == "ledcube" && state == "ein") { setState ('hm-rpc.2.CUX4000001.5.PRESS_LONG', true); setState ('broadlink2.0.RM:0x27a9_34:ea:34:55:3a:50.L.LED-Wuerfel_An', true); } else if(name == "ledcube" && state == "aus") { setState ('hm-rpc.2.CUX4000001.5.PRESS_SHORT', true); setState ('broadlink2.0.RM:0x27a9_34:ea:34:55:3a:50.L.LED-Wuerfel_Aus', true); } else if(name == "essecke" && state == "ein") { setState ('hm-rpc.2.CUX4000001.2.PRESS_LONG', true); setState ('broadlink2.0.RM:0x27a9_34:ea:34:55:3a:50.L.Licht_Essecke_An', true); } else if(name == "essecke" && state == "aus") { setState ('hm-rpc.2.CUX4000001.2.PRESS_SHORT', true); setState ('broadlink2.0.RM:0x27a9_34:ea:34:55:3a:50.L.Licht_Essecke_Aus', true); } else if(name == "esstischlampe" && state == "ein") { setState ('shelly.0.SHSW-1#2C7AEF#1.Relay0.Switch', true); } else if(name == "esstischlampe" && state == "aus") { setState ('shelly.0.SHSW-1#2C7AEF#1.Relay0.Switch', false); } else if(name == "fernsehlicht" && state == "ein") { fernsehlicht_ein(); } else if(name == "fernsehlicht" && state == "aus") { fernsehlicht_aus(); } else if(name == "radio" && state == "ein") { setState ('javascript.0.Silvercrest.On', true); } else if(name == "radio" && state == "aus") { setState ('javascript.0.Silvercrest.On', false); } //log ( name + " ist " + state ); let data = name + " wurde " + state + "geschaltet"; httpPost(data); }); //______________________________________________ // Broadlink-Szenen on({id: szenen, change: "any"},function(obj) { let empf_code = getState(szenen).val ; let empf_json = JSON.parse(empf_code); let name = empf_json.slots[0].value.value; //log ("name: " + name); let state = empf_json.slots[1].value.value; //log ("state: " + state); if (name == "schlafen" && state == "gehen"){ fernsehlicht_aus(); setState ('broadlink2.0.Scenes.Schlafen', true); let data = 'Wohnzimmerbeleuchtung und Fernseher werden ausgeschaltet. Gute Nacht.'; httpPost(data); } else if(name == "fernsehabend" && state == "aktivieren") { fernsehlicht_ein(); setState ('broadlink2.0.Scenes.Fernsehabend', true); let data = name + ' wird aktiviert. Ich wünsche gute Unterhaltung.'; httpPost(data); } }); //______________________________________________ // Rolladen on({id: rolladen, change: "any"},function(obj) { let empf_code = getState(rolladen).val ; let empf_json = JSON.parse(empf_code); let name = empf_json.slots[0].value.value; //log ("name: " + name); let state = empf_json.slots[1].value.value; //log ("state: " + state); //log ("name: " + name + " state: " + state); if (name == "rolladen" && state == "hochfahren"){ setState ('hm-rpc.0.PEQ0505813.1.STATE', true); let data = name + ' werden hochgefahren'; httpPost(data); } else if(name == "rolladen" && state == "runterfahren"){ setState ('hm-rpc.0.PEQ0505813.3.STATE', true); let data = name + ' werden runtergefahren'; httpPost(data); } else if(name == "rolladen" && state == "stoppen"){ setState ('hm-rpc.0.PEQ0505813.2.STATE', true); let data = name + " werden gestoppt "; httpPost(data); } //log ( name + " " + state ); }); //______________________________________________ //################################################################################################ // WakeWord-Erkennung const wake = 'mqtt.1.hermes.asr.startListening' // Wakeword erkannt const befehl = 'mqtt.1.hermes.asr.textCaptured' // Datenpunkt aendert sich von listening auf loaded, wenn befehl erkannt erkannt wurde const unbekannt = 'mqtt.1.hermes.nlu.intentNotRecognized' // Datenpunkt Intent nicht erkannt on({id: wake, change: "any"},function(obj) { wakeword(); }); on({id: befehl, change: "any"},function(obj) { //befehl_empf(); }); on({id: unbekannt, change: "any"},function(obj) { nicht_erkannt(); }); function wakeword(){ //setState ('broadlink2.0.RM:0x27a9_34:ea:34:55:3a:50.L.SamsungTV_Mute', true); let data = "ja?" ; httpPost(data); } function befehl_empf(){ setTimeout(function(){ // setState ('broadlink2.0.RM:0x27a9_34:ea:34:55:3a:50.L.SamsungTV_Mute', true); // //log ( "Mute gesetzt " ); }, 10000); let data = "Moment bitte, "; httpPost(data); } function nicht_erkannt(){ // setTimeout(function(){ // setState ('broadlink2.0.RM:0x27a9_34:ea:34:55:3a:50.L.SamsungTV_Mute', true); // setState ('broadlink2.0.RM:0x27a9_34:ea:34:55:3a:50.L.SamsungTV_Mute', true); // //log ( "Nicht verstanden" ); // }, 6000); let data = "Entschuldigung, ich habe dich leider nicht verstanden"; httpPost(data); } // Ende WakeWord-ErkennungsScript //################################################################################################ //__________________________________________________ function formatTwoDigits(n) { return n < 10 ? '0' + n : n; } //__________________________________________________ function GetCurrentTimeStamp() { var now = new Date(); //var hours = now.getHours(); //var minutes = now.getMinutes(); //var seconds = now.getSeconds(); var hours = formatTwoDigits(now.getHours()); var minutes = formatTwoDigits(now.getMinutes()); var seconds = formatTwoDigits(now.getSeconds()); var TimeString = hours + ":" + minutes + ":" + seconds; let data = "Es ist " + TimeString; httpPost(data); } //__________________________________________________ function GetCurrentDate() { var datum = new Date(); var tag = datum.getDay(); var wotag = wochentag(tag); //log(wotag); var now = new Date(); var dd = now.getDate(); var dd_string = String(dd); var tagi ="" if (dd_string == "1") { tagi = "ers";} else if (dd_string == "3") { tagi = "drit";} else { tagi = dd_string ;} var mm = now.getMonth()+1; var monat =""; if (mm == 1) { monat = "Januar";} else if (mm == 2) { monat = "Februar";} else if (mm == 3) { monat = "März";} else if (mm == 4) { monat = "April";} else if (mm == 5) { monat = "Mai";} else if (mm == 6) { monat = "Juni";} else if (mm == 7) { monat = "Juli";} else if (mm == 8) { monat = "August";} else if (mm == 9) { monat = "September";} else if (mm == 10) { monat = "Oktober";} else if (mm == 11) { monat = "November";} else if (mm == 12) { monat = "Dezember";} var yyyy = now.getFullYear(); //var DateString = " Heute ist" + wotag + " der " + dd + "."+ mm +"."+yyyy; var DateString = " Heute ist" + wotag + " der " + tagi + "te " + monat +" "+ yyyy; let data = DateString; httpPost(data); } //__________________________________________________ function wochentag(i){ var tage = ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag', 'Sonntag']; var tag = (typeof(i) == 'object') ? i.getDay() : i ; return tage[tag]; } //__________________________________________________ function fernsehlicht_ein(){ //regal an setState ('hm-rpc.2.CUX4000001.1.PRESS_LONG', true); setState ('broadlink2.0.RM:0x27a9_34:ea:34:55:3a:50.L.Licht_Regal_An', true); //couchjoerg an setState ('hm-rpc.2.CUX4000001.10.PRESS_LONG', true); setState ('broadlink2.0.RM:0x27a9_34:ea:34:55:3a:50.L.Licht_CouchJoerg_An', true); //couchrenate an setState ('hm-rpc.2.CUX4000001.3.PRESS_LONG', true); setState ('broadlink2.0.RM:0x27a9_34:ea:34:55:3a:50.L.Licht_CouchRenate_An', true); //hydro an setState ('hm-rpc.2.CUX4000001.8.PRESS_LONG', true); setState ('broadlink2.0.RM:0x27a9_34:ea:34:55:3a:50.L.Licht_HydroTV_An', true); } //__________________________________________________ function fernsehlicht_aus(){ //regal aus setState ('hm-rpc.2.CUX4000001.1.PRESS_SHORT', true); setState ('broadlink2.0.RM:0x27a9_34:ea:34:55:3a:50.L.Licht_Regal_Aus', true); //couchjoerg aus setState ('hm-rpc.2.CUX4000001.10.PRESS_SHORT', true); setState ('broadlink2.0.RM:0x27a9_34:ea:34:55:3a:50.L.Licht_CouchJoerg_Aus', true); //couchrenate aus setState ('hm-rpc.2.CUX4000001.3.PRESS_SHORT', true); setState ('broadlink2.0.RM:0x27a9_34:ea:34:55:3a:50.L.Licht_CouchRenate_Aus', true); //hydro aus setState ('hm-rpc.2.CUX4000001.8.PRESS_SHORT', true); setState ('broadlink2.0.RM:0x27a9_34:ea:34:55:3a:50.L.Licht_HydroTV_Aus', true); } //__________________________________________________ function GetPrinterTime() { const anycubic_fortschritt = 'octoprint.0.printjob.progress.completion' const anycubic_online = 'octoprint.0.info.connection' const rest = 'javascript.0.OctoPi.Restzeit' var druck_status = getState(anycubic_online).val; var druck_fortschritt0 = getState(anycubic_fortschritt).val; var druck_fortschritt = Math.round(druck_fortschritt0 * 1) / 1; // keine Nachkommastellen ansagen var restzeit = getState(rest).val; var restzeit0 =restzeit.split(':')[0]; var restzeit1 =restzeit.split(':')[1]; var restzeit2 =restzeit.split(':')[2]; var restzeit_std = parseInt( restzeit0); var restzeit_min = parseInt( restzeit1); var restzeit_sec = parseInt( restzeit2); if (restzeit_std > 1){ var stunde = restzeit_std + " Stunden, "} if (restzeit_std == 1){ var stunde = " eine Stunde, "} if (restzeit_std == 0){ var stunde = ""} if (restzeit_min > 1){ var minute = restzeit_min + " Minuten, "} if (restzeit_min == 1){ var minute = " eine Minute, "} if (restzeit_min == 0){ var minute = ""} if (druck_status != false){ let data = 'Der 3 D-Drucker hat ' + druck_fortschritt + 'Prozent des Ausdruckes fertiggestellt. ' + 'Es dauert noch ' + stunde + ' ' + minute + ' und ' +restzeit_sec + ' Sekunden, bis der Ausdruck fertig ist.'; httpPost(data); } else{ let data = 'Der 3 D-Drucker ist ausgeschaltet'; httpPost(data); } } //__________________________________________________ function GetWindows() { const windows = 'hm-rega.0.8240' var fenster_status = getState(windows).val; //log("Anzahl Fenster: " + fenster_status); if (fenster_status > 1){ let data = 'Ja, es sind noch ' + fenster_status + ' Fenster im Haus offen'; httpPost(data); } else if(fenster_status == 1) { let data = 'Ja, es ist noch ein Fenster im Haus offen'; httpPost(data); } else{ let data = 'Nein , alle Fenster im Haus sind geschlossen'; httpPost(data); } } //__________________________________________________ function GetRain() { const rain = 'javascript.0.WS2000.Regenmenge' const dauer = 'javascript.0.WS2000.Regendauer' var rain_amount = getState(rain).val; //log("Regenmenge: " + rain_amount); let rain_amount_string = String(rain_amount); let rain_today = rain_amount_string.replace(".",","); var rain_duration = getState(dauer).val; //log("Regendauer: " + rain_duration); let rain_duration_string = String(rain_duration); let duration_today = rain_duration_string.replace(".",","); //log("duration_today: " + duration_today); let dauer_stunden = duration_today.split(':')[0]; //log("dauer_stunden :" + dauer_stunden) let dauer_stunden_zahl = parseInt(dauer_stunden); // String to number let dauer_minuten = duration_today.split(':')[1]; let dauer_minuten_zahl = parseInt(dauer_minuten); // String to number //log("dauer_minuten_zahl: " + dauer_minuten_zahl); let stunden = ""; let und = ""; //--------------------------------------------------- if (dauer_minuten_zahl == 0){ und = ""; dauer_minuten = "";} else if (dauer_minuten_zahl == 1){und = " und "; dauer_minuten = " eine Minute"; } else if (dauer_minuten_zahl > 1 && dauer_minuten_zahl < 10){und = " und "; dauer_minuten = dauer_minuten_zahl + " Minuten"; } else if (dauer_minuten_zahl >= 10){ und = " und "; dauer_minuten = dauer_minuten_zahl + " Minuten"; } if (dauer_stunden_zahl == 0){ und = ""; dauer_stunden = ""; stunden = "";} else if (dauer_stunden_zahl == 1){ stunden = dauer_stunden_zahl + " Stunde"; } else if (dauer_stunden_zahl > 1) { stunden = dauer_stunden_zahl + " Stunden"; } //log( 'rain_amount: ' + rain_amount + ' duration_today: ' + duration_today); if (rain_amount > 0){ let data = 'Ja, es hat heute ' + rain_today + ' Liter pro Quadratmeter geregnet'; httpPost(data); } else if (rain_amount == 0 && dauer_minuten_zahl > 0 ){ let data = 'Ja, aber es gab nur geringen Niederschlag, der' + stunden + und + dauer_minuten + " gedauert hat"; httpPost(data); } else if (rain_amount == 0 ){ let data = 'Nein, heute war es trocken'; httpPost(data); } } //__________________________________________________ function GetEvent() { const ereignis0 = 'javascript.0.Geburtstag.Heute0' // Event0 const ereignis1 = 'javascript.0.Geburtstag.Heute1' // Event1 const ereignis2 = 'javascript.0.Geburtstag.Heute2' // Event2 const bio_heute = 'ical.1.events.0.today.Biomüll' const gelb_heute = 'ical.1.events.0.today.GelberSack' const papier_heute = 'ical.1.events.0.today.Papier' const rest_heute = 'ical.1.events.0.today.Restmüll' const bio_morgen = 'ical.1.events.1.Biomüll' const gelb_morgen = 'ical.1.events.1.GelberSack' const papier_morgen = 'ical.1.events.1.Papier' const rest_morgen = 'ical.1.events.1.Restmüll' var event0 = getState(ereignis0).val; var event1 = getState(ereignis1).val; var event2 = getState(ereignis2).val; var bio_today = getState(bio_heute).val; var gelb_today = getState(gelb_heute).val; var papier_today = getState(papier_heute).val; var rest_today = getState(rest_heute).val; var bio_tomorrow = getState(bio_morgen).val; var gelb_tomorrow = getState(gelb_morgen).val; var papier_tomorrow = getState(papier_morgen).val; var rest_tomorrow = getState(rest_morgen).val; if (event0 != '' && event0 != 'Heute: Biomüll' && event0 != 'Heute: Gelber Sack' && event0 != 'Heute: Papier' && event0 != 'Heute: Restmüll' ){ let data = 'Ja, ' + event0 + '. '; httpPost(data); } if (event1 != '' && event1 != 'Heute: Biomüll' && event1 != 'Heute: Gelber Sack' && event1 != 'Heute: Papier' && event1 != 'Heute: Restmüll' ){ let data = ' ' + event1 + '. '; httpPost(data); } if (event2 != '' && event2 != 'Heute: Biomüll' && event2 != 'Heute: Gelber Sack' && event2 != 'Heute: Papier' && event2 != 'Heute: Restmüll' ){ let data = ' ' + event2 + '. '; httpPost(data); } //if (bio_today == true || bio_tomorrow == true || gelb_today == true || gelb_tomorrow == true || papier_today == true || papier_tomorrow == true || rest_today == true || rest_tomorrow == true) { // sendTo("paw.0",'Tablet_Jörg',{tts: 'Es wird Müll abgeholt und zwar: '}); //} if (bio_today == true) { let data = ' Heute Biomüll. '; httpPost(data);} if (gelb_today == true) { let data = ' Heute Gelbersack. '; httpPost(data);} if (papier_today == true){ let data = ' Heute Papiertonne. '; httpPost(data);} if (rest_today == true) { let data = ' Heute Restmüll. '; httpPost(data);} if (bio_tomorrow == true) { let data = ' Morgen Biomüll. '; httpPost(data);} if (gelb_tomorrow == true) { let data = ' Morgen Gelbersack. '; httpPost(data);} if (papier_tomorrow == true) { let data = ' Morgen Papiertonne. '; httpPost(data);} if (rest_tomorrow == true) { let data = ' Morgen Restmüll. '; httpPost(data);} if (event0 == '' && event1 == '' && event2 == '' && bio_today == false && gelb_today == false && papier_today == false && rest_today == false && bio_tomorrow == false && gelb_tomorrow == false && papier_tomorrow == false && rest_tomorrow == false ) { let data = 'Nein , es stehen keine Termine an.'; httpPost(data); } } //__________________________________________________ function GetMoodlight() { let empf_code = getState(moodlight).val ; let empf_json = JSON.parse(empf_code); let moodlight_name = empf_json.name; let moodelight_state = empf_json.state; //log("moodlight_name: " + moodlight_name); //log("moodelight_state: " + moodelight_state); if (moodelight_state == "regenbogen"){ setState ('javascript.0.wled.brightness', 150); setState ('javascript.0.wled.effekt', 9); setState ('javascript.0.wled.intensity', 128); setState ('javascript.0.wled.speed', 80); } else if(moodelight_state == "polizei") { setState ('javascript.0.wled.brightness', 80); setState ('javascript.0.wled.effekt', 49); setState ('javascript.0.wled.intensity', 94); setState ('javascript.0.wled.speed', 181); } else if(moodelight_state == "running") { setState ('javascript.0.wled.brightness', 80); setState ('javascript.0.wled.farbe', "#efec5d"); setState ('javascript.0.wled.effekt', 15); setState ('javascript.0.wled.intensity', 156); setState ('javascript.0.wled.speed', 31); } else if(moodelight_state == "wischen") { setState ('javascript.0.wled.brightness', 80); setState ('javascript.0.wled.effekt', 36); setState ('javascript.0.wled.intensity', 136); setState ('javascript.0.wled.speed', 232); } else if(moodelight_state == "christmas") { setState ('javascript.0.wled.brightness', 80); setState ('javascript.0.wled.effekt', 44); setState ('javascript.0.wled.intensity', 156); setState ('javascript.0.wled.speed', 168); } else if(moodelight_state == "slowly") { setState ('javascript.0.wled.brightness', 140); setState ('javascript.0.wled.effekt', 63); setState ('javascript.0.wled.intensity', 220); setState ('javascript.0.wled.speed', 1); } let data = "Lichteffekt " + moodelight_state + " wurde aktiviert" ; httpPost(data); } //__________________________________________________
Ich weiß nicht, ob Du damit was anfangen kannst, bzw. es für Deine Zwecke entspr. umbauen kannst.
Es soll nur ein Beispiel sein, wie man die Sprachbefehle von Rhasspy auswerten kann.
Man kann dzu auch Blockly, oder Node Red verwenden, wobei beides nicht so mein Ding ist.
Natürlich wirst Du Dir Deine eigenen Sentences erstellen wollen, aber dazu schau am besten mal in die Doku von RhasspyWas mich noch interessieren würde:
1.) Hat Dein Respeaker-Mic einen Audio-Ausgang, d.h. hast Du daran den Lautsprecher angeschlossen?
2.) Funktioniert bei Dir der LED-Ring auf dem Mic (bzw. HLC = Hermes LED Control ?Gruß
JörgP.S.
@capitaenz sagte in Rhasspy Offline Sprachsteuerung:
Ich stelle mir nur grad vor was passiert wenn ein Update von Rhasspy kommt, dann habe ich direkt MQTT als weitere Baustelle.
Da sehe ich kein Problem, denn die sog. Hermes-Topics werden wohl auch in künftigen Rhasspy-Versionen nicht geändert werden.
-
@joergeli
Super, vielen Dank, es läuft jetzt!
Allerdings musste ich noch etwas probieren und von deiner Anleitung oben abweichen, denn ich musste unter MQTT nicht die IP des ioBroker, sondern die IP des Rhasspy eintragen.
Und das ist es was mich verwirrt. Denn ich bin davon ausgegangen, dass Rhasspy MQTT von haus aus unterstützt, denn es muss ja irgendwie an ein anderes System angebunden werden. Da habe ich geglaubt, dass die Entwickler natürlich MQTT mit eingebaut haben.
Hier die Einstellungen:
Der Repeaker hat einen Stecker für einen Lautsprecher:
Die LEDs leuchten nur beim Hochfahren kurz auf und bleiben dann leider dunkel.
Jetzt bleibt noch eine weitere Frage, wie bekomme ich wie bei Snips eine Sprachausgabe hin?
Ich stelle mir dies so vor, das ich (wie bei Snips) per MQTT-Datenpunkt den Text übergeben kann.
OK, sehe gerade ich könnte auf die HTTP API ausweichen.
Etwa so: http://192.168.0.93:12101/api/text-to-speech/
Leider finde ich jetzt kein Beispiel wie ich den eigentlichen Text hiermit übergeben kann.
Ich meine http://192.168.0.93:12101/api/text-to-speech/test funktioniert nicht, oder bin ich zu naiv?
Bekomme immer ein:
NotFound: NotFound(404)
Habe mir einen Einzeiler vorgestellt, den ich auch in einem x-beliebigen Browser absetzen kann.
Update, habe jetzt herausgefunden, das man mit:http://<ip>:12101/api/#/default/post_api_text_to_speech
etwas Licht ins Dunkel bringen kann und ein Einzeiler, so wie ich geglaubt hatte nicht möglich ist.
Ich komme so langsam wieder an einen Punkt, wo ich nicht sicher bin, ob Snips nicht doch noch die besseren (einfacheren) Möglichkeiten bietet.Hoffe mein Vorhaben ist über MQTT zu realisieren.
Jetzt bleiben für mich noch folgende Punkt offen, damit Rhasspy eine vollwertige Alternative zu Snips wird:- Lautstärke dauerhaft abspeichern, auch nach Reboot
- Sprachausgabe über MQTT oder über Blockly per HTTP
- LEDs zum leuchten bringen
VG
Leif -
Ich fasse jetzt hier die Arbeit der letzten Tage zusammen, damit weitere Leute von Snips zu Rhasspy wechseln können:
Hier wie es bei mir mit einem RP Pi 3b+, einem Respeaker2 und einem externen Lautsprecher funktioniert hat:
Danke an @joergeli und @tobetobe-
Image Flashen mit Win32 DiskImager (Raspian Buster lite)
-
ssh und wpa_supplicant.conf auf SD-Karte anlegen
-
Per SSH (z.B. Putty) einloggen
sudo apt update sudo apt full-upgrade sudo curl -sSL https://get.docker.com | sh sudo usermod -aG docker pi sudo reboot -n
sudo docker pull rhasspy/rhasspy:2.5.0-pre
Dies ist eine Zeile:
sudo sudo docker run -d -p 12101:12101 --restart unless-stopped -v "$HOME/.config/rhasspy/profiles:/profiles" --device /dev/snd:/dev/snd rhasspy/rhasspy:2.5.0-pre --user-profiles /profiles --profile de
sudo wget https://gist.githubusercontent.com/Psychokiller1888/a9826f92c5a3c5d03f34d182fda1ce4c/raw/cbb53252dd55dc4e9f5f6064a493f0981cf133fb/hlc_download.sh sudo chmod +x hlc_download.sh sudo ./hlc_download.sh
-
Fragen
-
What assistant engine are you using?
2 (rhasspy) -
What's the path to your assistant config file?
/home/pi/.config/rhasspy/profiles/de/profile.json -
What device do you wish to control with SLC?
1 (respeaker2) -
What pattern do you want to use?
5 (kiboost) -
Do you need to install / configure your respeaker2?
1 (yes) -
SPI Aktivieren
sudo raspi-config
->5->P4->YES->EXIT
->7->A1->Expand Filesystem
->7->A3->16->OKsudo reboot -n
- onboard Sound deaktivieren, nur bei respeaker2 mit Lautsprecher am "SPEAKER"
sudo nano /boot/config.txt
Turn dtparam=audio parameter to off:
von: dtparam=audio=on auf: dtparam=audio=off
STRG+X -> Y -> ENTER
- Lautstärke
sudo alsamixer
Speichern funktioniert nicht:
sudo alsactl store
- MQTT
sudo apt update sudo apt install -y mosquitto mosquitto-clients sudo systemctl enable mosquitto.service sudo systemctl start mosquitto
-
<IP-Rhasspy>:12101 -> Webinterface aufrufen
-
Rhasspy wie folgt einstellen:
MQTT -> External
Host -> IP Rhasspy
Port -> 1883
Audio Recording -> PyAudio
Wake Word -> Snowboy (Apply Frontend nicht anwählen und Sensitivity auf 0.9)
Speech to Text -> Kaldi (Dateien müssen später über das Webinterface nach einem Neustart von Rhasspy nachinstalliert werden)
Intent Recognition -> Fsticuffs
Text to Speech -> PicoTTS
Audio Playing -> aplay
Dialog Management -> Rhasspy
Intent Handling -> ausgegraut
Auf "Sentences" klicken (die Balken) -
Reboot Rhasspy
Anschließend die restlichen Dateien mit dem "Download" Knopf herunterladen (Kaldi) -
Folgendes zum Test unter [ChangeLightState] eintragen:
[Rolladen] rolladen_name = (rolladen ) {name} rolladen_state = (hochfahren | runterfahren | stoppen ) {state} <rolladen_name> <rolladen_state>
Abspeichern (Save Sentences) nicht vergessen und anschließend auf "Train" (oben rechts) drücken
- Im ioBroker einen (weiteren) MQTT-Adapter hinzufügen.
Diesen als "Client/subscriber" einrichten
Unter "URL" die IP des Rhasspy eintragen und den Port 1883
Unter Subscribe patters UND Prefix für alle Topics folgendes eintragen:
hermes/intent/#, hermes/asr/startListening, hermes/nlu/intentNotRecognized
Bekanntgeben eigene States beim Verbinden den Haken raus.
Fertig!
- Jetzt zum Test sagen:
"snowboy" "rolladen hochfahren"
Was fehlt:
- Lautstärke dauerhaft abspeichern, auch nach Reboot
- Sprachausgabe über MQTT oder über Blockly per HTTP
- LEDs zum leuchten bringen
-
-
Hallo Jörg,
stimmt. Ich habe mich dazu ziemlich verkürzt geäußert. Korrekt ist natürlich, dass Das Node-Red-Programm diesen Datenpunkt am Mosquitto-Broker ansteuert und der mqtt.1-Client dieses Topic dort nur abholt und als ioBroker Datenpunkt anzeigt.
Aber wie gesagt, hat dieses Thema für mich momentan keine Priorität, solange es Dein Skript auch noch tut.
Gruß
Thomas -
Hallo Leif,
na da hat sich ja deine Beharrlichkeit ausgezahlt. Den Rest schaffst du auch noch.
-
@joergeli
OK, sehe gerade die Rhasspy MQTT-API gibt gar keine Sprachausgabe her. Hast du vielleicht irgendwo erfahren ob sich dies in Zukunft ändern soll? -
@capitaenz
Bin z.Zt im Streß, ich antworte heute abend ausführlicher.
Nur so viel: Ich hatte ja geschrieben, daß wir die Sprachausgabe über die HTTP-Api machen, weil wir es bis dato nicht über MQTT geschafft haben.
Ich habe das auch in meinem o.a. Script implementiert. -
@capitaenz sagte in Rhasspy Offline Sprachsteuerung:
Allerdings musste ich noch etwas probieren und von deiner Anleitung oben abweichen, denn ich musste unter MQTT nicht die IP des ioBroker, sondern die IP des Rhasspy eintragen.
Und das ist es was mich verwirrt. Denn ich bin davon ausgegangen, dass Rhasspy MQTT von haus aus unterstützt, denn es muss ja irgendwie an ein anderes System angebunden werden. Da habe ich geglaubt, dass die Entwickler natürlich MQTT mit eingebaut haben.Hatte ich nicht geschrieben, daß die IP des MOSQUITTO, also letztendlich die des Rhasspys eingetragen werden muss?
1.) Lautstärke dauerhaft abspeichern:
Kann ich nichts zu sagen, da ich für die Sprachausgabe den ioBroker PAW-Adapter nutze, der die Antworten auf einem Android-Tablet ausgibt.
Ausgabe über Lautsprecher hatte ich nur temporär über die 3,5mm Klinkenbuchse getestet.
Evtl.kann @tobetobe mehr dazu sagen?2.) Sprachausgabe über MQTT
Rhasspy hat einen internen MOSQUITTO, aber leider kann man - nach unseren Tests - darauf von außen (ioBroker) nicht zugreifen. Deshalb der Workaround mit dem zusätzlichen MOSQUITTO auf dem Rhasspy, auf den dann von ioBroker aus subscribed wird.
Wie schon erwähnt, konnte man mit der vorigen Rhasspy-Version 2.4.19 noch auf den internen MOSQUITTO zugreifen, bzw. dort einen externen MQTT (IP-iobroker/Port-beliebig) eintragen, das funktioniert - aus welchen Gründen auch immer - nicht mehr mit der Rhasspy V2.5-pre. Das hatte ich auch in einem issue schon gemeldet.
Evtl. wird das seitens Rhasspy noch gefixed?Du musst auch bedenken, daß Rhasspy nicht speziell für ioBroker gemacht ist, sondern primär für andere Systeme wie Home Assistant, Hass.io, und Node-RED.
Hier noch mal mein (gekürztes) JavaScript, welches nur die Sprachausgabe via HTTP-API über Lautsprecher macht.
Die Sprachbefehle werden aber weiterhin über die MQTT-API gesendet.
(bei Blockly bin ich raus)In Rhasspy habe ich dazu für die Sprachausgabe "Text to Speech" --> PicoTTS --> Language: de-DE gewählt,
was m.E. am natürlichsten klingt.//########################################################################## // Rhasspy-Voltron-intents (hier nur Rolladen) via MQTT-Client empfangen und entspr.Datenpunkte setzen/schalten // Ausgabe ueber Lautsprecher //########################################################################## // Für Sprachausgabe auf via HTTP-API auf Rhasspy let http = require('http'); let options = { host: 'xxx.xxx.xxx.xxx', //Hier Rhasspy IP-Adresse eintragen port: 12101, //Rhasspy Port muss so bleiben (HTTP-Api) 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.write(data); req.end(); } //______________________________________________________________________________ const rolladen = 'mqtt.1.hermes.intent.Rolladen' // Rolladen // Rolladen on({id: rolladen, change: "any"},function(obj) { let empf_code = getState(rolladen).val ; let empf_json = JSON.parse(empf_code); let name = empf_json.slots[0].value.value; //log ("name: " + name); let state = empf_json.slots[1].value.value; //log ("state: " + state); //log ("name: " + name + " state: " + state); if (name == "rolladen" && state == "hochfahren"){ //setState ('hm-rpc.0.PEQ0505813.1.STATE', true); // <--Hier entspr. Aktor eintragen let data = name + ' werden hochgefahren'; httpPost(data); } else if(name == "rolladen" && state == "runterfahren"){ //setState ('hm-rpc.0.PEQ0505813.3.STATE', true); // <--Hier entspr. Aktor eintragen let data = name + ' werden runtergefahren'; httpPost(data); } else if(name == "rolladen" && state == "stoppen"){ //setState ('hm-rpc.0.PEQ0505813.2.STATE', true); // <--Hier entspr. Aktor eintragen let data = name + " werden gestoppt "; httpPost(data); } }); //_____ Ende Rolladen-Auswertung _________________________________________ //################################################################################################ // WakeWord-Erkennung const wake = 'mqtt.1.hermes.asr.startListening' // Wakeword erkannt const unbekannt = 'mqtt.1.hermes.nlu.intentNotRecognized' // Datenpunkt Intent nicht erkannt on({id: wake, change: "any"},function(obj) { wakeword(); }); on({id: unbekannt, change: "any"},function(obj) { nicht_erkannt(); }); function wakeword(){ let data = "ja?" ; httpPost(data); } function nicht_erkannt(){ let data = "Entschuldigung, ich habe dich leider nicht verstanden"; httpPost(data); } // Ende WakeWord-ErkennungsScript //################################################################################################
Das sollte so funktionieren:
Du sagst "snowboy" --> Rhasspy antwortet über Lautsprecher "ja?"
Du sagst sofort nach dem "ja?" --> "rolladen hochfahren" --> Rhasspy antwortet über Lautsprecher "rolladen werden hochgefahren".
Teste mal, ob das bei Dir funktioniert.3.) LEDs zum leuchten bringen
Versuch mal, anstatt "kiboost" den LED-Pattern "projectalice":sudo systemctl stop hermesledcontrol
sudo nano /etc/systemd/system/hermesledcontrol.service --> hier anstatt kiboost del LED-pattern projectalice eintragen
sudo systemctl daemon-reload
sudo systemctl start hermesledcontrolIch kann aber nicht garantieren, daß das mit Deinem Respeaker 2-Mic funktioniert, da ich es nur mit meinem Respeaker 4 testen kann.
--
Wie mir in Deinem obigen Screenshot aufgefallen ist, wurde anscheinend Kaldi nicht installiert (--> not compatible)?
Falls dem so ist, muß der Docker-Container nochmals neu erstellt werden.
Das beschreibe ich, falls es wirklich zutrifft.
Nach unserer Erfahrung ist von den verschiedenen Optionen der Spracherkennung, Kaldi die zuverlässigste, bzw. genaueste.Gruß
Jörg -
Hat schon jemand versucht die Github Version zu installieren? Ich habe da drin leider nicht genug Routine. Habe mal den Docker von rhasspy/rhasspy installiert ( Last updated a day ago by rhasspy ) leider reagiert er weiterhin nicht auf das Wake Word.
-
hallo Leute,
Danke für die vielen Infos.
Aber bei mir bleiben noch ein paar Fragen offen:
Kann man den Docker auch unter Proxmox installieren?
Dann wäre meine "Cloud" im Netzwerkschrank im Keller.
Als Sateliten habe ich 4 Raspberies angedacht, die in verschiedenen Räumen verteilt werden sollen.
Der Raspberry PI3 würde als Satelit reichen?Gruß,
Mathias -
Hallo und willkommen in dieser Runde,
@MathiasJ said in Rhasspy Offline Sprachsteuerung:
Kann man den Docker auch unter Proxmox installieren?
Mit Proxmox habe ich persönlich leider keine Erfahrung, habe aber soeben mal das wesentliche hierzu schnell überflogen.Wenn ich das richtig verstanden habe, handelt es sich bei Proxmox um eine Linux basierte Virtualisierungsumgebung. Docker in Linux zu installieren, ist gar kein Problem. Auch habe ich Rhasspy, und damit Docker, schon in VMs, die auf Oracle Virtual Box basierten, ohne Probleme installieren können. Nach meiner Einschätzung, sollte das, was du vorhast, also auch machbar sein. Vielleicht gibt es einige Spezialitäten, die zu beachten sind. Versuch es einfach mal mit der Standardprozedur, wie sie @capitaenz oben beschrieben hat:
.
@capitaenz said in Rhasspy Offline Sprachsteuerung:
Ich fasse jetzt hier die Arbeit der letzten Tage zusammen, damit weitere Leute von Snips zu Rhasspy wechseln können:
@MathiasJ said in Rhasspy Offline Sprachsteuerung:
Der Raspberry PI3 würde als Satelit reichen?
Absolut, es genügt sogar ein Pi Zero für einen Satelliten. Wie schon oben erwähnt: Das Mikrofon ist das entscheidende Element.
Trau dich einfach mal ran, wir helfen gerne weiter.
Gruß
Thomas -
@capitaenz said in Rhasspy Offline Sprachsteuerung:
Hat schon jemand versucht die Github Version zu installieren?
Nein, ich sehe dazu auch keine Veranlassung. Der normale Pull mit dem dir bekannten Kommando genügt mMn vollkommen. Was versprichst du dir davon, ggf. eine Beta-Version von einer Beta-Version zu installieren?
Wenn es dir um die Lösung dieses Problems geht:
@capitaenz said in Rhasspy Offline Sprachsteuerung:
leider reagiert er weiterhin nicht auf das Wake Word.
dann wirst du die Lösung nicht durch die Installation der GitHub-Version finden. Das Problem muss in deiner Konfiguration liegen.
Hast du alles so, wie es @joergeli dir geschrieben hat, getestet? Wenn nicht, mach das erst einmal, bevor du neue Fässer aufmachst. Das ist nicht zielführend.
Wenn du uns hier deine Konfigurationen postest, und zwar einmal grafisch (die Einstellungen), und dann als Text (Kopie vom Profile), dann könnten wir mal drüberschauen, was da nicht stimmt. meistens sind es nur Kleinigkeiten.Das Profil findest du unter Home/Advanced
-
@tobetobe
Ich erhoffe mir dadurch eine Fehlerfreie Version von Rhasspy installiert zu bekommen, denn der Fehler ist ja bekannt:@joergeli said in Rhasspy Offline Sprachsteuerung:
Wie schon erwähnt, konnte man mit der vorigen Rhasspy-Version 2.4.19 noch auf den internen MOSQUITTO zugreifen, bzw. dort einen externen MQTT (IP-iobroker/Port-beliebig) eintragen, das funktioniert - aus welchen Gründen auch immer - nicht mehr mit der Rhasspy V2.5-pre. Das hatte ich auch in einem issue schon gemeldet.
-
@capitaenz said in Rhasspy Offline Sprachsteuerung:
Ich erhoffe mir dadurch eine Fehlerfreie Version von Rhasspy installiert zu bekommen, denn der Fehler ist ja bekannt:
Für mich nicht nachvollziehbar. Wir haben dir ein einwandfrei funktionierendes System an die Hand gegeben. Mit dem könntest du ohne Probleme arbeiten. Jetzt unbedingt mit dem ioBroker MQTT Adapter arbeiten zu wollen, erscheint mir als reine Liebhaberei. Sachlich / funktional gibt es dafür keinen Anlass. Ich würde die weitere Entwicklung einfach abwarten. Synthesiam wird eine Lösung schon eines Tages präsentieren.
Und wie gesagt: Dass dein Wakeword nicht erkannt wird, hat mit dem gemeldeten Fehlverhalten wirklich gar nichts zu tun.
-
@tobetobe
super, danke für die Hilfe!
Raspberry Zero w, noch besser.
Brauche dann mindestens 4 Stück davon
Als erstes lese ich mich bei Rhaspy und Proxmox ein, und komme später zurück.
Gruß,
Mathias -
@MathiasJ
"Kann man den Docker auch unter Proxmox installieren?
Dann wäre meine "Cloud" im Netzwerkschrank im Keller."Warum möchtest du eine Virtualisungsumgebung (Docker) unter eine Virtualisungsumgebung (Proxmox) installieren?
-
@zahnheinrich
Weil unter Proxmox bereits freePBX, RaspberryMatic und IObroker laufen. Sonst müsste ich einen weiteren PC, sei es nur einen Raspberry bemühen.
Das ist genau das, was ich verhindern will. -
@MathiasJ Und warum installierst du den rasspy nicht in Proxmox?