TTS device: one piston interrupts another piston. Is there a way to prevent this?


#1

1) Give a description of the problem
I have two pistons driving the same TTS device. When the first triggers, I start hearing the TTS message. At times a second piston gets triggered with another TTS message which then interrupts the first … or sometimes the first never happens. Is there a way to prioritize these messages from different pistons? Or is there a way to serialize them?


#2

How about setting up a global variable, say @ttsPlaying = true while a piston is doing its thing, then setting that variable back to false after it’s done. Now you’ll have to include that variable in the condition to only play the TTS while it’s false. Have it retry again when @ttsPlaying is true.


#3

I’ve noticed similar behavior. I cannot speak for all TTS devices, but with Sonos, I feel like piston has no way of knowing if it is done with the message. I have a piston that give me a weather report each morning. Works great. I also have it remind me to bring an umbrella if the chance of rain is over 30%.

When I 1st set it up the umbrella reminder would often interrupt the weather report. I tried a few things, but ultimately ended up putting in a pause to get past that. Obviously that wont work in your situation. I guess the point of this long message is that I don’t think the variable would work. I think it would send the TTS message to the speaker, while the message was speaking the piston would continue on and set the variable back to false, but it would still be playing.

Sonos does have a status of playing, which might be good to check. Basically Pause at the end of the message, and then for each piston, don’t play TTS message if status is playing?


#4

You might consider using a single piston to manage all TTS then send the message in an argument as done over here. This setup can achieve your goal and also provides the benefit of standardizing how the message is played and previous media resumed.

The following example shows a piston that waits for an existing instance of itself to finish before doing its job. Note that the Parallelism setting is enabled to allow multiple instances of the piston to run at the same time, otherwise Execute Piston just clobbers any active execution. Just use a Wait after the TTS, either based on the length of the text or just a standard wait time that will avoid collisions. If the piston is executed again while it’s already speaking that second one will wait until the first has finished.

If you have a lot of messages going to TTS you will have issues with sequencing but this is probably a good start for the basic two messages at a time scenario.


#5

Thanks @ipaterson and @eibyer will try this out. I need to see how to use global variables. I have three TTS devised and thus, would want to pass which devices to activate for TTS and what the message is. Seems like this should be passed to the other piston and not stored in a global variable. I wouldn’t be wiping out another piston which is setting the global variable as well?


#6

Well, I tried to make one that supports multiple devices but it seems that the scheduling breaks once there are a few instances of the piston running. For example, if I send a message to the kitchen, another message to the kitchen, then a message to the bedroom the second one to the kitchen gets lost.

I would recommend having one copy of the original for each TTS device. There are no global variables, so nothing to conflict. Based on the behavior with this multi device test I would imagine that if you queue up several messages some will be lost.

Note that I changed the Task Scheduling Policy for the blocks that wait to allow multiple scheduled tasks but it didn’t fix the scheduling.