Hi, I am not sure if there is a more elegant way in achieving this, however I thought this might be useful for others too.
This script reduces coding overhead when writing automations. If you wish to call multiple services on multiple entities under particular conditions in an automation you can use this script.
For example: My presence detection automation is triggered on status change. Depending on the status I wish to execute various operations: e.g. when I leave, all my lights and my media player should be switched off, thus requiring multiple services and potentially multiple entities to be iterated.
Also, when I arrive I want certain lights to switch on and have a particular scene activated.
I did not find a way to pass multiple entities and services to multiline data_templates using multiple services.
The script works by separating service calls on entities by commas “,” and separating individual entities by vertical bars “|” . The first element defines the service to be called e.g.
homeassistant.turn_on al following elements are entities , all elements are separated by a “|” to call another service use a comma.
Have a look at the example that makes it more clear.
With this script all can be handled in a single easily readable automation:
Let me know if you find this useful, or if there is a more elegant way in achieving what I wanted to do.
Data format:
service1|entityA|entityB|entityC,
service2|entityX|entityY|entityZ
Here the automation code:
- alias: Tom presence status change
trigger:
- platform: state
entity_id: sensor.sensor_presence_tom
action:
- service: notify.notify_tom_telegram
data_template:
message: >
Toms status has changed to "{{ states.sensor.sensor_presence_tom.state }}"
- service: python_script.python_script_call_service_on_multiple_entities
data_template:
operations: >
{% set topic = states.sensor.sensor_presence_tom.state %}
{% if topic == 'Fort' %}
media_player.media_stop|media_player.spotify,
light.turn_off|group.all_lights|group.all_switches
{% elif topic == 'Gerade angekommen' %}
scene.turn_on|scene.comfortable|test,
homeassistant.turn_on|group.office
scene.turn_on|scene.comfortable
{% else %}
{% endif %}
This is the script:
#==================================================================================================
# python_scripts/python_script_call_service_on_multiple_entities.py
#==================================================================================================
#--------------------------------------------------------------------------------------------------
# Call multiple services on multiple entities in an automation template
# currently does not support additional payload such as color information or brightness
#--------------------------------------------------------------------------------------------------
"""
Data format: service1|entityA|entityB|entityC,
service2|entityX|entityY|entityZ
Example Usage:
- service: python_script.python_script_call_service_on_multiple_entities
data_template:
operations: >
{% set topic = states.sensor.sensor_presence_tom.state %}
{% if topic == 'Fort' %}
media_player.media_stop|media_player.spotify,
light.turn_off|group.all_lights|group.all_switches
{% elif topic == 'Gerade angekommen' %}
scene.turn_on|scene.comfortable|test,
homeassistant.turn_on|group.office
scene.turn_on|scene.comfortable
{% else %}
{% endif %}
"""
operations = data.get('operations')
if not operations:
logger.debug("Error, wrong data format or empty.")
else:
logger.debug("tasks {0} end".format(operations))
tasks = operations.replace("\n","").replace(" ","").split(",")
for task in tasks:
logger.warning("tasks {0}".format(tasks))
data = task.split("|")
operation = data[0].split(".")
service = operation[0]
action = operation[1]
if hass.services.has_service(service,action):
for entity in data[1:]:
if hass.states.get(entity) is not None:
logger.debug("Calling {0}.{1} on Entity {2}".format(service,action,entity))
hass.services.call(service, action, {"entity_id" : entity}, False)
else:
logger.warning("Could not find entity \"{0}\"".format(entity))
else:
logger.warning("Error: Service \"{0}\" not found".format(service))