Text To Speech (TTS) With Sonos - Creating Dynamic Messages

You got it !!

[quote=“parkerc, post:77, topic:173177”]Hi

Just change the value next to AV_DEV to your own Sonos device number e.g.

Local AV_DEV = 73

And then add the rest of the code, updating the temperature from 232 to 74 and then the Condition device numbers from 115 to ??? (What ever it is?)[/quote]

Good to see that you got it working. I spent some time figuring this out since I am not a programmer.
The thing that can be a bit confusing I guess is that in this code the weather condition and temperature is coming from two different devices. I use a real outdoor sensor to report the temperature.
The code is working perfect for me, and I use it every morning when I turn on the lights in my kitchen.

regards

@haavard

Yes, thanks!

So to use your own outdoor temp sensor. Did you just have to change the device number
Ie: what I have as 75 to the device number of your sensor ?

What do you want the code to read info from? Weather Plugin only?

local OutTemp = luup.variable_get("urn:upnp-org:serviceId:TemperatureSensor1","CurrentTemperature", 232) local currentCondition = luup.variable_get("urn:upnp-micasaverde-com:serviceId:Weather1", "Condition", 115)

115 is my device number for the Weather underground device.
232 is the device number for my local temperature sensor.

If you go into settings for the device and the advance part you will find the “CurrentTemperature” variable and the “Condition” variable

ok… Thats my observation, 232 is your temp sensor…

Thanks

It works great… Using the OSX TTS engine with the “siri” voice (Samantha)

How did you setup the plugin to work with osx tts?

Sent from my iPad using Tapatalk

I’m running Beta 3 that has the OSX_TTS support.

On the advanced tab just set the:

DefaultEngineTTS to OSX_TTS_SERVER

OSXTTSServerURL http://YOUR_MACS_IP:8080

and on your MAC install this:

http://wolfpaulus.com/jounal/mac/ttsserver/

and configure from your web browser: http://YOUR_MACS_IP:8080

Works perfect :wink:

Here is new piece of TTS code to provide you with a way to have random words spoken, that way each time you run it, it’s potentially different. I’ve taken bits and pieces from other posts, so I cannot take any credit…

[size=14pt]Play Random Words[/size]

[code]url = require(“socket.url”)

local SONOS = 5
local LS_SID = “urn:micasaverde-com:serviceId:Sonos1”
local TEMP_SID = “urn:upnp-org:serviceId:TemperatureSensor1”

local greetings = { "Hi, ", "Hello, ", "Whatcha, " }
local greeting = greetings[math.random(table.getn(greetings))], “RAID”

local messages = { "How Ya Doing! ", "Hope You’re Well! " }
local message = messages[math.random(table.getn(messages))], “RAID”

local introductions = { "My name is Vera! ", "This is your house talking, " }
local introduction = introductions[math.random(table.getn(messages))], “RAID”

local goodbyes = { “See Ya!”, “Adios!”, “Cheerrio,”, "Goodbye, ", "Later, ", "Bye, "}
local goodbye = goodbyes[math.random(table.getn(goodbyes))], “RAID”

local frase = greeting … message … introduction … goodbye

local benTemp = luup.variable_get(TEMP_SID,“CurrentTemperature”, 210)
local emmaTemp = luup.variable_get(TEMP_SID,“CurrentTemperature”, 211)

luup.call_action(LS_SID, “Say”, {Text = string.format("%s, %s, I just wanted to let you know that Ben’s room is at %s degrees, where as Emmers is at %s degrees, %s ", greeting, message, benTemp, emmaTemp, goodbye)}, SONOS)[/code]

Let me know what you think…

Here’s a bit of fun, but it can be used for an all zones announcement. Just change you say command to include the GroupZones details below.

[size=14pt]All Zones Message[/size]

(This one is out of respect to the UK TV show Red Dwarf)

[code]local SONOS = 5
local LS_SID = “urn:micasaverde-com:serviceId:Sonos1”

luup.call_action(LS_SID, “Say”, {Text="A-wooga! A-wooga! this is a test, A-wooga! A-wooga! this is a drill, A-wooga! A-wooga!.. No need to panic!! ", Language=“en”, GroupZones=“ALL”,Volume=30, SameVolumeForAll=“true”},SONOS)
[/code]

ParkerC,
thanks for the tip…

but what is the 5 in the SONOS variable, what this value set ?

[quote=“Piwtorak, post:90, topic:173177”]ParkerC,
thanks for the tip…

but what is the 5 in the SONOS variable, what this value set ?[/quote]
Looking at the script, it is the Device ID of the Sonos that will play the TTS

[size=14pt]Simon Says Game[/size]

A big thank you to Rex for helping me get this one done, I never would’ve got there myself, it’s all him…

[quote=“RexBeckett”]The trouble with random selection is that you can get repetition - which doesn’t work too well for Simon says. This version does not allow that to happen.

[code]local count = math.random(2,5)
local prms = string.format(“%d,%d”,count,0)
luup.call_delay(“simonSays”,1,prms)

function simonSays(sprms)
local SONOS = 105
local LS_SID = “urn:micasaverde-com:serviceId:Sonos1”
local scnt,slst = string.match(sprms,“(%d+),(%d+)”)
local cnt = tonumber(scnt)
local lst = tonumber(slst)
local says = {“put your hands on your head!”, “put your hands on your hips!”, “turn around!”, “sit down!”, “touch your nose!”, “stand on one leg!”, “Touch your toes!”}
local pick = math.random(1,table.maxn(says))
if pick == lst then
if pick == table.maxn(says) then
pick = pick - 1
else
pick = pick + 1
end
end
local thissay = says[pick]
if (cnt > 1) then thissay = “Simon says, " … thissay end
luup.call_action(LS_SID, “Say”, {Text = thissay}, SONOS)
cnt = cnt - 1
if cnt > 0 then
local parms = string.format(”%d,%d",cnt,pick)
luup.call_delay(“simonSays”,10,parms)
end
end[/code][/quote]

Now just to make the adult version.

Vera says, you’re a bad boy! :wink:

These programming ideas are awesome and I plan to implement al of them. right now i’m coding a time triggered event that will check all door and window sensors, then verbally report to me which ones are open around bed time. does anyone know of a way to store values from a previous run so I can make the system talk louder if the same sensors are still tripped? i’m assuming the code can handle arrays, right? the question is how to clear the arrays after a certain time so that the system starts anew the next evening?

Also, a question about the simon says code. What’s the best way to trigger this event to run on demand? can I create a virtual light switch that I can “turn on” from the dashboard, or better yet, my iphone Vera mobile app? Also, how can I stop the program from looping when i’m done with it?
thanks
Pasqual

does anyone know of a way to store values from a previous run so I can make the system talk louder if the same sensors are still tripped?

Just use a global variable (without a local tag). It will vanish after a restart so will return nil.

i'm assuming the code can handle arrays, right?

Lua is very comfortable with arrays.

the question is how to clear the arrays after a certain time so that the system starts anew the next evening?
You could have another scene scheduled to run at a certain time that cleared the global variable.
What's the best way to trigger this event to run on demand?

Just run the scene.

can I create a virtual light switch that I can "turn on" from the dashboard, or better yet, my iphone Vera mobile app?

Yes. You could use VirtualSwitch or MultiSwitch.

Also, how can I stop the program from looping when i'm done with it?

It stops automatically after saying the last phrase (without Simon says).

I know that this post may be moved out of this section for being off topic, but it does have much relevance to dynamic TTS messages using the Sonos Plugin, so I thought I’d start here. So I’m planning to start programming some LUA code in a scene that will do the following:

  1. Identify all door/window sensors and get their device IDs. I could hard code all my sensors into the script, but I think I can use the devices variable. I found this code in the Luup Lua extensions wiki page which seems to gather all attributes for attached devices. I can probably search for devices that are within a specific device type for my purposes:

for k, v in pairs(luup.devices) do
for k2, v2 in pairs(v) do
luup.log(“Device #” … k … “:” … k2 … “=” … tostring(v2))
end
end

  1. Loop through all the devices and check if any are tripped

  2. Generate a dynamic TTS message that either tells me that all windows/doors are closed, or identify the open ones by name using the device information gathered in step 1.

I think this is pretty straightforward, and could put it together in a few hours, but in the spirit of community, I realized that others may have already created such a script and would be willing to post it here for consumption. This is where I’m probably going to be told to make my request in a more generic programming forum.
Thanks
Pasqual

Hi @pasqualz

This thread is largely focussed on sharing the end product, rather than the journey - but this is a community so we all try and help where we can :slight_smile:

You might however be better served in the Programming section of the forum. However if it is a straight forward as you say, then please do post your code examples here, as I think it would be great to have some code that can more effectively scan all devices and report information via TTS.

[size=18pt]Door & Window Sensor Check and Annunciation[/size]
Ok, so it took more than “a few hours” but here it is!!! This script checks for all connected door/window sensors, announces how many there are and if any are open (tripped,) it tells you which ones. I need to do more tinkering with the speech strings to make them smoother and maybe a bit slower. I plan to have two scenes, one for upstairs sonos and one for downstairs. The variables should be self explanatory. Feel free to reply with questions, comments, improvements, etc.

– Door/Window sensor check and speech annotation by Pasqual Zottola
local vol = 50
local son = 27 --mast bdr =33, kitch=27
local devcnt = 0
local devno = 0
local numopen = 0
local isare = “is”
local opensensors = " "
luup.log(‘Commencing sensor device search loop’)
for deviceNo,d in pairs(luup.devices) do
if d.category_num == 4 then

  local tripped = luup.variable_get("urn:micasaverde-com:serviceId:SecuritySensor1", "Tripped", deviceNo) or "Nil"
  
  if (tripped == "1") then
     opensensors = opensensors .. ". " .. d.description
     --[[ This line will change to recording info to an array so sonos speaks only once.

luup.call_action(“urn:micasaverde-com:serviceId:Sonos1”, “Say”,
{Text=d.description … " is Open", Language=“en”, Volume=vol}, son)
–]]
– luup.log(d.description … " status was " … tripped)
numopen = numopen + 1
end
luup.log(d.description … ’ status:’ … tripped … ’ Dev #’ … deviceNo … ’ id:’ … d.id … ’ cat #:’ … d.category_num … ’ type:’ … d.device_type)
devcnt = devcnt + 1
end
end
if numopen == 0 then --If there are no sensors tripped, log and announce!
luup.log(‘There were ’ … devcnt … ’ door and window sensors found and all are closed’)
luup.call_action(“urn:micasaverde-com:serviceId:Sonos1”, “Say”, {Text=“There were " … devcnt … " door and window sensors found, and all are closed”, Language=“en”, Volume=vol}, son)

else --If there are any sensors tripped, log and announce!
if numopen > 1 then
isare = “are”
end
luup.log(‘There were ’ … devcnt … ’ door and window sensors found and ’ … numopen … " " … isare … ’ open’ … opensensors)
luup.call_action(“urn:micasaverde-com:serviceId:Sonos1”, “Say”, {Text=“There were " … devcnt … " sensors found and " … numopen … " " … isare … " open.” … opensensors, Language=“en”, Volume=vol}, son)

end

Nice, thanks so much for sharing,

As is, it will look for everything that uses that service, so for example it will also report the status of the Ping Sensor plugin and any motion sensors too e.g.

Ping Sensor status:0 Dev #9 id: cat #:4 type:urn:schemas-demo-ted-striker:device:PingSensor:1 _Motion Sensor status:1 Dev #246 id:30 cat #:4 type:urn:schemas-micasaverde-com:device:MotionSensor:1

Maybe you could consider an option in your code so you can specify a certain device type, at least that could exclude the Ping sensor being reported.

If you click the ‘#’ hash/number option on the tool bar, it will allow you to wrap your code up nicely with some HTML so it can stand out more