Can't get Rhasspy to recognize microphone/speaker. Can't send intents to home assistant

I have been trying all weekend to get Rhasspy up and running. It’s installed and I’ve got a USB microphone/headset combo connected to the RasPi4B on which HAOS and Rhasspy are installed.

When I visit the Rhasspy WebUI, Rhasspy doesn’t seem to recognize that I have a microphone or speaker connected. If I press “wake” and start speaking a command, the Rhasspy UI eventually tells me that it timed out.

If I type Hello into the text to speech field and press Speak, nothing comes through on the headset (speakers).

My ultimate goal/plan is to use the RasPi as a server only and let satellites send it voice data. So no microphone or speaker should be needed (in theory at least – I don’t know for sure). So I decided to forgo that and configure Rhasspy to send intents to HA.

I typed a sentence in the Recognize field that I know is part of the sentences file and pressed the Recognize button. It parsed the sentence correctly (the json shows it correctly) but HA shows no indication that it received the intent.

I assumed I had done something wrong during the initial installation and configuration of Rhasspy so I uninstalled Rhasspy then reinstalled it with the intention of starting over. All the changes previously made were still there. So even uninstalling and reinstalling Rhasspy didn’t help.

What can I do?

I don’t know if this is related or not but it’s something that at least SEEMS like it could cause problems.

I’ve had my RasPi4B set up and running with HAOS since June of last year. It is configured to use DuckDNS and LetsEncrypt so that I can use it with Google assistant (once I get Rhasspy working, I plan to stop using the GA devices). But when visiting the Rhasspy WebUI, I have to use the internal IP address and the port number vs the DuckDNS address and port number.

Edit to add: at first, I installed the junior version. But since it didn’t seem to be utilizing my speaker(microphone, I uninstalled Rhasspy and installed the full version so that I’d have the webUI where I could type in sentences to try and pass to HA.

Bump - don’t want it to get lost in the shuffle.

Ok, you have two separate issues.

  1. You are using HAOS which installs HA and Rhasspy in separate Docker containers. You will need to get the Docker container for Rhasspy to connect to the USB microphone and speaker. I don’t use this configuration so don’t have the answer off the top of my head - but it has come up before in this forum; and I’m pretty sure it is mentioned in the Rhasspy documentation

  2. There are 3 or more methods for Rhasspy to send intents to Home Assistant. For the Rhasspy “Intent handling” setting, are you using “Home Assistant” + Intents, “Home Assistant” + Events, or “Remote HTTP” ?
    I started using Rhasspy with HA sending the intents using the Home Assistant + Intents method, and it works fine (though I found that I needed to setup a long-lived access token). I documented this here

In the HA > Add-ons > Rhasspy Assistant you can look at the [Log] tab. There is an awful lot of DEBUG messages there, but among them you should find some that are helpful (eg search for “hermes/intent/”) .

I’m curious that you don’t want to use internal IP addresses. I find they have less overhead, both in terms of devices becoming available on the network quicker, and quicker to pass messages over the LAN; and of course one less component to go wrong :wink:

  1. I’ve dug through the docs and didn’t find anything that helped fix the issues. I don’t know if I was just looking for the wrong info or what.

  2. I’ve tried both the intents and events methods. I didn’t know where to begin with “remote http” so I didn’t try that.

As to the question of using a local IP. I never said I don’t want to. I mentioned that I AM using the local IP to access Rhasspy webUI. I thought that MAYBE that could be contributing to the issues. I would much prefer to keep as much of the network traffic inside the LAN as possible – if my Internet fails, Rhasspy will continue to work.

I started with using the Home Assistant + Intents method, and it worked fine. I suggest having a look at this part of my tutorial. Note that you may not need to setup a long-lived access token as i did.

You mention in another post that you would be happy to use node-RED, which is yet another option.

I’ll try NR.

When I configured it to use intents, I set up the long live token.

And you also added Note the keywords “intent:” and “intent_script:” to HA configuration.yaml ? BOTH are required.
I chose to place the actual intents in a separate include file to make them easier to edit; but you can simply list the intents directly after “intent_script:”.

intent: 
intent_script: !include intents.yaml

Beyond that, I’m not sure what can go wrong. There may be something in one of the various log files, but I’m not sure which one to look in.


If you are interested in the NR route, I recommend Paul Romkes’ rhasspy wiki Intent Handling with HA and Node Red tutorial,

Configuring the MQTT In node is straightforward

My Rhasspy flow looks complicated because my Kitchen and Living_room satellites often hear (and try to process) the same command simultaneously … resulting in me using session variables to check if the intent being processed is the same one processed <3 seconds ago. Added to that, there are plenty of false alarms from the TV :wink:

[{"id":"13b29f95.47317","type":"switch","z":"b74f060c.6b2908","name":"find intent","property":"payload.intent.intentName","propertyType":"msg","rules":[{"t":"eq","v":"WatchTvChannel","vt":"str"},{"t":"eq","v":"WatchProgramme","vt":"str"},{"t":"eq","v":"GoodMorning","vt":"str"},{"t":"eq","v":"Dinnertime","vt":"str"},{"t":"eq","v":"GetTemperature","vt":"str"},{"t":"eq","v":"WeatherCurrent","vt":"str"},{"t":"eq","v":"WeatherForecast","vt":"str"},{"t":"eq","v":"Movietime","vt":"str"},{"t":"eq","v":"GetTime","vt":"str"},{"t":"eq","v":"TVoff","vt":"str"},{"t":"eq","v":"GoodNight","vt":"str"},{"t":"eq","v":"Play","vt":"str"},{"t":"eq","v":"TimerSet","vt":"str"},{"t":"eq","v":"TimerCancel","vt":"str"},{"t":"eq","v":"ChangeSwitchState","vt":"str"},{"t":"eq","v":"ChangeCoverState","vt":"str"},{"t":"eq","v":"ChangeCoverLevel","vt":"str"},{"t":"eq","v":"ChangeLightState","vt":"str"},{"t":"eq","v":"ChangeLightBrightness","vt":"str"},{"t":"eq","v":"XMASLights","vt":"str"},{"t":"else"}],"checkall":"false","repair":false,"outputs":21,"x":100,"y":720,"wires":[["eb98925768dc9495"],["8aa8328b2b29c9e5"],["f67084dc288b4bc3"],["3714768a7b16ba91"],["cbe27e388ccedef7"],["e337cc3fb23a3756"],["3586706ae38d0dcd"],["e0e58732b65afd0d"],["79279baa.e9e9d4"],["802d9c301fe10e25"],["2edc03f6e9bd21e2"],["4a57d326c3aa8048"],["205297a969810602"],["45aadc897818c429"],["c25a5fe4915e4c80"],["e6889705dcae7372"],[],["5d0b70fd3a9f7a96"],["497278a27faff99c"],["0fdb581e2d9c6372"],["f058b4b213fc15b6"]]},{"id":"79279baa.e9e9d4","type":"function","z":"b74f060c.6b2908","name":"GetTime","func":"\n\n// Extract Hours and Minutes \nvar date = new Date();\nvar timeH = date.getHours();\nif (timeH > 12) { timeH -= 12 }     // afternoon to 12-hour clock\nvar timeM = date.getMinutes();\nnode.warn(\"Hours=\" + timeH +\", Min=\"+ timeM);\n\n// say a leading \"oh\" if less than 10 minutes past the hour\nvar timeStringM = timeM;\nif (timeM == 0) { \n    timeStringM = \"oh clock\" \n} else if (timeM < 10) { \n    timeStringM = \"oh \" + timeM \n};\n\nmsg.payload = \"The time is \" + timeH + \" \" + timeStringM;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":380,"y":640,"wires":[["ada61f79f15bb868"]]},{"id":"f67084dc288b4bc3","type":"link call","z":"b74f060c.6b2908","name":"","links":["620d653529fbe536"],"timeout":"30","x":420,"y":400,"wires":[["ada61f79f15bb868"]]},{"id":"2edc03f6e9bd21e2","type":"link call","z":"b74f060c.6b2908","name":"","links":["4963009a35c24980"],"linkType":"static","timeout":"600","x":410,"y":720,"wires":[["ada61f79f15bb868"]]},{"id":"e0e58732b65afd0d","type":"link call","z":"b74f060c.6b2908","name":"","links":["ea8c42aa5725fb01"],"timeout":"30","x":410,"y":600,"wires":[["ada61f79f15bb868"]]},{"id":"3714768a7b16ba91","type":"link call","z":"b74f060c.6b2908","name":"","links":["5227b56088071a3f"],"timeout":"30","x":410,"y":440,"wires":[["ada61f79f15bb868"]]},{"id":"e337cc3fb23a3756","type":"link call","z":"b74f060c.6b2908","name":"","links":["90eb5fa0d241d6e7"],"timeout":"30","x":400,"y":520,"wires":[["ada61f79f15bb868"]]},{"id":"cbe27e388ccedef7","type":"link call","z":"b74f060c.6b2908","name":"","links":["efeff2c75b6558b7"],"timeout":"30","x":400,"y":480,"wires":[["ada61f79f15bb868"]]},{"id":"3586706ae38d0dcd","type":"link call","z":"b74f060c.6b2908","name":"","links":["0434d546133de08e"],"timeout":"30","x":410,"y":560,"wires":[["ada61f79f15bb868"]]},{"id":"4a57d326c3aa8048","type":"link call","z":"b74f060c.6b2908","name":"","links":["0758a72b677e6fd7"],"timeout":"30","x":410,"y":760,"wires":[["ada61f79f15bb868"]]},{"id":"eb98925768dc9495","type":"change","z":"b74f060c.6b2908","name":"tidy TV channel name","rules":[{"t":"change","p":"slots.channel","pt":"msg","from":"seven","fromt":"str","to":"TV channel 7","tot":"str"},{"t":"change","p":"slots.channel","pt":"msg","from":"nine","fromt":"str","to":"TV 9Now","tot":"str"},{"t":"change","p":"slots.channel","pt":"msg","from":"ten","fromt":"str","to":"TV 10play","tot":"str"},{"t":"change","p":"slots.channel","pt":"msg","from":"abc","fromt":"str","to":"TV ABC","tot":"str"},{"t":"change","p":"slots.channel","pt":"msg","from":"sbs","fromt":"str","to":"TV SBS","tot":"str"},{"t":"change","p":"slots.channel","pt":"msg","from":"rai","fromt":"str","to":"TV RAI Italy","tot":"str"},{"t":"change","p":"slots.channel","pt":"msg","from":"stan","fromt":"str","to":"STAN","tot":"str"},{"t":"change","p":"slots.channel","pt":"msg","from":"ted","fromt":"str","to":"TED","tot":"str"},{"t":"change","p":"slots.channel","pt":"msg","from":"prime","fromt":"str","to":"Amazon Prime","tot":"str"},{"t":"change","p":"slots.channel","pt":"msg","from":"binge","fromt":"str","to":"BINGE","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":420,"y":320,"wires":[["ded5b9e04e3d4e72"]]},{"id":"ded5b9e04e3d4e72","type":"link call","z":"b74f060c.6b2908","name":"","links":["43ee774c3579cae2"],"timeout":"90","x":660,"y":320,"wires":[["ada61f79f15bb868"]]},{"id":"8aa8328b2b29c9e5","type":"link call","z":"b74f060c.6b2908","name":"","links":["2672aeb014579af3"],"timeout":"90","x":430,"y":360,"wires":[["ada61f79f15bb868"]]},{"id":"58b18b2324312465","type":"comment","z":"b74f060c.6b2908","name":"process all voice commands","info":"Rhasspy is used on the several satellite machines to parse voice commands, which are then sent here. \n\nVoice commands are defined in \"sentences.ini\" on the base Rhasspy machine (http://homeassistant.local:12101/sentences). Valid commands are called \"intents\". \n\nRhasspy uses MQTT to communicate between modules running on Base and Satellite machines. Node-RED's \"websocket intent listener\" listens to the intents ... and this is where we process them. \n","x":140,"y":40,"wires":[]},{"id":"de42b45806fed3ec","type":"comment","z":"b74f060c.6b2908","name":"Check for multiple satellies responding","info":"because of open plan layout, often the Kitchen and Living room satellites both respond to the same voice command.\n\nSuggestion at https://laurentchervet.wordpress.com/2019/03/06/satellites-and-the-multidetection-hell/ seems to be to assume the first satellite to respond is the one which is closest (because sound takes time to travel); and so simply  take the first command that arrives, and ignore any other sites which also respond within 0.3 seconds.  This doesn't seem to allow for the RasPi Zero's slower processor - I will have to do some tests. \nHis solution is basically to set a global variable when the first response arrives, and for each incoming intent to be cheched against this global variable. \n\nEasily resolved using the optional node-red-contrib-semaphore \n\nI want to unlock the flag immediately on ending the Rhasspy session - but I also need the session to time out if there was an error which prevented getting to the endSession !\n","x":180,"y":140,"wires":[]},{"id":"cfa38da8e49eb8ce","type":"mqtt in","z":"b74f060c.6b2908","name":"","topic":"hermes/intent/#","qos":"2","datatype":"json","broker":"3e24a26f3fe6c572","nl":false,"rap":true,"rh":0,"inputs":0,"x":100,"y":80,"wires":[["067b4454e5a11716","fd7c2510f82f999a"]]},{"id":"067b4454e5a11716","type":"debug","z":"b74f060c.6b2908","name":"MQTT intent listener","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":380,"y":80,"wires":[]},{"id":"ab75bd4c6654464d","type":"mqtt out","z":"b74f060c.6b2908","name":"","topic":"hermes/dialogueManager/endSession","qos":"","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"3e24a26f3fe6c572","x":1170,"y":660,"wires":[]},{"id":"ada61f79f15bb868","type":"template","z":"b74f060c.6b2908","name":"End Session","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"{\n    \"sessionId\": \"{{sessionId}}\",\n    \"siteId\": \"{{siteId}}\",\n    \"text\": \"{{payload}}\"\n}","output":"json","x":830,"y":600,"wires":[["42726d46b392562f","dc78817c08e95239"]]},{"id":"42726d46b392562f","type":"debug","z":"b74f060c.6b2908","name":"end-session","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1070,"y":720,"wires":[]},{"id":"5a74138a02d2baa2","type":"debug","z":"b74f060c.6b2908","name":"globals saved","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":980,"y":260,"wires":[]},{"id":"126e7c57a0e452d5","type":"debug","z":"b74f060c.6b2908","name":"ERROR: INTENT NOT RECOGNISED","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":810,"y":1120,"wires":[]},{"id":"e7354935ba862272","type":"inject","z":"b74f060c.6b2908","name":"In case of rhasspy non-respond","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":930,"y":480,"wires":[["dc78817c08e95239"]]},{"id":"725a6649afe169ea","type":"switch","z":"b74f060c.6b2908","name":"already inSession","property":"inSession","propertyType":"msg","rules":[{"t":"true"},{"t":"else"}],"checkall":"false","repair":false,"outputs":2,"x":730,"y":200,"wires":[["1aa6b7d178818ef4","08f27e5ca822e8de"],["5a74138a02d2baa2","c4b70ab633dca027"]]},{"id":"08f27e5ca822e8de","type":"mqtt out","z":"b74f060c.6b2908","name":"","topic":"hermes/dialogueManager/endSession","qos":"","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"3e24a26f3fe6c572","x":1030,"y":200,"wires":[]},{"id":"dc78817c08e95239","type":"change","z":"b74f060c.6b2908","name":"reset global.inSession","rules":[{"t":"set","p":"inSession","pt":"global","to":"false","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":1090,"y":600,"wires":[["ab75bd4c6654464d"]]},{"id":"06b6f9593ee21ca6","type":"comment","z":"b74f060c.6b2908","name":"Ignore the secondary satellite","info":"This is the situation where another satellite is already processing a spoken request - most paobably they both heard the same verbal command, so we only want to process the first one ","x":960,"y":120,"wires":[]},{"id":"1aa6b7d178818ef4","type":"debug","z":"b74f060c.6b2908","name":"ignoring secondary satellite","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1000,"y":160,"wires":[]},{"id":"fd7c2510f82f999a","type":"function","z":"b74f060c.6b2908","name":"Check session and extract all slots","func":"/*\nSometimes the Living room and Kitchen Rhasspy satellites \nboth respond to the same command, almost simultaneously. \n\nIn theory the closest should respond first because speed of \nsound, and the other should be ignored. However: \n (a) RasPi Zero has a slower processor\n (b) could be that a totally different comand is given elsewhere\n (c) assume Node-RED is multi-thread, so could be processing \n    commands simultaneously (though on my RasPi4 this does not \n    seem to be the case)\n \ncheck for a second Rhasspy satelite responding within 3 seconds \n    with the same intent - but maybe misheard\n\nProcedure:\n - check whether received within 3 seconds of last intent. \n - check for low voice recognition confidence\n - if not, record details of the current session and intent to compare against \n - start other processing\n\nVariables in the global scope\n - lastSession.time         datetime that last session started\n - lastSession.intentName   what intent is being processed\n Note: It appears that we have to use set and get for global variables\n\nReturn msg.inSession is true if the current process should be abandoned\n\n*/\n\n// what if Rhasspy doesn't have much confidence in the command ?\n//  probably because it mis-heard\n//  Check it now, so msg.intent.name stores what WAS heard, in case we want it later\n\nif (msg.payload.asrConfidence < 0.4) {\n    msg.payload = '{ \"sessionId\": \"' + msg.payload.sessionId + '\", \"siteId\": \"' + msg.payload.siteId + '\", \"text\": \"I didnt hear that clearly\"}';\n    msg.inSession = true;\n    return msg;\n}\n\n\n// Node-RED seems single thread, so we are not currently processing another intent.\n// but maybe we only just finished process the last command ?\n\nlet currTime = Date.now();\nlet lastSession = global.get(\"lastSession\");\n// node.warn(\"lastSession.intentName=\"+ lastSession.intentName +\", lastSession.time=\"+ lastSession.time );\n\nvar seconds = Math.abs(currTime - lastSession.time) / 1000;\n// node.warn(\"last intent received \"+ seconds +\" seconds ago.\");\nif (seconds < 3) {\n    // less than 3 seconds - assume the same intent heard (or mis-heard)\n    //  by another satellite\n    msg.payload = '{ \"sessionId\": \"' + msg.payload.sessionId + '\", \"siteId\": \"' + msg.payload.siteId + '\", \"text\": \"\"}';  // no voice response\n    msg.inSession = true;\n    return msg;\n}\n\n//\n//  Not already processing another session ... so start process this one\n//\n\n// save the variables used to determine current session\nlastSession = {time: currTime, sessionId: msg.payload.sessionId, intentName: msg.payload.rawInput, confidence: msg.payload.asrConfidence };\nglobal.set(\"lastSession\", lastSession);\n\n//  MQTT in node returned the Rhasspy slots in the array msg.payload.slots. \n//  This code parses the array into a list of name and value pairs,\n//      which will be much easier to work with\n//\nvar slot;\nvar newslots = {};                  // create a new empty object\nfor (var i in msg.payload.slots) {\n    slot = msg.payload.slots[i];     // one array element at a time\n    //new name and value pair\n    newslots[slot.slotName] = slot.value.value;\n}\nmsg.slots = newslots;               // save back into msg.\nmsg.intent = {};\nmsg.intent.name = msg.payload.intent.intentName;\nmsg.intent.confidence = msg.payload.asrConfidence;\nmsg.sessionId = msg.payload.sessionId;\nmsg.siteId = msg.payload.siteId;\n\n//node.warn(\"ready to return\");\nreturn msg;","outputs":1,"noerr":0,"initialize":"// Code added here will be run once\n// whenever the node is started.\n\nglobal.inSession = false;\n\nvar lastSession = {time: Date.now(), sessionId: \"\", intentName: \"\", confidence: 0 };\nglobal.set(\"lastSession\", lastSession);\n\nreturn;\n","finalize":"","libs":[],"x":410,"y":180,"wires":[["a6cf562714dc6595","725a6649afe169ea"]]},{"id":"a6cf562714dc6595","type":"debug","z":"b74f060c.6b2908","name":"slots extracted","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":700,"y":140,"wires":[]},{"id":"5d0b70fd3a9f7a96","type":"link call","z":"b74f060c.6b2908","name":"","links":["defb47cac878fba1"],"timeout":"30","x":430,"y":1000,"wires":[["ada61f79f15bb868"]]},{"id":"497278a27faff99c","type":"link call","z":"b74f060c.6b2908","name":"","links":["626a7cf1e161a589"],"timeout":"30","x":450,"y":1040,"wires":[["ada61f79f15bb868"]]},{"id":"f058b4b213fc15b6","type":"change","z":"b74f060c.6b2908","name":"Invalid command message","rules":[{"t":"set","p":"payload","pt":"msg","to":"Invalid command","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":440,"y":1120,"wires":[["ada61f79f15bb868","126e7c57a0e452d5"]]},{"id":"802d9c301fe10e25","type":"link call","z":"b74f060c.6b2908","name":"","links":["a39703c7a0c52b1e"],"timeout":"30","x":390,"y":680,"wires":[["ada61f79f15bb868"]]},{"id":"205297a969810602","type":"link call","z":"b74f060c.6b2908","d":true,"name":"intent_timerSet","links":[],"linkType":"static","timeout":"30","x":400,"y":800,"wires":[["ada61f79f15bb868"]]},{"id":"45aadc897818c429","type":"link call","z":"b74f060c.6b2908","name":"intent_timercancel","links":["60d742cd691a5345"],"linkType":"static","timeout":"30","x":410,"y":840,"wires":[["ada61f79f15bb868"]]},{"id":"0fdb581e2d9c6372","type":"link call","z":"b74f060c.6b2908","name":"","links":["c1f781746184e241"],"linkType":"static","timeout":"30","x":380,"y":1080,"wires":[["912fc502dfbbd0c4"]]},{"id":"912fc502dfbbd0c4","type":"template","z":"b74f060c.6b2908","name":"Light Text","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"Christmas is {{slots.state}}!","output":"str","x":600,"y":1080,"wires":[["ada61f79f15bb868"]]},{"id":"c25a5fe4915e4c80","type":"link call","z":"b74f060c.6b2908","name":"","links":["b67399100cf149d2"],"linkType":"static","timeout":"30","x":440,"y":880,"wires":[["ada61f79f15bb868"]]},{"id":"e6889705dcae7372","type":"link call","z":"b74f060c.6b2908","name":"","links":["162c5b523c2f9e2f"],"linkType":"static","timeout":"30","x":430,"y":920,"wires":[["ada61f79f15bb868"]]},{"id":"c4b70ab633dca027","type":"junction","z":"b74f060c.6b2908","x":40,"y":340,"wires":[["13b29f95.47317"]]},{"id":"3e24a26f3fe6c572","type":"mqtt-broker","name":"HA MQTT broker add-on","broker":"192.168.1.98","port":"1883","clientid":"","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"userProps":"","sessionExpiry":""}]

Because NR is intercepting the MQTT Intent messages, you should set “Intent Handling” on all your Rhasspy devices to “disabled”.

Thanks for all the advice. I was able to get Rhasspy to communicate with NR which then was able to turn A LIGHT on and off. It literally just toggles it.

Next step it to figure out how to get NR to turn it on of that’s what was requested or off it that’s what was requested. That and to have NR understand WHICH light to change. I’d really rather not have a separate flow/subflow for every light fixture in my house.

But this was a big step in the right direction!

I’ve found audio in HA to be very flakey currently. I’m using a USB microphone and getting it to use that involved a lot of tweaking and container restarts. ‘ha audio …’ and ‘pactl …’ are your friends here. Random guessing: your internal pi microphone was probably the default. Start with ‘ha audio info’ and look for the input section. If it isn’t listing your USB microphone as the default, then you have to do some finagling.

As long as I can get satellites to pick up my voice requests and send them to the Rhasspy server for processing and then get HA to handle the intents, I’m not too concerned about gett the headset working on the server.

I was able to get Node Red to receive the instructions from Rhasspy (typing the requests into the webUI). Node Red then tells HA what to do.

Next step is to get Rhasspy Android app working as a satellite.