Service template calling scripts with mis-matched data

I have two long automations that are identical except for a single service in the middle.

These different services both have data passed to them, but not the same parameters.

Is there any way to do this? ‘Mismatched’ data is not allowed i.e. if I define all parameters and pass them all to both services it produces an error because neither service expect the same data.

The only way around this as far as I can tell is to call a script with all the data parameters and have that script then call the necessary service. (HA of won’t create a ‘mismatch’ error on the script receiving the ‘wrong’ data).

So to illustrate:

- alias: my_automation
  # My two automations have a different trigger
  trigger:
    # Trigger in automation 1
    - platform: mqtt
      topic: topic/first_trigger

    # Trigger in automation 2
    - platform: mqtt
      topic: topic/second_trigger

  action:

    #--- Some actions here ---#

    # This is the only service in the whole automation that is different
    # For example this...
    - service: tts_google_say
      data_template:
        my_boolean: "{{ input_boolean.my_boolean }}"

    # ...or this
    - service: media_player.play_media
      data_template:
        my_input_text: "{{ input_boolean.my_input_text }}"

    # And I can't do this to combine them in one automation
    - service_template: >
      {% if trigger.topic == 'topic/first_trigger' %}
        tts_google_say
      {% else %}
        media_player.play_media
      {% endif %}
      data_template:
        my_boolean: "{{ input_boolean.my_boolean }}"
        my_input_text: "{{ input_boolean.my_input_text }}"

    #--- Loads more actions ---#

(I know those service calls aren’t consistent with the data, it is just a very simplified example.)

I’m not sure if I understand correctly, but couldn’t you just use a service_template and then define the service to use based on the data received?

Yes, that is what I wanted to do but both services take different data parameters and HA checks that the passed parameters match those the service expects to receive. Unless the service is a script in which case it doesn’t know what the called script is expecting.

I call a script and do it that way but then I’d need to move everything in the automation that comes after the service_template into another script as well. Not a big deal but I just wanted to make sure there wasn’t another, cleaner way to do this that I didn’t know about.

I still don’t get it :upside_down_face: You should be able to adjust your data_template accordingly.
I think you should be able to template the parameters as well.

I think it would be easier for me to understand if you post the two service calls you want with the parameters you want for them and the values that the parameters should have.

Ok,

Here are the triggers from the two automations:

Automation 1

    trigger: 
      - platform: mqtt
        topic: notifications/media_clip

Automation 2

    trigger: 
      - platform: mqtt
        topic: notifications/announcement

Automation 1 plays a media clip like this:

      - service: media_player.play_media
        data_template:
          entity_id: >
            media_player.kitchen
          media_content_id: >
            {{ trigger.payload }}
          media_content_type: 'music'

Automation 2 uses tts to make an announcement like this:

      - service_template: >
          tts.google_translate_say
        data_template:
          entity_id: >    
            media_player.kitchen
          message: >
            {{ trigger.payload }}

what I want to do is this:

  trigger: 
    - platform: mqtt
      topic: notifications/media_clip

    - platform: mqtt
      topic: notifications/announcement

  action:
    - service_template: >
        {% if trigger.payload == 'notifications/media_clip' %}
          media_player.play_media
        {% else %}
          tts.google_translate_say
        {% endif %}
      data_template:
        entity_id: >
          media_player.kitchen
        media_content_id: >
          {{ trigger.payload }}
        media_content_type: 'music'
        message: >
          {{ trigger.payload }}
my_boolean:
my_input_text:

Can you not just call the variable

my_variable:
In both scripts?

Ignore me, I’m sleepy and I misread what you were trying to do.

I’ll come back when I’m awake!

What you want to do is not really possible with the base automations. You can do it with a python_script or appdaemon.

Here’s the simplest way using 1 automation and 2 scripts with the built in automation engine.

  trigger: 
    - platform: mqtt
      topic: notifications/media_clip

    - platform: mqtt
      topic: notifications/announcement

  action:
    - service_template: 
        {% if trigger.topic == 'notifications/media_clip' %}
          script.play_media
        {% else %}
          script.annouce
        {% endif %}
      data_template:
        entity: media_player.kitchen
        payload: "{{ trigger.payload }}"

scripts

play_media:
  sequence:
    service: media_player.play_media
    data_template:
      entity_id: "{{ entity }}"
      media_content_id: "{{ payload }}"
      media_content_type: music
announce:
  sequence:
    service: tts.google_translate_say
    data_template:
      entity_id: "{{ entity }}"
      message: "{{ payload }}"

OR PYTHON

do_it.py

topic = data.get('topic')
entity_id = data.get('entity')
payload = data.get('payload')

if None not in [ topic, entity_id, payload ]:
    service_data = { 'entity_id': entity }
    if topic == notifications/media_clip:
        domain, service = 'media_player', 'play_media'
        service_data['media_content_id'] = payload
        service_data['media_content_type'] = 'music'
    else:
        domain, service = 'tts', 'google_translate_say'
        service_data['message'] = payload
    hass.services.call(domain, service, service_data)
  trigger: 
    - platform: mqtt
      topic: notifications/media_clip

    - platform: mqtt
      topic: notifications/announcement
  action:
  - service: python_script.do_it
    data_template:
      topic: "{{ trigger.topic }}"
      entity_id: media_player.kitchen
      payload: "{{ trigger.payload }}"

@petro Yes that is the only way I could see to do it (call separate scripts) and that would be fine but it brings the drawback that everything in the automation following those service calls also has to be moved into a third script because there is no 100% foolproof way to know when a script has finished.

I’m not sure doing it that way is any better than the duplicated code I have now.

I don’t use appdaemon but the python script looks interesting. Even if I don’t use it, it has taught me something.


Do all python scripts absolutely have to be in the python_scripts folder? Is there a way !include or redirect an any way. I use packages and it would make sense to be able to keep python scripts in the package.

And as an aside, do you know if there is particular reason HA was designed to check data parameters passed to ‘built-in’ services? After all it doesn’t (can’t) check when the service is script.

I believe they all have to be in the python_scripts folder. I don’t know if include will work. I don’t use them. So my knowledge is just the API and some use cases.

I believe it’s just the way it was coded. It would be nice if you could just pass a bunch of random crap.

Yes, especially when the crap isn’t random :slight_smile: