SONOS TTS Script

how are you actually using this in your automations? I use alexa via media_player to make my announcements such as people arriving home etc… I have multiple lines that it just choose one at random to then announce/speak.

I cannot see how to add the “curl” command in a script other than a “shell_command” which would mean I would loose the “random” announcements above as I would have to select a single shell_command.

Maybe I’m missing something, do you have any suggestions/examples of how you use.

:slight_smile:

I do not make automations in yaml (all of mine are in Node Red) so unfortunately I can’t give you much help with shell_command but could you use a template in the shell_command such as:

shell_command:
  speak_arrival: 'curl..... ?text={{ states('input_text.arrival_message') }}'

And then before calling the service, set input_text.arrival_message to a random choice?

I would however use https://www.home-assistant.io/components/rest_command/ instead as then you don’t have to worry about the security issues that arise from running shell commands on your instance. The examples section shows how to use templates which im sure can be used to set random messages.

I’m currently using the addon to play arrival messages such as “Welcome home, starting your music”. It’s also useful for random announcements / updates (For example I use sonos.set_option to automatically turn on night sound on my beam at a certain time (if anything is playing) and then announce that it has been turned on). Pretty easy in node red to do that logic but not sure how complex it is in yaml.

seem as its about time I started using Node Red, would appreciate if you could show any examples in it…guess this would be my first project! :slight_smile:

@partymike For example here’s a flow where pushing the inject button will play a message on the specified sonos device:

The node on the left is an “inject” node.
The node on the right is a “http request” node set to GET the url http://192.168.29.109:8349/api/speakText?playerId=RINCON_347E5C600F4E01400&volume=35&text=Welcome home, Starting your music

You’ll notice how I had to use the IP instead of hassio.local. I think Node Red has issues with local domain names.

Hi, I have tried your addon (Hassio) and everything looks OK, it installed OK, got the Auth message and so on, however no sound is coming from the speaker (Ikea Symfonisk Speaker)

Even the logs are OK:

request completed GET 200 /api/speakText?playerId=Sonos_---w&volume=95&text=Hello, do you want to go outside 415ms

The only thing that is different from your post is the my speaker has a very long name, and there is a point in the middle. My playerId has like 45 charecters, while yours is only about 25. Is there something special with the “playerId”?

@Litux Interesting… So your speaker id shows up on http://<your_ha_location>:8349/api/allClipCapableDevices correct?. I haven’t had a chance to play around with those speakers as I don’t have them but everything I have seen points to the fact they should work. Also be sure that you are using the speaker id and not the household id (which also appears on that page). Try a message with no spaces (e.x. Hello) too. If that works it could be a string url encoding issue. Also that volume is way too high if any of the steps above end up working. I’d drop that down to around 35.

EDIT: I looked at the documentation. I think you’re for sure accidentally using the sonos houshold id (starts with Sonos_) instead of an individual speaker id.

OK, that adress only replay with:

{
	"success": true,
	"households": {
		"Sonos_VaZf8dVYuS0Il7C91111111111.Lq1jWwFZdL41111111111": []
	}
}

I changed some number for security reasons.
As you can see only the househols ID is listed.
I have check for updates, but there none. I have also re-do the auth, I restarted the server…
Any ideas why the speaker is not detected?

@Litux Ah I should have read Sonos’ page more closely: https://developer.sonos.com/reference/control-api/audioclip/

They say:

It will also work on the SYMFONISK table lamp with WiFi speaker and SYMFONISK WiFi bookshelf speaker in the next software release

So I think you just have to wait until the next Sonos update happens. After that you’ll see more id’s appear inside that those []. You’ll want to use those

1 Like

Great! At least we (mostly you :slight_smile: )found an answer.
I can sit and wait… or continue with other projects…
Anyways, THANKS

1 Like

SYMFONISK now working

As is often the case, HA develops and scripts described by users no longer work due to syntactic changes. So here is a working version (Oct 2019) of the great script developed by @domlen and shared with us a couple of years ago.

test_tts:
  alias: Test for TTS
  sequence:
    - service: script.turn_on
      entity_id: script.say
      data:
        variables:
          where: 'office'
          what: 'Test.'


say:
  alias: Sonos Text To Speech
  sequence:
  - service: sonos.snapshot
    data_template:
      entity_id: "{{ 'media_player.' ~ where }}"
  - service: tts.google_translate_say
    data_template:
      entity_id: "{{ 'media_player.' ~ where }}"
      message: "{{ what }}"
  - delay:
      seconds: 1
  - delay: >-
      {% set duration = states.media_player[where].attributes.media_duration %}
      {% if duration > 0 %}
        {% set duration = duration - 1 %}
      {% endif %}
      {% set seconds = duration % 60 %}
      {% set minutes = (duration / 60)|int % 60 %}
      {% set hours = (duration / 3600)|int %}
      {{ [hours, minutes, seconds]|join(':') }}
  - service: sonos.restore
    data_template:
      entity_id: "{{ 'media_player.' ~ where }}"


3 Likes

entity_id: “{{ ‘media_player.’ ~ where }}”

Hey @ianadd, is the delay working as applied in your script calling different speakers via automations?

@Coolie1101, To be honest i did my testing on the old play:3 in my office and it behaved as expected, resuming after saying what i asked.
As you have asked, i will do some detailed testing. I will vary the length of what is said and do so on other speakers that i have. I will then report back.

Appreciate it.

For me I have to specify the media player, otherwise it throws an error when the script is activated.

delay: >- {% set duration = states.media_player.living_room.attributes.media_duration %}

Paste here your call to the script as well.

      - service: script.turn_on
        entity_id: script.sonos_tts
        data_template:
          variables:
            where: "living_room"
            what: some message

Ok, I have some feedback.
If I use my Sonos app to start music on a single speaker OR on my soundbar + two rear speakers for example then it works as intended.
If I ask google to play music on the same speakers then the script errors and the music does not resume. Well this seems fairly reasonable to me, though disappointing.
What is your experience, @Coolie1101 ??

As google can now play music to sonos speakers some head scratching is required, by someone more experienced than me, to see if a script can work that out and do something different.

Thanks for posting this! Works great for me!

Sorry for the delayed response, my reference was for the delay without specifying the entity, and I find the following to not work 100% of the time.

  - delay: >-
      {% set duration = state_attr('media_player.living_room','media_duration') %}
      {% if duration > 0 %}
        {% set duration = duration - 1 %}
      {% endif %}
      {% set seconds = duration % 60 %}
      {% set minutes = (duration / 60)|int % 60 %}
      {% set hours = (duration / 3600)|int %}
      {{ [hours, minutes, seconds]|join(':') }}
- delay: >-
      {% set duration = state_attr('media_player.' + where,'media_duration') %}
      {% if duration > 0 %}
        {% set duration = duration - 1 %}
      {% endif %}
      {% set seconds = (duration % 60)|int %}
      {% set minutes = (duration / 60)|int % 60 %}
      {% set hours = (duration / 3600)|int %}
      {{ [hours, minutes, seconds]|join(':') }}