Trying to get Alexa to read out a temperature

Gentlemen
I have a Sonoff TH16 in my living room with a temperature sensor delivering its Celsius values into a Node Red flow. This is then displayed in a dashboard widget. The next step is that I would like my Alexa device to be able to inform me of the temperature when I ask "Alexa what is the temperature in the living room" I just need her to retrieve the dashboard temperature data and speak it. Seems rather trivial but I'm going round in circles.

I have installed the Remote2 set of nodes and I can get Alexa to speak a predetermined phrase, but of course the temperature is always changing so I need to somehow point Alexa's nose to this data and get her to read it out when requested.

Any tips chaps?

I have a sonoff th16 linked to alexa with sonoff skill. If i say Alexa, what is the temperature of kitchen extractor, alexa replies with the current temp of the device.

You can also query the device with the remote2 smarthome node
e.g.

[{"id":"8a51cb16.f75ca","type":"inject","z":"c791cbc0.84f648","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":140,"y":200,"wires":[["a4c466ba.48e2a"]]},{"id":"a4c466ba.48e2a","type":"alexa-remote-smarthome","z":"c791cbc0.84f648","name":"","account":"c8738129.d902c","config":{"option":"query","value":[{"entity":"cd41cd6f-1e0e-46aa-968e-d54d42c6b12b","property":"temperature"}]},"outputs":1,"x":460,"y":200,"wires":[["d346a058.47b348"]]},{"id":"d346a058.47b348","type":"debug","z":"c791cbc0.84f648","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":620,"y":60,"wires":[]},{"id":"c8738129.d902c","type":"alexa-remote-account","name":"alexa remote 2","authMethod":"proxy","proxyOwnIp":"localhost","proxyPort":"3456","cookieFile":"","refreshInterval":"14","alexaServiceHost":"layla.amazon.co.uk","amazonPage":"amazon.co.uk","acceptLanguage":"en-GB","userAgent":"","useWsMqtt":"on","autoInit":"off"}]

Output

{"value":19.7,"scale":"CELSIUS"}

I use node-red-contrib-amazon-echo as a trigger for flows and set responses in routines or you can use blueprint Q&A.

There are a few ways to do this.

You could setup a vitrtual device and use that to supply the data to Alexa via the response node, using the alexa-home-skill

Or you could use Alexa blueprints as detailed here -

Thanks for those suggestions chaps. I'll investigate them tomorrow.

E1cid.
In answer to your kind response. I have been trying to find a sonoff skill in Alexa but when searching the skill menu nothing comes up. Also my Sonoff devices have all been flashed with Tasmota so I don't think this skill would work without the pucker Sonoff firmware installed. All I need is to take the MQTT sensor temperature data from the Sonoff into some kind of Alexa speech node which she can then read out when requested. I don't really want to go down the Blueprints road as I'm having difficulty with this simple stuff without the complexities of setting up data bases and the like. Thanks

I run node red on a raspberry pi which is connected by bluetooth to Alexa, which is used as a bluetooth speaker. The raspberry pi node red flow include the wemo-emulator node so that the flow can be addressed by an audible instruction from Alexa.

The text to speech is dependent on an internet connection to https://translate.google.com and the mp3 output is an via ffmpeg and aplay which are installed by default on the raspberry pi.

image

[{"id":"88bc7ff238ee11b3","type":"ui_text_input","z":"e273b97f.97c148","name":"Dynamic","label":"Dynamic:  APLAY as wav after coverting from mp3","tooltip":"","group":"0e9c5f30215bb24c","order":6,"width":0,"height":0,"passthru":true,"mode":"text","delay":"0","topic":"topic","sendOnBlur":false,"className":"","topicType":"msg","x":120,"y":1300,"wires":[["b14ec78481324685"]]},{"id":"b14ec78481324685","type":"function","z":"e273b97f.97c148","name":"TTS","func":"msg.payload = encodeURIComponent(msg.payload.trim());// replace spaces with %20 for url GET REQUEST\nmsg.url =\"https://translate.google.com/translate_tts?ie=UTF-8&client=tw-ob&tl=en&q=\"+msg.payload;\nmsg.payload = \"'\"+msg.url+\"'\";// need enclose REQUEST in quotes\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":270,"y":1300,"wires":[["a444e30475b8f12e","421cf47fca038cb0"]]},{"id":"421cf47fca038cb0","type":"exec","z":"e273b97f.97c148","command":"ffmpeg  -i ","addpay":"payload","append":"-f wav - | DISPLAY=:0 aplay","useSpawn":"false","timer":"","winHide":false,"oldrc":false,"name":"","x":460,"y":1300,"wires":[[],[],[]]},{"id":"0e9c5f30215bb24c","type":"ui_group","name":"Text to Sound via Google Translate","tab":"b6152d595c55a32b","order":1,"disp":true,"width":"6","collapse":false,"className":""},{"id":"b6152d595c55a32b","type":"ui_tab","name":"Pi_2_bleSPEAKER","icon":"dashboard","disabled":false,"hidden":false}]

The function node :

  1. msg.payload = encodeURIComponent(msg.payload.trim());// replace spaces with %20 for url GET REQUEST
  2. msg.url ="https://translate.google.com/translate_tts?ie=UTF-8&client=tw-ob&tl=en&q="+msg.payload;
  3. msg.payload = "'"+msg.url+"'";// need enclose REQUEST in quotes
  4. return msg;

The Exec node:
image

Thanks PdeJ.
Your solution seems very complicated to do something relatively simple, I was hoping for something a little easier and more simple. I cant really use it as my Raspberry Pi and Alexa device are too far away from each other to achieve a stable blue tooth connection.
Thanks for your suggestion anyway.

A bit like this

Maybe I'm being too simplistic.

The sonoff skill is under ewelink i think, but as you have mqtt that would not be needed. You will have to use blue print or an alexa routine so you can catch the correct phrase and avoid alexa saying "i don't understand that", You may be able to use node-red-contrib-vitual-smart as a temp trigger

there is no database involved in blueprint or routines.

Its easy to do - but you need a way to know when the request has been made for temperature.
All the options have already been sugested.
To keep it simple without needing any other accounts, skills or nodes, then using the Q&A blueprint option is the best bet.
It is a very simple way to allow you to ask Alexa any question you setup and relpy with a mesage of your choosing. Then all you need to do is listen for this response and use that to trigger whatever actions you want.

Thanks for the responses chaps. I try again tomorrow.

To use Q&A

Go to blueprints
Login with your amazon account and click on custom Q&A
Click - make your own
Follow prompts to add several ways to ask the question eg "what is the living room temperature"

Then enter a response in the Alexa will say box - This is what Alexa will say when you ask the question, and is what you will be listening for to trigger the flow. So make it generic but specifc to this action. eg "I will just check"

If you want to add more questions later, then each response has to be different so you know which flow to trigger.

That is all that is required outside of Node-Red.

In NR add an Alexa Event node with command set to "device activity"

Whenever you ask Alexa anything this node will output the details. So use a switch or function node to check msg.payload.alexaResponse for the response you setup.

If it matches then trigger the response that you want.

If you get stuck let me know.

Sean

And of course, there is always the "Simon says" approach that needs no skills at all

You can easily increase the vocabulary by creating a routine in Alexa and associate it with the light or plug, which is what I do with the wemo emulator in node red, so that I can ask Alexa "what is the temperature in the study" and the emulator node triggers the flow for the response from the sensor as text which is then converted to speech and output by Alexa.

Thanks for info guy's. I've got the blueprint side of things working but now I'm trying to get Alexa to say the temperature, which is a number (from MQTT data). I've noticed that using the Alexa routine node, the payload has to be in text (string) format before it can be spoken. If I inject a number it comes up with invalid sequence error. So how can I get Alexa to speak a number? Is there some kind of conversion necessary to go from number to text?
Thanks for your patience.

Use a change node with a JSONata $string() function:
Screenshot-31

try something like this - just change the number to your value eg flow.temp or where ever you store the actual temp and setup alexa node for your account and device

[{"id":"c04df06e9a03e5dc","type":"inject","z":"5f089500.98b45c","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payloadType":"date","x":1160,"y":420,"wires":[["2405b210424bd9fb"]]},{"id":"2405b210424bd9fb","type":"function","z":"5f089500.98b45c","name":"","func":"msg.payload=\"The lounge temperature is \" + 23 \nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1310,"y":420,"wires":[["d8b275f2b92b9d8d"]]},{"id":"d8b275f2b92b9d8d","type":"alexa-remote-routine","z":"5f089500.98b45c","name":"","account":"a6b62444.7794c8","routineNode":{"type":"speak","payload":{"type":"regular","text":{"type":"msg","value":"payload"},"devices":["G0911B05925316LT"]}},"x":1480,"y":420,"wires":[[]]},{"id":"a6b62444.7794c8","type":"alexa-remote-account","name":"","authMethod":"proxy","proxyOwnIp":"localhost","proxyPort":"3456","cookieFile":".node-red/alexa.txt","refreshInterval":"1","alexaServiceHost":"alexa.amazon.co.uk","amazonPage":"amazon.co.uk","acceptLanguage":"en-UK","onKeywordInLanguage":"","userAgent":"","useWsMqtt":"on","autoInit":"on"}]

My Alexa does not care if the number is "24" or "twenty four" as long as it is sent a string. try something like this
a number is injected, the change node concatenates it in the reply string converting the number to a string at same time.
e.g.

[{"id":"c04df06e9a03e5dc","type":"inject","z":"c791cbc0.84f648","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"20","payloadType":"num","x":230,"y":1760,"wires":[["bab69827.23e41"]]},{"id":"bab69827.23e41","type":"change","z":"c791cbc0.84f648","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"\"the temperature is \" & $$.payload & \" degrees celcius\"","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":360,"y":1700,"wires":[["d8b275f2b92b9d8d"]]},{"id":"d8b275f2b92b9d8d","type":"alexa-remote-routine","z":"c791cbc0.84f648","name":"","account":"c8738129.d902c","routineNode":{"type":"speak","payload":{"type":"regular","text":{"type":"msg","value":"payload"},"devices":["G090LF1182850C6D"]}},"x":570,"y":1760,"wires":[[]]},{"id":"c8738129.d902c","type":"alexa-remote-account","name":"alexa remote 2","authMethod":"proxy","proxyOwnIp":"localhost","proxyPort":"3456","cookieFile":"","refreshInterval":"14","alexaServiceHost":"layla.amazon.co.uk","amazonPage":"amazon.co.uk","acceptLanguage":"en-GB","userAgent":"","useWsMqtt":"on","autoInit":"off"}]

Well another day and a bit closer thanks to everyone's suggestions. As can be seen in the screen grab of my flow, I have Alexa listening and responding to requests for room temperatures using Blueprints. I have simulated a numerical input from an inject node and changed it to a string which is then stored in the numeric dashboard node (I'm sure there must be a better storage place for this information). All I need to do now is somehow combine the two sections to allow Alexa to speak the the response and add the string temperature value to the end of her message. Please for give my ignorance. Any help will be appreciated.

Here'e what I have in a function node to format data about one of my Raspberry Pi(es) and embed it in a message for Alexa. I tend to retain values I receive from a MQTT-In node in flow variables (using flow.set) so I can use them later. You'll have to alter the flow.get and/or msg.payload references for your situation.

var hostname = flow.get("hostname");
var ip_address = flow.get("ip_address");
var cpu_temperature = flow.get("cpu_temperature");

var message = "<break time='0.25s'/> Here's your report on your raspberry pie<break time='0.5s'/>";
    
message += "hostname is <break time='0.1s'/>"+hostname+ "<break time='0.25s'/>";
message += "IP address is <break time='0.1s'/>"+ip_address+ "<break time='0.25s'/>";
message += "CPU core temperature is <break time='0.1s'/>"+cpu_temperature+ "degrees sea <break time='0.25s'/>";

// This the footer for the message
message += "<break time='0.75s'/> that's the end of the report";

msg.payload = message;
return msg;