Hello everyone!
Just solved one of my major problems and thought to share.
THIS WILL ONLY WORK IF YOU’RE STREAMING!
Setup:
I have only simple media_players (1 Kodi, 1 mpd with snapcast and 3 snapcast clients). No google home devices to use broadcast. Kodi is usually turned off unless playing a movie or something and it’s set on a pc, so I don’t use it for TTS as it’s no point. MPD with snapcast on the other hand is perfect for the job since it’s always on. When it’s playing music, it’s from a web radio, meaning it’s a stream.
The problem is that when MPD streamed radio and I used the TTS service, it stopped the stream, played the TTS and then, silence! That was frustrating!
So along searching and getting replies on how to keep the stream and restart it(thanks everyone who helped!), I eventually figured it out.
Steps:
First of all, install hass-variables from here:
Then we go to configuration.yaml and declare our variables:
variable:
mpdstream:
value: 0
attributes:
icon: mdi:volume-high
mpdcheck:
value: 0
ttssay:
value: 0
mpdstream is the variable where we will store our stream url
mpdcheck is a variable to check if the media_player was previously streaming. If not, there’s no point to start playing radio!
ttssay is the variable where we will store our message. I didn’t use it at first, but I have at least 3 automations using this tts with radio and it was no point to flood the automation.yaml with code not needed. You’ll understand later.
Moving on to automation.yaml:
- id: Overtemp
alias: Suggest options when temp is too high
trigger:
- platform: numeric_state
entity_id: sensor.0x00158d00036b744d_temperature
above: 29.00
for:
minutes: 2
condition:
condition: and
conditions:
- condition: state
entity_id: group.all_devices
state: home
action:
- service: variable.set_variable
data:
variable: ttssay
value: 'Temperature on living room is high. Turn on the A C'
- service: script.ttssay
This is just an example. You only care about the action part. This is where we store a random message to the variable ttssay. And we call the script ttssay.
Moving on to the last part, scripts.yaml:
ttssay:
alias: Say google commands
sequence:
- service: variable.set_variable
data:
variable: mpdcheck
value_template: >
{% if is_state('media_player.mpd', 'playing') %}
1
{% else %}
0
{% endif %}
- service: variable.set_variable
data_template:
variable: mpdstream
value: >
{% if is_state('variable.mpdcheck', '1') %}
{{ states.media_player.mpd.attributes.media_content_id }}
{% else %}
http://radio.1055rock.gr:30000/1055
{% endif %}
- service: tts.google_say
entity_id: media_player.mpd
data_template:
message: '{{ states.variable.ttssay.state }}'
language: 'en'
- delay: '00:00:07'
- service_template: >
{% if is_state('variable.mpdcheck', '1') %}
script.mpdrestore
{% else %}
script.mpdoff
{% endif %}
Ok this is where it gets somewhat tricky. Here we check at first if our media_player (media_player.mpd in my case) is playing and if yes, we store 1 to variable mpdcheck, if not we store 0.
Next one is for my flavor. Since I usually listen to a standard station and I have a button on the house that toggles the media_player, I want to have the stream ready at all times. I just hit turn on media_player.mpd and it starts this stream. But if the media_player was already playing another stream, it will store that instead.
So what this does is, if the media_player is playing now, store it’s stream to the variable mpdstream. If it’s not playing, store the stream http://radio.1055rock.gr:30000/1055 (or your personal flavor)
Next one is of course the tts! It will say whatever we stored on automations. This is very handy since you can have multiple automations with tts and you wont fill the yaml with useless code! The variable stores in whatever language, it doesn’t care! So in my case it’s Greek with Greek characters and it works correctly.
Next one is a delay that waits for the tts to finish before launching the stream to the media_player.
And last, we check again if the media_player was playing or not and we launch the appropriate script.
The last scripts are:
mpdrestore:
alias: Restore Stream from welcome home automation
sequence:
- service: media_extractor.play_media
data_template:
entity_id: media_player.mpd
media_content_id: >
{{ states.variable.mpdstream.state }}
media_content_type: "music"
mpdoff:
alias: Turn off MPD
sequence:
- service: media_extractor.play_media
data_template:
entity_id: media_player.mpd
media_content_id: >
{{ states.variable.mpdstream.state }}
media_content_type: "music"
- delay: '00:00:01'
- service: media_player.turn_off
data:
entity_id: media_player.mpd
Fist one I think is self explanatory. If the media_player was playing, we inject the stream it had and play it.
Second one is for what I mentioned earlier to my personal flavor. It’s a “bandage fix” that tries to play the “default” stream I use and then turn it off, so it will be always loaded when I hit the power on of the mpd. Luckily the mopidy doesn’t play immediately, more of “try to play 200ms of music, then stop, then after 500ms I play normally”. So with the delay I have, I only hear a 200ms sound and it stops. As long as it works, I don’t care.
If you have better solutions, please post!
Or refined code, all answers are welcome!