Help Trouble setting up TTS via script to play using multiple sonoses

Hi,

I am very new to HASS and I am hoping this is the right place to ask.

What I would like to be able to do is to call a script with a message and it would use TTS to speak it on multiple sonos devices.

Idea

My automation:

- alias: test speaking  'test'
  trigger:
    - platform: time
      at: '21:41:00'
  action:
    - service: script.sonos_say
      data:
        sonos_entity: sonoses
          - media_player.living_room
          - media_player.master_bedroom
          - media_player.theater
        volume: 0.5
        message: 'TTS test'
        delay: '00:00:05'

My script:

sonos_say:
    alias: "Sonos TTS script"
    sequence:
      - service: media_player.sonos_snapshot
        data_template:
          entity_id: "{{ sonos_entity|default('media_player.living_room') }}"
      - service: media_player.sonos_unjoin
        data_template:
          entity_id: "{{ sonos_entity|default('media_player.living_room') }}"
      - service: media_player.volume_set
        data_template:
          entity_id: "{{ sonos_entity|default('media_player.living_room') }}"
          volume_level: "{{ volume|default(0.5) }}"
      - service: tts.google_say
        data_template:
          entity_id: "{{ sonos_entity|default('media_player.living_room') }}"
          message: "{{ message }}"
      - delay: "{{ delay|default('00:00:00') }}"
      - wait_template: "{{ is_state(sonos_entity|default('media_player.living_room'), 'playing') }}"
        timeout: '00:00:05'
      - wait_template: "{{ not is_state(sonos_entity|default('media_player.living_room'), 'playing') }}"
        timeout: '00:02:00'
      - service: media_player.sonos_restore
        data_template:
          entity_id: "{{ sonos_entity|default('media_player.living_room') }}"

The main issue I am having is that nothing happens and I get an error in the logs:

2018-07-06 12:50:50 WARNING (SyncWorker_5) [homeassistant.components.media_player.sonos] Loading Sonos via platform config is deprecated.
2018-07-06 12:50:54 ERROR (MainThread) [homeassistant.core] Invalid service data for media_player.sonos_snapshot: Entity ID ['media_player.living_room' is an invalid entity id for dictionary value @ data['entity_id']. Got "['media_player.living_room', 'media_player.master_bedroom', 'media_player.theater']"
2018-07-06 12:50:54 ERROR (MainThread) [homeassistant.core] Invalid service data for media_player.sonos_unjoin: Entity ID ['media_player.living_room' is an invalid entity id for dictionary value @ data['entity_id']. Got "['media_player.living_room', 'media_player.master_bedroom', 'media_player.theater']"
2018-07-06 12:50:54 ERROR (MainThread) [homeassistant.core] Invalid service data for media_player.volume_set: Entity ID ['media_player.living_room' is an invalid entity id for dictionary value @ data['entity_id']. Got "['media_player.living_room', 'media_player.master_bedroom', 'media_player.theater']"
2018-07-06 12:50:54 ERROR (MainThread) [homeassistant.core] Invalid service data for tts.google_say: Entity ID ['media_player.living_room' is an invalid entity id for dictionary value @ data['entity_id']. Got "['media_player.living_room', 'media_player.master_bedroom', 'media_player.theater']"

I would love to be able to pass an array or a group to a script in some way.

Does anyone have any suggestions?

1 Like

I think the problem is that when you use the variable sonos_entity (which is an array) in a template (which you have to do) it turns into a string. So [a, b, c] turns into "[a, b, c]", which of course, is no longer an array.

However, some things that can take an array of entity_id’s will also take a string of comma separated entity_id’s. So, you could try this:

- alias: test speaking  'test'
  trigger:
    - platform: time
      at: '21:41:00'
  action:
    - service: script.sonos_say
      data:
        sonos_entity: media_player.living_room, media_player.master_bedroom, media_player.theater
        volume: 0.5
        message: 'TTS test'
        delay: '00:00:05'

Thank you! This works perfectly!
yaml with jinja is annoying to say the least :slight_smile: I had much less trouble getting used to Ansible!

2 Likes

I suspect this would have worked, too.

I tried passing a group before asking for help in this thread, and it didn’t work. Maybe I was doing something wrong. Would you be able to post an example code so I could learn?

@pnbruckner How do I set a dynamic delay based on the media duration?, will the template below work?

  - delay: >-
      {% set duration = states.[sonos_entity]|default('media_player.living_room').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(':') }}

If you’re asking about a delay step in an automation action or a script, it does accept a template. If the template returns a single number, it will be interpreted as seconds.

I don’t think this is correct, though:

      {% set duration = states.[sonos_entity]|default('media_player.living_room').attributes.media_duration %}

If sonos_entity is an entity_id, then this should work:

  - delay: >
      {% set duration = state_attr(sonos_entity|default('media_player.living_room'), 'media_duration') %}
      {% if duration > 1 %}
        {% set duration = duration - 1 %}
      {% endif %}
      {{ duration }}

sonos_entity is not an entity itself, but specified in the automation and reflected in script as in OP.

From Script:
entity_id: “{{ sonos_entity|default(‘media_player.living_room’) }}”

In Automation:
sonos_entity: media_player.living_room, media_player.master_bedroom, media_player.theater

Yes, I know sonos_entity is not an entity itself. It’s a variable. My question was what does that variable contain. And, yes, I’m aware of the code in the OP, but that doesn’t mean you’re using it as-is.

If sonos_entity does indeed contain a comma separated list of multiple entity_id’s, then what I suggest would not work. But in that case, which entity’s media_duration attribute would you want to use? And if it’s not a comma separated listed of entity_id’s, then you’ll need to be specific about that.

So do you still need help at this point, and if so, can you be a bit more specific about what you’re looking for?

Makes sense, since “media_player.living_room” is set as the default and used in all automations, I can always specify the entity, thanks.

Just to be clear, are you saying, if the entities are specified as a list in the automation, your template will NOT work?

What do you think? I.e., what do you think this would do:

state_attr('media_player.living_room, media_player.master_bedroom, media_player.theater', 'media_duration')

If you can’t answer that question then maybe you need to do some reading of the docs, specifically Templating.

Sure, thanks for your help.

This post was VERY helpful! Thanks!