Approaches to room aware voice commands for Alexa with Node-Red

Thanks for the tip. The problem I’m solving there isn’t the rate, it’s that different echos are hearing the same command but I need to know which one specifically Amazon thinks was the closest so I can route based on that echo and not the others near it. For example before I had it both the echo in my master bath heard me when I was talking to the echo in my master bedroom and both fans would turn on. Rate limiting would make it so only one would turn on but it might be the wrong one.

I also edited my post above to note that I’m routing based on echo device name instead of serial number.

I am sufficiently simple in my needs. :smiley: If it would let you use Regex in the skill like you can in Node Red, that would be ideal but this is better than my 15-20 dummy rules.

1 Like

I agree; that would help.

At the moment, the “Parse” function node I created provides sufficient flexibility to support a choice of verbs and where the verb occurs in the phrase. There are no hard-coded entities; it works with any light, switch, or climate entity (albeit a single climate entity, because I only have one, and just for setting its target temperature). All of the entities are, of course, understood to be Hue lights because they are exposed to Alexa as emulated Hue devices.

The “Route” node is the only one with hard-coded entities because it performs the ‘room-awareness’ function. If “Turn on the light” is heard by the Guest Bathroom Alexa, it routes the request to the vanity light in the Guest Bathroom. Similarly, if the request is “Set the fan on” it is routed to the fan in the Guest Bathroom.

You inspired me to try it and it worked for me too (when I targeted a “real” Alexa-aware device and not an emulated Hue device). It also worked when the Input node contained a payload like:

[
    {
        "entity": "Bathroom Fan",
        "action": "turnOn",
        "value": ""
    }
]

So, basically, no mass-deletion of flows was done and cakebaked version works … except not in my existing flow (where a Template node formats the payload and passes it along to the SmartHome Action node).

The discrepancy I experienced with the “real” and “emulated” Alexa-aware devices convinced me to erase all registered entities from Amazon Alexa and re-discover them (the majority are based on node-red-contrib-amazon-echo, namely Hue emulation).

I also erased the file containing the cookie (used by node-red-contrib-alexa-cakebaked) and had it get a fresh one. This was necessary to ensure the SmartHome Action node had a list of the latest, registered devices.

Now the original flow works; room-awareness is back in business.

I wouldn’t discount that there might have been something else I did (unknowingly/unwittingly) to put this back on track. I’m willing to concede some PEBKAC because the solution (erase/re-discover; refresh cookie) seems kind of dubious. Anyway, all’s well that ends well.

1 Like

Interesting, so does using HomeAutomation mean the bathroom echo doesn’t fire with that domain name? What does it fire with, if any?

So the “right” Echo comes through with a data payload of:

payload.data.utteranceType: GENERAL
payload.data.domain: HomeAutomation

All of the other Echos that heard what I said but aren’t the one Amazon decided should respond to the command have payloads of:

payload.data.utteranceType: DEVICE_ARBITRATION
payload.data.domain: Unknown

I decided to filter on the “domain” parameter, but could have used the utteranceType as well to filter out the extra ones.

So to answer your specific question, the bathroom one fires correctly with the HomeAutoation domain if I’m in the bathroom talking to it (meaning Amazon thinks that Echo is the closest). I have 16+ Echo devices around the house so on almost every command more than one of them hears the command.

2 Likes

Wouldn’t that be the one that fires first? I just tried to incorporate your method, but I’ve realised that I don’t always just use it for ‘turn on something’. I also use it to mute my stereo when the wake word is heard, so I don’t have to shout over the top. I also use it to ask ‘what is the local weather?’ which then checks my weather station on the roof and gives me that temperature, but of course that is not part of the HomeAutomation domain.

I might try and incorporate the

payload.data.utteranceType: DEVICE_ARBITRATION

thing instead. But to be honest, I haven’t had too much trouble with it turning on the wrong thing, using purely rate limiting. Always ready to try new things to make it better though. And yeah, I have 13 devices. I think they breed in the dark. :slight_smile:

It would be nice if there were a way to know which device heard the command.
After all, Amazon knows which device to reply to.

It would be nice, for example, if you are in the living room and the Alexa device name is “Living Room” that you wouldn’t have to say “Alexa, turn on the living room light” when you are in the living room and talking to the Alexa living room device. Then it would be as simple as “Alexa, turn on the light”.

That information is reported by the Alexa Event Node as a payload property.

The rest of what you described is what the flows presented in this topic are achieving. Say “Turn on the light” and if heard by the bathroom Alexa, the bathroom light is turned on.

If you meant it would be nice if this functionality was baked into Amazon Alexa, then it currently has a means of implementing it using a Smart Device Group. However, it isn’t quite as flexible as what users have presented in this thread based on node-red-contrib-alexa-remote2 .

Thanks. I am using other nodes in Alexa Remote2, but I hadn’t looked at the Alexa Event node.

It’s the node used by almost all flows posted in this thread. It appears as “On Device Activity” in the posted screenshots.

I’m using msg.payload.deviceSerialNumber and comparing the value (a long alphanumeric string) with the serial number of each Echo device to determine which one is responding to the spoken command. The code for it is posted far above in my first post within this thread.

If you don’t make your request too fast, the on device activity node sends a msg.payload.data.utteranceType == WAKE_WORD_ONLY for the listening device.

If you make your requests really fast, you can filter which device is listening when:

msg.payload.data.utteranceType == GENERAL

and

payload.description.summary contains alexa

I filter them this way and it’s flawless.

[{"id":"3191affe.74692","type":"alexa-remote-event","z":"877467b7.3b2fb8","name":"Listening to Alexa events","account":"bb44c27d.b8d5a","event":"ws-device-activity","x":230,"y":1320,"wires":[["fb442699.1853a8"]]},{"id":"fb442699.1853a8","type":"switch","z":"877467b7.3b2fb8","name":"","property":"payload.data.utteranceType","propertyType":"msg","rules":[{"t":"eq","v":"WAKE_WORD_ONLY","vt":"str"},{"t":"eq","v":"GENERAL","vt":"str"}],"checkall":"false","repair":false,"outputs":2,"x":415,"y":1300,"wires":[["38141a56.873b86"],["e98f9246.cb6d5"]],"l":false},{"id":"e98f9246.cb6d5","type":"switch","z":"877467b7.3b2fb8","name":"","property":"payload.description.summary","propertyType":"msg","rules":[{"t":"cont","v":"alexa","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":455,"y":1340,"wires":[["38141a56.873b86"]],"l":false},{"id":"38141a56.873b86","type":"debug","z":"877467b7.3b2fb8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":580,"y":1320,"wires":[]},{"id":"bb44c27d.b8d5a","type":"alexa-remote-account","name":"Edu","authMethod":"proxy","proxyOwnIp":"192.168.1.29","proxyPort":"1234","cookieFile":"/config/.storage/authentication2","refreshInterval":"1","alexaServiceHost":"alexa.amazon.es","amazonPage":"amazon.es","acceptLanguage":"es-SP","userAgent":"","useWsMqtt":"on","autoInit":"on"}]

Well wouldn’t you know it, I had a problem last night with it picking up the wrong echo. Spoke too soon. I incorporated your tips, thanks @apnar and it works well for devices, and other utterances.

[{"id":"40539fa4.dadab8","type":"tab","label":"contextual routines","disabled":false,"info":""},{"id":"1f04bf8f.30ea5","type":"change","z":"40539fa4.dadab8","name":"Strip Wake Word","rules":[{"t":"change","p":"payload.description.summary","pt":"msg","from":"^(alexa )?","fromt":"re","to":"","tot":"str"},{"t":"change","p":"payload.description.summary","pt":"msg","from":"^(amazon )?","fromt":"str","to":"","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1230,"y":540,"wires":[["b7255960.3427c"]]},{"id":"90c1d642.6a8928","type":"alexa-remote-event","z":"40539fa4.dadab8","name":"Amazon Account 1","account":"","event":"ws-device-activity","x":210,"y":480,"wires":[["2719c088.60b7c"]]},{"id":"79d11927.38918","type":"alexa-remote-event","z":"40539fa4.dadab8","name":"Amazon Account 2","account":"","event":"ws-device-activity","x":210,"y":560,"wires":[["2719c088.60b7c"]]},{"id":"8d80fd02.eda358","type":"delay","z":"40539fa4.dadab8","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"2","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"x":1040,"y":480,"wires":[["1f04bf8f.30ea5"]]},{"id":"5f649b70.1df99c","type":"switch","z":"40539fa4.dadab8","name":"Alexa hears","property":"payload.description.summary","propertyType":"msg","rules":[{"t":"regex","v":"alexa|amazon","vt":"str","case":true},{"t":"regex","v":"^(?:(?!amazon|alexa).)+$","vt":"str","case":true}],"checkall":"false","repair":false,"outputs":2,"x":770,"y":520,"wires":[["8d80fd02.eda358"],["505f5f7e.f54c7"]],"outputLabels":["Turn on",""]},{"id":"505f5f7e.f54c7","type":"delay","z":"40539fa4.dadab8","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"2","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"x":1040,"y":580,"wires":[["1f04bf8f.30ea5"]]},{"id":"b7255960.3427c","type":"change","z":"40539fa4.dadab8","name":"Clear Data","rules":[{"t":"delete","p":"payload.data","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1430,"y":540,"wires":[[]]},{"id":"2719c088.60b7c","type":"switch","z":"40539fa4.dadab8","name":"Only if NOT \"DEVICE_ARBITRATION\"","property":"payload.data.utteranceType","propertyType":"msg","rules":[{"t":"neq","v":"DEVICE_ARBITRATION","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":490,"y":520,"wires":[["5f649b70.1df99c"]]},{"id":"d6e529.07842ad8","type":"comment","z":"40539fa4.dadab8","name":"Wake Word | Command","info":"","x":800,"y":480,"wires":[]},{"id":"9257dd57.c8345","type":"comment","z":"40539fa4.dadab8","name":"Drop duplicate commands","info":"","x":1070,"y":440,"wires":[]}]

Anyone else have their device activity just stop reporting ANYTHING? Looks like a change on Amazon’s end has screwed the pooch for us. :frowning:

Edit: Aaaaand, it’s back working again.

Edit x2: and broken again. Looks like a new approach is necessary.

I’ve been using this setup for awhile, and yeah, it seems like it stops working for a few days, then starts again, then stops. It is currently down. If anyone knows a different way to implement room-aware commands, please post.

I believe Amazon changed something recently:

I updated the NR nodes with the ones here:

It solved the problem for me.

2 Likes

Yesterday, I replaced node-red-contrib-alexa-remote2-cakebaked with node-red-contrib-alexa-remote2-applestrudel. It works but, like with all previous versions of alexa-remote2, its reliability is the question and it may take a week or more to answer that.

Anyway, so far so good; this morning’s announcement played on schedule and room-awareness is functional.

1 Like

Looks like the apple strudel version doesn’t work now. :frowning:

Anyone found an alternative way to get around this problem?

1 Like

I can confirm that it is no longer able to connect to Amazon Alexa’s services.

The author of apple strudel believes the API may have changed.